私はプログラムの出力をwhile read VAR
ループにパイプし、パターンがbreak
見つかったら出力する予定でしたが、そうではありませんでした。
概念の証拠:
inotifywait -qm -e create . | while read line; do echo $line; break; done
./ CREATE newfile
..
tail -f /var/log/syslog | while read line; do echo $line; break; done
Nov 6 22:44:05 section9 ntpdate[2381]: adjust time server 91.189.89.199 offset 0.272779 sec
ソースプログラムが何を出力しても終了しません。プリセットは、set -x
ループが2回目以降繰り返されないことを示しますread
。$BASH_SUBSHELL
この例では 1 です。
tail
inotifywait
など。 SIGPIPEを受けて終了してはいけませんか?
プロセス置換(while read ... break; done < <(tail -f ...)
)が正しく機能することに注意してください。$BASH_SUBSHELL
この場合は0です。
答え1
要点は、bash(他のシェルは異なる場合があります)からパイプが終了するまで終了しないことです。すべてのコマンドパイプラインで完了しました。
理解するために、次の点を考えてみましょう。
inotifywait -qm -e create . | while read line; do echo $line; break; done
1行を読み取ると、read
エコーされた後にbreak
実行され、最後にプロセスが終了します。ただし、最初のプロセスは標準出力書き込みに失敗するまで続きます。したがって、ループは少なくともinotifywait
そのエントリに書き込もうとするまで続きます。第二出力ライン。バッファリングの曖昧さのためにこれは起こらないかもしれません。検索が発生するには複数行が必要な場合があります。書き込み試行が失敗すると、SIGPIPE が発行されます。
今、別のシナリオを考えてみましょう。
while read line; do echo $line; break; done < <(inotifywait -qm -e create .)
ここにパイプはありません。break
実行するとwhile
ループが完了します。
文書
「パイプライン」セクションでman bash
:
シェルすべてのコマンドを待ちますパイプからシャットダウン中...
これはあなたがする選択ですbash
。 POSIXではこれを義務付けていません。 POSIX状態:
パイプがバックグラウンドにない場合(非同期リストを参照)、シェルはパイプで指定された最後のコマンドが完了するまで待つ必要があります。待つことができるすべてのコマンドを完了するには
答え2
strace tail -f -n 5000 /var/log/messages |
while read line; do echo $line; break; done;
何が起こったのかを詳しく見せてください。
[...]
write(1, "Nov 1 22:20:01 inno systemd[1]:"..., 4096) = 4096
つまり、tailは一度に最大4096バイトをパイプに書き込むことができます(パイプがバッファリングできる容量)。データがあまり多くない場合が多いですtail
。
strace tail -f /var/log/messages | while read line; do echo $line; break; done;
プログラム
write(1, "Nov 7 07:00:02 inno systemd[1]:"..., 730) = 730
したがって、tail
ファイルに何かが追加されるまで書き換えを試みません。
私はunbuffer
これが解決できると思いました。そうではないことに驚きました。
unbuffer tail -f file1 | while read line; do echo $line; break; done