web-dev-qa-db-ja.com

名前付きパイプからの継続的な読み取り(catまたはtail -f)

特定のログイベントを/dev/xconsoleに記録するようにrsyslogを設定しました:

*.*;cron.!=info;mail.!=info      |/dev/xconsole

/dev/xconsoleは名前付きパイプ(fifo)です。ログに記録されている内容を確認したい場合は、cat /dev/xconsoleを使用できます。コマンドcat /dev/xconsoleがファイルの読み取り後に終了せず、代わりにtail -fとして機能することを確認して驚いています。つまり、2つのコマンドは同じように動作します。

cat /dev/xconsole
tail -f /dev/xconsole

誰かがその理由を説明できますか?

2つの間に違いはありますか?

16
Martin Vegter

catは、EOFになるまで読み取りを続けます。パイプがEOFを取得するのは、入力でEOFを取得した場合のみです。ロギングデーモンがファイルを開いて書き込みを行っていますそして、それを開いたままにします —通常のファイルの場合と同様に— EOFは出力で生成されることはありません。catは読み取りを継続し、現在パイプ中です。

手動でこれを試すことができます:

$ mkfifo test
$ cat test

そして別のターミナルで:

$ cat > test
hello

他の端子に出力されます。次に:

world

他の端末にはmoreの出力があります。ここで入力をCtrl-Dすると、他のcatも終了します。

この場合、cattail -fの唯一の観察可能な違いは、ロギングデーモンが終了または再起動された場合です。catは、パイプの書き込み側が閉じられると永久に停止します、ただしtail -fは、デーモンが再起動されても続行します(ファイルを再度開きます)。

18
Michael Homer

catと_tail -f_の間にはbufferingの違いもあります。あなたはこれをチェックすることができます:

パイプを作成:_mkfifo pipe_

バックグラウンドでcatを使用してパイプの読み取りを開始します:_cat pipe &_

パイプを開き、毎秒書き込みます:Perl -MFcntl -we 'sysopen(my $fh, "pipe", O_WRONLY | O_NONBLOCK); while() {warn "written: " . syswrite($fh, "hello\n"); sleep 1}'

catの代わりに_tail -f pipe &_でこれを試してください。したがって、catは、Perlスクリプトによってパイプに書き込まれるとすぐに行を出力し、_tail -f_は、標準出力に出力する前に最大4kbをバッファリングすることがわかります。

2
InterestedIn