別のプロセスに転送するために、bash スクリプトで複数の子プロセスの出力を 1 行ずつ収集しようとしています。
サブプロセスの出力が混在していないことを保証するものは何も見つかりませんでしたが、各出力行が正しく出力に送られることが重要です。出力間の順序は重要ではありません。
混合/文字化けした出力の例を次に示します。
#!/bin/bash
for i in {1..1000}; do
( { echo BEGIN; dmesg; echo END; } | tr -d '\n'; echo ) &
done
wait
これを実行する:
$ ./test_output.sh | perl -ne 'print "$1\n" if m/(.{1,20}BEGIN.{0,20})/' | head
0.000000] SRAT: PXMBEGIN[ 0.000000] Initi
ME through PCIe PME BEGIN[ 0.000000] Initi
ME through PCIe PME BEGIN[ 0.000000] Initi
[ 0.209816] pci 0BEGIN[ 0.000000] Initi
ciehp 0000:00:16.1:pBEGIN[ 0.000000] Initi
CI: Updating contextBEGIN[ 0.000000] Initi
l family 2[ 0.588BEGIN[ 0.000000] Initi
ME through PCIe PME BEGIN[ 0.000000] Initi
CI: Updating contextBEGIN[ 0.000000] Initi
3922 pages, LIFO batBEGIN[ 0.000000] Initi
混合コンテンツの行がいくつか表示されます。
もちろん無くて&
も大丈夫です。
したがって、今のところ、すべての子の出力をファイルにリダイレクトしてから、大きなwait
の後にcat
これらすべてのファイルにリダイレクトする以外に選択肢はありません。
GNU 並列で同じことを実行することは仕事の一部ですが、私の環境ではオプションではありません。
GNU 並列は、コマンドからの出力が、コマンドを順番に実行した場合と同じ出力であることを確認します。これにより、GNU パラレルからの出力を他のプログラムの入力として使用することが可能になります。
そのため、GNU parallel は、各ジョブが終了するとすぐに各ジョブ出力を書き込み、出力を混合しないようにします。それは良い。しかし、各ジョブの出力をできるだけ早く取得することにも関心があります。つまり、ジョブの終了を待たないことです。「-u」スイッチがありますが、ジョブの出力が混在します。
fifo で遊んだり、選択したり、perl スクリプトを作成したりする必要がありますか?
--
出力がman 7パイプで混合される理由/方法/時期を見つけたと思います
POSIX.1-2001 は、PIPE_BUF バイト未満の write(2) はアトミックでなければならないと述べています。出力データは連続したシーケンスとしてパイプに書き込まれます。PIPE_BUF バイトを超える書き込みはアトミックではない可能性があります。カーネルは、データを他のプロセスによって書き込まれたデータとインターリーブする可能性があります。POSIX.1-2001 では、PIPE_BUF が少なくとも 512 バイトである必要があります。(Linux では、PIPE_BUF は 4096 バイトです。)