Многократное чтение из txt-файла в bash (параллельная обработка)

1469
user7423959

Вот простой bash-скрипт для кода статуса HTTP

while read url do urlstatus=$(curl -o /dev/null --silent --head --write-out '%' "$" --max-time 5 ) echo "$url $urlstatus" >> urlstatus.txt done < $1 

Я читаю URL из текстового файла, но он обрабатывает только по одному за раз, что занимает слишком много времени, параллельный GNU и xargs также обрабатывают одну строку за раз (проверено)

Как обработать одновременный URL для обработки, чтобы улучшить время? Другими словами, многопоточность URL-файла, а не команд bash (что делают GNU параллельно и xargs)

как ответ от пользователя, этот код работает нормально, за исключением того, что он не обрабатывает последний URL

urlstatus=$(curl -o /dev/null --silent --head --write-out '%' "$" --max-time 5 ) && echo "$url $urlstatus" >> urlstatus.txt & 

может быть добавление ждать помощи ,, какие-либо предложения

3
You could look into sub processes for this. That would mean you could start an individual shell/thread for each `curl`. As for your solution using xargs/parallel it would be worth it to include it since you might have just done something wrong. Just reading the file should be fast enough (except if it's really large) but the waiting for the answer is probably whats your problem. Seth 7 лет назад 0
фактически после использования параллельного интерфейса он обрабатывает один URL-адрес так же, как и обычное время выполнения сценария bash. user7423959 7 лет назад 0
Почему один URL-адрес будет быстрее? С одним URL-адресом вы можете выполнить все необходимые распараллеливания, это не будет быстрее. С другой стороны, с несколькими URL вы можете запросить набор URL одновременно. Таким образом, проблема могла заключаться в том, как вы называли / использовали параллели. Следовательно, было бы полезно указать, как вы на самом деле пытались его использовать. Seth 7 лет назад 0
вот пример --cat abc.txt | Параллельно -j100 --pipe /root/bash.sh abc.txt теперь у вас есть идея ,,,, и n1 также используется ,,, он обрабатывает один URL-адрес за раз, не занимая при этом одно и то же время. user7423959 7 лет назад 0

2 ответа на вопрос

3
me_alok

В bash вы можете использовать символ & для запуска программ в фоновом режиме. пример

for i in ; do echo $i>>numbers.txt & done; 

РЕДАКТИРОВАТЬ: Извините, но ответ на ваш вопрос в комментарии неверный, поэтому я просто отредактировал ответ. Предложения по коду

urlstatus=$(curl -o /dev/null --silent --head --write-out '%' "$" --max-time 5 ) && echo "$url $urlstatus" >> urlstatus.txt & 
Можете ли вы дать предложение по коду, так как добавление этого символа (&) не улучшает синхронизацию. user7423959 7 лет назад 0
Попробуйте это urlstatus = $ (curl -o / dev / null --silent --head --write-out '% ' "$ " --max-time 5) & me_alok 7 лет назад 0
уже пробовал, user7423959 7 лет назад 0
Это сработало для меня. ninja 7 лет назад 0
Работает, проверял перед редактированием ответа me_alok 7 лет назад 0
Ваш код работает нормально, но есть одна проблема - он не обрабатывает последние некоторые URL, может потребоваться добавить где-нибудь в коде ожидание, любое предложение по этому вопросу user7423959 7 лет назад 0
на самом деле он пропускает много URL ,,, только некоторые показаны user7423959 7 лет назад 0
добавление ожидания в конце файла также не работает user7423959 7 лет назад 0
There is no need to add a wait command in here unless you want to limit the number of threads and it should be inside the while loop. me_alok 7 лет назад 0
For missing url issue, what's the output in urlstatus.txt? Is it just the status code that's missing or the entire url and status? me_alok 7 лет назад 0
Отсутствуют все URL-адреса, чей код состояния 000 ,,,, это не проблема, я хочу управление потоком в этом скрипте, так как очень длинный текстовый файл зависает моя система на некоторое время (хотя и дает результаты) ,,,, любые предложения по добавлению потоков к этому коду user7423959 7 лет назад 0
Можете ли вы произвести пример ввода и вывода? me_alok 7 лет назад 0
Да, вывод правильно воспроизведет любые предложения по управлению потоками в этом сценарии user7423959 7 лет назад 0
Можете ли вы опубликовать пример вывода (как stdout, так и urlstatus.txt)? me_alok 7 лет назад 0
1. здесь находится входной файл http://s3.amazonaws.com/alexa-static/top-1m.csv.zip 2. я сохраняю ваш скрипт как bash.sh и выполняю как из терминала ./bash.sh top1m. TXT (разархивирование выше) 4. Затем он приводит к результатам в файле urlstatus.txt 5. Я хочу, чтобы контроль потока в этом скрипте (вы можете взять некоторые входные данные для тестирования в виде небольшого файла) 6. Есть гораздо больше файлов, так как это большой ... там как 100 ,,, 500 кб и т. д. не такие большие это ,,, 6. ваш ответ работает, я просто спрашиваю, возможно ли управление потоками user7423959 7 лет назад 0
Ну, многопоточность работает здесь, используйте команду top, чтобы увидеть это. Для контроля потока, дайте мне посмотреть, что я могу сделать me_alok 7 лет назад 0
1
Ole Tange

Параллельно GNU и xargs также обрабатывают одну строку за раз (проверено)

Можете ли вы привести пример этого? Если вы используете, -jто вы сможете запускать гораздо больше, чем один процесс одновременно.

Я бы написал это так:

doit() { url="$1" urlstatus=$(curl -o /dev/null --silent --head --write-out '%' "$" --max-time 5 ) echo "$url $urlstatus" } export -f doit cat input.txt | parallel -j0 -k doit 

На основании input.txt:

Input file is txt file and lines are separated as ABC.Com Bcd.Com Any.Google.Com Something like this www.google.com pi.dk 

Я получаю вывод:

Input file is txt file and lines are separated as 000 ABC.Com 301 Bcd.Com 301 Any.Google.Com 000 Something like this 000 www.google.com 302 pi.dk 200 

Который выглядит примерно так:

000 if domain does not exist 301/302 for redirection 200 for success 

Я должен сказать, что я немного удивлен, если введенные вами строки действительно являются частью ввода, который вы фактически используете. Ни один из этих доменов не существует, и доменные имена с пробелами, вероятно, никогда не будут существовать - никогда:

Input file is txt file and lines are separated as Any.Google.Com Something like this 

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

редактировать

Отладка, почему это не работает для вас.

Пожалуйста, не пишите скрипт, а запустите его прямо в терминале:

bash # press enter here to make sure you are running this in bash doit() { url="$1" urlstatus=$(curl -o /dev/null --silent --head --write-out '%' "$" --max-time 5 ) echo "$url $urlstatus" } export -f doit echo pi.dk | parallel -j0 -k doit 

Это должно дать:

pi.dk 200 
эй, у меня есть тот же код состояния 000, можете ли вы сказать мне, как вы выполняете свой скрипт из терминала, это может помочь user7423959 7 лет назад 0
I put the input lines above into the file `input.txt`. Then I run the exact lines that is written above. My shell is bash. Ole Tange 7 лет назад 0
i explain the whole process--- 1. i copied your bash script and saved it as bash.sh and giving execution permissions . 2. my input file is big file but i also tested on small 10 lines file---here is list www.yahoo.com ,www.google.com facebook.com amazon.com bing.com apple.com www.microsoft.com www.windows.com ,,,,,all seperated by lines and saved as top.txt 4. now then i go to terminal and type ./bash.sh top.txt 5. now it gives the result 000 in each 6. now can you assist me further where ia am wrong ,,,thanks user7423959 7 лет назад 0
Это отлично работает user7423959 7 лет назад 0