5

У меня есть длинный список URL на моем собственном веб-сайте, указанный в отдельном текстовом файле с возвратом каретки. Так, например:

  • Http:/www.mysite.com/url1.html
  • Http:/www.mysite.com/url2.html
  • Http:/www.mysite.com/url3.html

Мне нужно создать несколько параллельных виджетов, чтобы дважды щелкнуть по каждому URL, проверить и получить определенный заголовок, а затем сохранить результаты в массиве, который я хочу вывести в хороший отчет.

У меня есть часть того, что я хочу, используя следующую команду xargs:

xargs -x -P 20 -n 1 wget --server-response -q -O - --delete-after<./urls.txt 2>&1 | grep Caching

Вопрос в том, как выполнить эту команду дважды и сохранить следующее:

  1. Попадание URL
  2. 1-й результат grep против заголовка Caching
  3. 2-й результат grep против заголовка Caching

Таким образом, вывод должен выглядеть примерно так:

=====================================================
http:/www.mysite.com/url1.html
=====================================================
First Hit: Caching: MISS
Second Hit: Caching: HIT

=====================================================
http:/www.mysite.com/url2.html
=====================================================
First Hit: Caching: MISS
Second Hit: Caching: HIT

И так далее.

Порядок появления URL-адресов не обязательно должен вызывать беспокойство, если заголовки связаны с URL-адресом.

Из-за количества URL-адресов мне нужно использовать несколько URL-адресов параллельно, а не последовательно, иначе это займет слишком много времени.

Хитрость в том, как получить несколько параллельных виджетов И сохранить результаты осмысленным образом. Я не женат на использовании массива, если есть более логичный способ сделать это (возможно, запись в файл журнала?)

Есть ли у Баш-гуру какие-нибудь предложения относительно того, как мне поступить?

3 ответа3

3

Создайте небольшой скрипт, который делает правильные вещи, учитывая один URL (на основе кода Тердона):

#!/bin/bash

url=$1
echo "=======================================";
echo "$url"
echo "=======================================";
echo -n "First Hit: Caching: ";
wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
if [ $? == 0 ]; then echo HIT; else echo MISS; fi;
echo -n "Second Hit: Caching: ";      
wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
if [ $? == 0 ]; then echo HIT; else echo MISS; fi; echo "";

Затем запустите этот скрипт параллельно (скажем, 500 заданий одновременно), используя GNU Parallel:

cat urls.txt | parallel -j500 my_script

GNU Parallel гарантирует, что выходные данные двух процессов никогда не будут смешаны - гарантия xargs не дает.

Вы можете найти больше информации о GNU Parallel по адресу: http://www.gnu.org/s/parallel/

Вы можете установить GNU Parallel всего за 10 секунд с помощью:

wget -O - pi.dk/3 | sh 

Посмотрите вступительное видео на http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

0

Я предполагаю, что ваш файл - новая строка, а не разделенный переводом каретки, потому что команда, которую вы даете, не будет работать с \r разделенным файлом.

Если файл используется \r вместо \n для линейных окончаний, изменить его с помощью \n запустив это:

perl -i -pe 's/\r/\n/g' urls.txt 

Если вы используете окончания строки в стиле Windows (\r\n), используйте это:

perl -i -pe 's/\r//g' urls.txt 

Теперь, когда у вас есть файл в форме Unix, если вы не против того, чтобы ваши задания не выполнялись параллельно, вы можете сделать что-то вроде этого:

while read url; do 
  echo "=======================================";
  echo "$url"
  echo "=======================================";
  echo -n "First Hit: Caching: ";
  wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
  if [ $? == 0 ]; then echo HIT; else echo MISS; fi;
  echo -n "Second Hit: Caching: ";      
  wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
  if [ $? == 0 ]; then echo HIT; else echo MISS; fi; echo "";
done < urls.txt

ОБНОВЛЕНИЕ в ответ на ваш комментарий:

Если у вас есть 22 000 URL, я действительно могу понять, почему вы хотите делать это параллельно. Вы можете попробовать создать файлы tmp:

(while read url; do 
 ( 
  echo "=======================================";
  echo "$url"
  echo "=======================================";
  echo -n "First Hit: Caching: ";
  wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
  if [ $? == 0 ]; then echo HIT; else echo MISS; fi;
  echo -n "Second Hit: Caching: ";      
  wget --server-response -q -O - $url 2>&1 | grep Caching >/dev/null
  if [ $? == 0 ]; then echo HIT; else echo MISS; fi; 
  echo ""; ) > `mktemp urltmpXXX` 2>/dev/null&
done < urls.txt )

Там запущены две субоболочки, первая (while ... < urls.txt) как раз для подавления сообщений о завершении. Второй ( ( echo "=== ... ) > mktemp urltmpXXX ) предназначен для сбора всех выходных данных для данного URL-адреса в один файл.

Приведенный выше сценарий создаст 22 000 файлов tmp с именем urltmpXXX где XXX заменяется на столько же случайных символов. Поскольку у всех файлов tmp будет 6 строк текста, когда все они будут закончены, вы можете отслеживать (и при желании удалять файлы) следующую команду:

b=`awk 'END{print NR}' urls.txt`; 
while true; do 
 a=`wc -l urltmp* | grep total | awk '{print $1}'`;     
 if [ $a == $((6 * $b)) ]; then cat urltmp* > urls.out; break; 
  else sleep 1; fi; 
done

Теперь другая проблема состоит в том, что это запустит 22000 рабочих мест одновременно. В зависимости от вашей системы это может быть или не быть проблемой. Одним из способов решения этой проблемы является split входного файла и последующее выполнение вышеуказанного цикла для каждого файла.

0

Одним из тривиальных решений было бы записать вывод каждой из команд wget в отдельный файл и использовать cat для последующего их слияния.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .