Выполнение тысяч фоновых процессов curl параллельно в bash-скрипте

14

Я запускаю тысячи фоновых процессов curl параллельно в следующем скрипте bash

START=$(date +%s)
for i in {1..100000}
do       
    curl -s "http://some_url_here/"$i  > $i.txt&
    END=$(date +%s)
    DIFF=$(( $END - $START ))
    echo "It took $DIFF seconds"
done

У меня 49Gb Corei7-920 выделенный сервер (не виртуальный).

Я отслеживаю потребление памяти и процессора через topкоманду, и они далеки от границ.

Я использую ps aux | grep curl | wc -lдля подсчета количества текущих процессов скручивания . Это число быстро увеличивается до 2-4 тысяч, а затем начинает непрерывно уменьшаться.

Если я добавлю простой анализ через piping curl в awk ( curl | awk > output), то число процессов curl возрастет до 1-2 тысяч, а затем уменьшится до 20-30 ...

Почему количество процессов так резко уменьшается? Где границы этой архитектуры?

zavg
источник
2
Вы, вероятно, достигли одного из пределов максимального количества запущенных процессов или максимального числа открытых сокетов. ulimitпокажет некоторые из этих ограничений.
HBruijn
6
Я также предложил бы использовать parallel(1)для таких задач: manpages.debian.org/cgi-bin/…
zhenech
Попробуйте start=$SECONDSи end=$SECONDS- и используйте имена переменных в нижнем или смешанном регистре по привычке, чтобы избежать возможного конфликта имен с переменными оболочки. Однако на самом деле вы получаете только постоянно увеличивающийся интервал времени запуска каждого процесса. Вы не получаете, сколько времени заняло скачивание, так как процесс идет в фоновом режиме (и startрассчитывается только один раз). В Bash вы можете (( diff = end - start ))сбросить знаки доллара и сделать интервалы более гибкими. Используйте, pgrepесли у вас есть.
Приостановлено до дальнейшего уведомления.
Я согласен с HBruijn. Обратите внимание, как количество ваших процессов уменьшается вдвое, когда вы удваиваете количество процессов (добавляя awk).
Приостановлено до дальнейшего уведомления.
@zhenech @HBrujin Я запустил, parallelи мне сказали, что я могу выполнить только 500 параллельных задач из-за системного ограничения файловых дескрипторов. Я поднял лимит в limit.conf, но теперь, когда я пытаюсь запустить 5000 заданий simulaneus, он мгновенно съедает всю мою память (49 Гб) еще до запуска, потому что каждый parallel скрипт perl съедает 32 Мб.
Завг

Ответы:

12

После вопроса строго:

mycurl() {
    START=$(date +%s)
    curl -s "http://some_url_here/"$1  > $1.txt
    END=$(date +%s)
    DIFF=$(( $END - $START ))
    echo "It took $DIFF seconds"
}
export -f mycurl

seq 100000 | parallel -j0 mycurl

Короче, если вам не нужен шаблонный текст вокруг времени:

seq 100000 | parallel -j0 --joblog log curl -s http://some_url_here/{} ">" {}.txt
cut -f 4 log

Если вы хотите запустить 1000 с параллельно, вы достигнете некоторых ограничений (например, файловых дескрипторов). Может помочь повышение ulimit -n или /etc/security/limits.conf.

Оле Танге
источник
И если я хочу параллельно запустить несколько команд, например, в версии с коротким ответом, как мне это сделать?
Гай Авраам
2
Цитировать это: seq 100 | parallel 'echo here is command 1: {}; echo here is command 2: {}'. Проведите час, прогуливаясь по учебнику. Ваша командная строка будет любить вас за это:man parallel_tutorial
Ole Tange
2
for i in {1..100000}

Всего 65536 портов. Дросселировать это.

for n in {1..100000..1000}; do   # start 100 fetch loops
        for i in `eval echo {$n..$((n+999))}`; do
                echo "club $i..."
                curl -s "http://some_url_here/"$i  > $i.txt
        done &
        wait
done

(edit: (edit: убрать строго устаревшее утверждение об ограничениях ОС и добавить недостающее )echocurl
wait

jthill
источник
На самом деле ОС может справиться с этим просто отлично. Это ограничение TCP. Ни одна ОС, какой бы особенной она ни была, не сможет ее обойти. Но 4K-соединения OP отнюдь не близки к 64К (или 32К по умолчанию в некоторых дистрибутивах)
Патрик
@ Патрик, хорошо, я взял эту часть, она избыточна с безвозвратным пределом дизайна, но посмотри на комментарий Завга 7-го.
jthill