使用xargs -P0

使用xargs -P0

私はURLファイルを読み込み、各URLのHTTPステータスコードを出力するDebianシステムにスクリプトを書いています。

...
while read url
do
    urlstatus=$(curl -H 'Cache-Control: no-cache' -o /dev/null --silent --head --insecure --write-out '%{http_code} ; %{redirect_url}' "$url")
    ...
done < $1

100個のURLを含むファイルには問題はありませんが、1000個を超えるURLを含む大きなファイルの場合、スクリプトは非常に遅くなります!

SOで見つけたいくつかの「ヒント」を試しました。 KeepAlive設定-H 'Keep-Alive: 500'、GoogleBotをユーザーエージェントとして定義、--user-agent 'Googlebot/2.1 (+http://www.google.com/bot.html)'接続タイムアウト定義などが--connect-timeout 1ありましたが、何もありません!

答え1

並列に実行するには、GNU Parallelを使用できます。

#!/usr/bin/env bash

file=$1

status_func () {
    local _url="${1:-/dev/stdin}"
    local _urlstatus
    _urlstatus=$(curl -H 'Cache-Control: no-cache' -o /dev/null --silent --head --insecure --write-out '%{http_code} ; %{redirect_url}' "$_url")
    printf 'Status: %s\n' "$_urlstatus"
}

export -f status_func

cat "$file" | parallel -j20 status_func

-j オプションは、最大同時ジョブ数を設定します。デフォルトはシステムのスレッド数ですが、最良の結果を得るにはこの数を調整する必要があります。

コマンドを関数(またはまったく別のスクリプト)に追加し、並列処理がそれを知るために関数をエクスポートする必要があることに注意してください。

コマンドをスタンドアロンスクリプトに配置するには、次のようにコマンドラインから実行できます。

cat "$file" | parallel -j20 ./my_script.sh

このスクリプトはstdinを介して送信されたURLのみを期待する必要があります。


また、GNU 並列処理を使用できない場合でも、複数のジョブを同時に実行したい場合は、そのジョブをバックグラウンドジョブとして実行できますが、同時プロセス数を制限したい可能性があります。これは次の方法で行うことができます。

#!/usr/bin/env bash

file=$1

max_bg_procs () {
    local max_number=$((0 + ${1:-0}))
    while :; do
        local current_number=$(jobs -pr | wc -l)
        if [[ $current_number -lt $max_number ]]; then
            break
        fi
        sleep 2
    done
}

status_func () {
    local _url="${1:-/dev/stdin}"
    local _urlstatus
    _urlstatus=$(curl -H 'Cache-Control: no-cache' -o /dev/null --silent --head --insecure --write-out '%{http_code} ; %{redirect_url}' "$_url")
    printf 'Status: %s\n' "$_urlstatus"
}

while IFS= read -rd url; do
    max_bg_procs 20
    status_func "$url" &
done < "$file"

答え2

使用xargs -P0

seq 100 | xargs -I@ echo 'https://example.com?@' > urls.txt
cat urls.txt | xargs -P0 -n1 curl

どのくらい早く?

いいえ-P0:

time sh -c 'cat urls.txt | xargs -n1 curl'
real    0m 59.79s
user    0m 1.64s
sys     0m 0.99s

そして-P0

time sh -c 'cat urls.txt | xargs -P0 -n1 curl'
real    0m 0.76s
user    0m 1.26s
sys     0m 0.82s

引用元man xargs:

-P最大プロセス

パラレルモード:一度に最大maxprocsユーティリティ呼び出しを実行します。 maxprocsが0に設定されている場合、xargsはできるだけ多くのプロセスを実行します。

答え3

使用-Z

ユースケースに応じて、別の潜在的な解決策は-Zフラグです。これは、複数のURLを指定しcurlたり、curl範囲を操作したりする特定の構文を指定して、カールにページ付けなどの操作を自動化させる場合に便利です。

このフラグのドキュメントは-Z次のとおりです。https://curl.se/docs/manpage.html#-Z

特定の範囲構文のドキュメントはcurl次の場所にあります。https://curl.se/docs/manpage.htmlそして^ F 'ワイルドカード'。

curl -Z $(cat urls.txt | xargs)

関連情報