xargsのために出力はこのように混在しますか?どうすれば解決できますか?

xargsのために出力はこのように混在しますか?どうすれば解決できますか?

少し学んでいます。吹く使用してパラメータ複数のIPアドレスのwhoisレコードを一覧表示します。使用されるコマンドは次のとおりです。

echo "$1" | tr "\n" "\0" | xargs -0 -n 1 -t -P 3 -I %  sh -c 'echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net % ; echo "\n 44rEnd whois record -- \n"'

実行されるコマンドは次のとおりです。

sh -c echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net 206.190.36.45 ; echo "\n 44rEnd whois record -- \n"
sh -c echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net 212.146.69.237 ; echo "\n 44rEnd whois record -- \n"
sh -c echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net 77.238.184.24 ; echo "\n 44rEnd whois record -- \n"

sh -c私は実行を使用して、コマンドの各ブロックが順番に実行されたかのように出力したいと思います。代わりに、私の結果は次のようになります。

44rBegin whois record

44rBegin whois record

44rBegin whois record

whois1 output

44rEnd whois record --

whois2 output

44rEnd whois record --

whois3 output

44rEnd whois record --

この問題をどのように解決できますか?

答え1

この特定のケース-P 3ではxargs

   -P max-procs
          Run up to max-procs processes at a time; the default is 1.  If max-procs  is
          0,  xargs  will run as many processes as possible at a time.  Use the -n op‐
          tion with -P; otherwise chances are that only one exec will be done.

並列に実行するため、すべて同時に出力に書き込みます。

このコマンドを他の場所からコピーした場合は、調査してコピーする内容を理解することをお勧めします。それ以外の場合は危険です。

答え2

write複数のプロセスが同じ端末(またはファイル)に並列に出力されるたびに、その出力が分散される危険性があります(ある種のロックの準備やオープンファイルの追加などの低レベルのシステムコールを使用しない限り)。モデル)。

最初のステップとして、各シェル呼び出しで以下を使用してこれを実行できます。コマンドの置き換えwhoisコマンドを子プロセスとして実行し、その出力をキャプチャし、すべてを単一のジョブにprintfまとめます。

xargs -0 -n 1 -P 3 -I %% sh -c 'printf "\n%s\n%s\n%s\n" " 44rBegin whois record -- " "$(whois -h whois.arin.net %%)" " 44rEnd whois record -- "'

flockより良いことは、利用可能なプログラムがある場合は、それを使用して次の組み合わせへのすべての呼び出しをロックできることですprintf

xargs -0 -n 1 -P 3 -I %% sh -c 'who="$(whois -h whois.arin.net %%)"; flock /tmp/who.lock printf "\n%s\n%s\n%s\n" " 44rBegin whois record -- " "$who" " 44rEnd whois record -- "'

答え3

はい、それは出力を混ぜますxargs -P。複数のサブプロセスを並列に実行しており、出力を調整することはありません。必要に応じてすべて出力を作成し、すべて一緒に混在します。

使用GNUパラレル、これは同じことを行うより強力なツールですxargs -P。デフォルト値は次のとおりです。各タスクの結果をグループ化

echo "$1" | parallel -t -P 3 sh -c 'echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net $0; echo "\n 44rEnd whois record -- \n"'

答え4

この問題をどのように解決できますか?

catこの手法を示すために、標準出力を各プロセスとそれ以降のすべてのプロセスのファイルにリダイレクトします。

seq 100 | sort -R |
  xargs -I@ -P0 sh -c '{ echo begin @ && sleep 0.@ && echo end @; } > $$.log' &&
  find . -name '*.log' -exec cat {} \+

この手法をコマンドに適用します。

echo "$1" |
  tr "\n" "\0" |
  xargs -0 -n 1 -t -P 3 -I % sh -c '{echo "\n 44rBegin whois record -- \n"; whois -h whois.arin.net % ; echo "\n 44rEnd whois record -- \n";} > $$.log' &&
  find . -name '*.log' -exec cat {} \+

関連情報