從命名管道連續讀取(cat 或 tail -f)

從命名管道連續讀取(cat 或 tail -f)

我已配置rsyslog將某些日誌事件記錄到/dev/xconsole

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

/dev/xconsole是一個命名管道 ( fifo)。如果我想查看正在記錄的內容,我可以這樣做cat /dev/xconsole。我驚訝地發現該命令cat /dev/xconsole在讀取文件後並未完成,而是充當tail -f.換句話說,這兩個命令的行為相同:

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

有人可以解釋一下這是為什麼嗎?

兩者有什麼差別嗎?

答案1

cat繼續讀取直到到達 EOF。只有當管道在輸入上獲得 EOF 時,才會在輸出上產生 EOF。日誌守護程式正在開啟檔案並寫入,並保持開啟狀態— 就像常規文件一樣 — 因此輸出中永遠不會產生 EOF。cat只是繼續讀取,每當管道中當前的內容耗盡時就會阻塞。

您可以自己手動嘗試:

$ mkfifo test
$ cat test

在另一個終端中:

$ cat > test
hello

另一個終端會有輸出。然後輸入:

world

將有更多的輸出到另一個終端。如果您現在按 Ctrl-D 輸入,則另一個輸入cat也會終止。

cat在這種情況下,和will之間唯一可觀察到的區別tail -f是日誌守護程序是否終止或重新啟動:cat當管道的寫入端關閉時將永久停止,但當tail -f守護程序重新啟動時將繼續運行(重新打開文件)。

答案2

還有一個差別是緩衝之間cattail -f你可以看看這個:

建立管道:mkfifo pipe

開始在背景讀取管道catcat 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.因此,您可以看到,cat一旦 Perl 腳本將行寫入管道,就會將其列印出來,同時tail -f 在列印到 stdout 之前將其緩衝最多 4kb。

答案3

cattail -f當僅顯示最後一行和後面的行時,顯示整個文件。因此,如果文件很短,它們的行為是相同的,但如果文件很大(100+行),您可以看到它們兩者之間的明顯差異。

有關這些命令的附加資訊:

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

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

相關內容