GNU Parallel メーリング リストによると、これは GNU Parallel 固有の問題ではありません。ここで問題を投稿するよう提案されました。
私が受け取っているエラーは「壊れたパイプ」エラーですが、まずは問題の背景とこのエラーの原因を説明する必要があると思います。これは、GNU Parallel で「while read」ループを含む bash スクリプトを使用しようとすると発生します。
次のような基本的な bash スクリプトがあります。
#!/bin/bash
# linkcheck.sh
while read domain
do
host "$domain"
done
大きなリスト(たとえば 250 MB)をパイプで送信するとします。
cat urllist | ./linkcheck.sh
250 MB 相当の URL に対してホスト コマンドを実行すると、かなり時間がかかります。処理速度を上げるには、入力をパイプする前にチャンクに分割し、複数のジョブを並列で実行します。GNU Parallel は、これを実行できます。
cat urllist | parallel --pipe -j0 parallel ./linkcheck.sh {}
{} は、urllist の内容に 1 行ずつ置き換えられます。システムのデフォルト設定では、parallel のインスタンスごとに 500 程度のジョブを実行できると仮定します。この制限を回避するには、Parallel 自体を並列化します。
cat urllist | parallel -j10 --pipe parallel -j0 ./linkcheck.sh {}
これは約5000のジョブを実行します。また、残念なことに、「パイプが壊れています」というエラーも発生します。(bash FAQ)しかし、while read ループを削除し、{} に入力されたものから直接入力を取得すると、スクリプトは動作し始めます。例:
#!/bin/bash
# linkchecker.sh
domain="$1"
host "$1"
while read ループではなぜ動作しないのでしょうか? SIGPIPE 信号をオフにして「壊れたパイプ」メッセージを停止するだけで安全ですか、それともデータ破損などの副作用がありますか?
読んでくれてありがとう。
答え1
だからした
cat urllist | parallel --pipe -j0 parallel ./linkcheck.sh {}
正しく動作しますか?問題の一部は、2番目のを省略したことにあると思います--pipe
。
cat urllist | parallel -j10 --pipe parallel -j0- パイプ./linkcheck.sh {}
ところで、言う必要はありません
猫1ファイル|何らかのコマンド
これをいつでも変更することができます
何らかのコマンド<1ファイル
cat
その結果、プロセスが 1 つ減り (パイプも 1 つ減ります)。(複数の入力ファイルがある場合に使用するのが適切/必要な場合があります。)
答え2
パイプがまだ開いている間に子をフォークして linkcheck.sh の別のコピーを実行する時点と、子が実際に読み取りを試みる時点の間のウィンドウが原因で、悪い競合状態が発生し、エラーが発生している可能性があると思われます。そのウィンドウでは、別のコピーが EOF を読み取り、パイプが閉じています。