bashスクリプトで何千ものcurlバックグラウンドプロセスを並行して実行する


14

次のbashスクリプトでcurlバックグラウンドプロセスを実行しています。

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コマンドを使用してメモリ消費とCPUを追跡しますが、それらは限界からはかけ離れています。

ps aux | grep curl | wc -l現在のcurlプロセスの数を数えるために使用しています。この数は2〜4千まで急速に増加し、その後連続的に減少し始めます。

パイピングcurlを介して単純な解析をawk(curl | awk > output)に追加すると、curlプロセスの数は1〜2千に増え、その後20〜30に減少します。

プロセスの数がそれほど劇的に減少するのはなぜですか?このアーキテクチャの境界はどこですか?


2
おそらく、最大実行プロセス数または最大オープンソケットの制限の1つに達しています。ulimitこれらの制限の一部が表示されます。
HBruijn

6
またparallel(1)、そのようなタスクに使用することをお勧めします:manpages.debian.org/cgi-bin/…–
zhenech

試行start=$SECONDSしてend=$SECONDS-シェル変数との潜在的な名前の衝突を回避するために、習慣によって小文字または大文字と小文字が混在する変数名を使用してください。ただし、実際には、各プロセスの開始間隔がますます長くなっています。プロセスがバックグラウンドで実行されているため、ダウンロードにかかった時間はわかりません(start1回だけ計算されます)。Bashでは(( diff = end - start ))、ドル記号をドロップして、間隔をより柔軟にすることができます。pgrep持っている場合に使用します。
追って通知があるまで一時停止します。

HBruijnに同意します。プロセス数を2倍にしたときに(を追加してawk)プロセス数が半分になることに注意してください。
追って通知があるまで一時停止します。

@zhenech @HBrujin起動parallelしましたが、ファイルハンドルのシステム制限により、500の並列タスクしか実行できないと言われています。私はlimits.confで制限を上げましたが、5000個のsimulaneusジョブを実行しようとすると、parallel perlスクリプトはすべて32MBを消費するため、開始前でもすぐにすべてのメモリ(49GB)を消費します。
zavg

回答:


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: {}'。チュートリアルを1時間歩きます。あなたのコマンドラインはそれのためにあなたを愛します:man parallel_tutorial
Ole

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

(編集:( 編集:OSの制限に関する日付の厳しいアサーションを取り除き、欠落しているものを追加します。)echocurl
wait


実際、OSはこれをうまく処理できます。これはTCPの制限です。どんなに特別なOSでも、それを回避することはできません。しかし、OPの4k接続は64k(または一部のディストリビューションのデフォルトの32k)の近くにはありません。
Patrick

@パトリック大丈夫、私はその部分を取り除いた、それは取り返しのつかない設計の制限で冗長ですが、7日のzavgのコメントを見てください
jthill
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.