webdevqa.jp.net

Bashの並列wget

私はウェブサイトから比較的小さなページの束を取得していますが、Bashでそれをどうにかして並行して行うことができるかどうか疑問に思っていました。現在、私のコードはこのように見えますが、実行に時間がかかります(接続の遅延が私を遅くしていると思います)。

for i in {1..42}
do
    wget "https://www.example.com/page$i.html"
done

Xargsを使用したことを聞いたことがありますが、それについては何も知らず、manページは非常に混乱しています。何か案は?これを並行して行うことも可能ですか?これを攻撃する別の方法はありますか?

68

&または-bを使用してwgetをバックグラウンドにプッシュするよりも、xargsを使用して同じ効果を得ることができます。

利点は、xargs適切に同期を追加の作業なしで行うことです。つまり、ダウンロードしたファイルに安全にアクセスできます(エラーが発生しないと仮定)。 xargsが終了すると、すべてのダウンロードが完了(または失敗)し、終了コードですべてがうまくいったかどうかがわかります。これは、sleepでビジー待機し、手動で完了をテストするよりもはるかに望ましい方法です。

URL_LISTがすべてのURLを含む変数であると仮定すると(OPの例ではループで構築できますが、手動で生成されたリストでも可能です)、これを実行します:

echo $URL_LIST | xargs -n 1 -P 8 wget -q

一度に1つの引数(-n 1)をwgetに渡し、一度に最大8つの並列wgetプロセス(-P 8)を実行します。 xargは、最後に生成されたプロセスが終了した後に戻ります。これはまさに知りたいことです。余分なトリックは必要ありません。

私が選択した8つの並列ダウンロードの「魔法の数」は決まったものではありませんが、おそらく妥協案です。一連のダウンロードを「最大化する」には2つの要素があります。

1つは「ケーブル」を埋める、つまり利用可能な帯域幅を利用することです。 「通常の」状態(サーバーがクライアントよりも帯域幅が大きい)を想定すると、これは既に1つまたは多くても2つのダウンロードの場合です。問題でより多くの接続をスローすると、パケットがドロップされ、TCP輻輳制御が開始され、および[〜#〜] n [〜#〜]のみが発生します。 漸近的に1/N帯域幅でダウンロードし、同じ正味効果(ドロップされたパケットを差し引いて、ウィンドウサイズを引いたもの)パケットがドロップされることは、IPネットワークで発生する通常の現象であり、これが輻輳制御の動作方法(単一の接続であっても)であり、通常、影響は実質的にゼロになります。接続はこの効果を増幅するので、目立って来る可能性があります。

2番目の要因は、接続の確立と要求の処理です。ここでは、飛行中にいくつかの余分な接続があると、本当に役立ちます直面する問題は、2つの往復の遅延(通常、同じ地理的エリア内で20-40ミリ秒、大陸間で200-300ミリ秒)に加えて、サーバーが実際に要求を処理して応答をプッシュするのに必要な奇数1から2ミリ秒ですソケットに。これは多くの時間自体ではありませんが、数百/千のリクエストを掛けると、すぐに加算されます。
6から12個のリクエストを処理中に送信すると、このレイテンシのほとんどまたはすべてが隠されます(まだ存在しますが、重複するため、要約されません!)。同時に、同時接続数が少ない場合でも、過度の輻輳を引き起こしたり、サーバーに新しいプロセスをフォークさせたりするなどの悪影響はありません。

172
Damon

バックグラウンドでジョブを実行するだけではスケーラブルなソリューションではありません。10000個のURLをフェッチする場合、おそらく少数(100個など)を並列にフェッチするだけです。 GNUそのために並列が行われます:

seq 10000 | parallel -j100 wget https://www.example.com/page{}.html

その他の例については、manページを参照してください。 http://www.gnu.org/software/parallel/man.html#example__download_10_images_for_each_of_the_past_30_days

57
Ole Tange

-bオプションを使用できます:

wget -b "https://www.example.com/page$i.html"

ログファイルが必要ない場合は、-o /dev/nullオプションを追加します。

-o FILEログメッセージをFILEに保存します。
9
uzsolt

アンパサンドをコマンドに追加すると、バックグラウンドで実行されます

for i in {1..42}
do
    wget "https://www.example.com/page$i.html" &
done
7
Jack Edmonds

Wgetのバージョン2は、複数の接続を実装しているようです。 githubのプロジェクトのリンク: https://github.com/rockdaboot/wget2

1
user9869932