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

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

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

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

/dev/xconsoleは名前付きパイプ ( fifo) です。ログに記録されている内容を確認したい場合は、 を実行できます。コマンドはファイルを読み込んだ後も終了せず、 として動作することcat /dev/xconsoleに驚きました。つまり、2 つのコマンドの動作は同じです。cat /dev/xconsoletail -f

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

誰かその理由を説明してくれませんか?

この2つには何か違いがありますか?

答え1

catEOFを取得するまで読み取りを続けます。パイプは入力でEOFを取得したときにのみ出力にEOFを生成します。ログデーモンはファイルを開いて書き込み、そしてそれを開いたままにしておく— 通常のファイルの場合と同じように — 出力に EOF が生成されることはありません。catパイプ内の現在内容がなくなるとブロックしながら読み取りを続けます。

これを手動で自分で試すこともできます:

$ mkfifo test
$ cat test

別のターミナルでは:

$ cat > test
hello

他のターミナルに出力が表示されます。次に、次のように入力します。

world

あるだろうもっと他の端末に出力します。ここで入力を Ctrl-D すると、他の端末catも終了します。

この場合、 と の唯一の目に見える違いは、catログtail -f記録デーモンが終了したか再起動されたかです。 は、catパイプの書き込み側が閉じられると永久に停止しますが、tail -fデーモンが再起動されると続行されます (ファイルを再度開きます)。

答え2

また、バッファリングcatとの間ですtail -f。これを確認できます:

パイプを作成: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}'

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

答え3

cat最後の行のみを表示し、それに続く場合はファイル全体が表示tail -fされます。したがって、ファイルが短い場合は同じように動作しますが、ファイルが大きい場合 (100 行以上)、2 つの間に明確な違いが見られます。

これらのコマンドに関する追加情報:

tail http://www.computerhope.com/unix/utail.htm

cat http://www.computerhope.com/unix/ucat.htm

関連情報