
我已配置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
還有一個差別是緩衝之間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
.因此,您可以看到,cat
一旦 Perl 腳本將行寫入管道,就會將其列印出來,同時tail -f
在列印到 stdout 之前將其緩衝最多 4kb。
答案3
cat
tail -f
當僅顯示最後一行和後面的行時,顯示整個文件。因此,如果文件很短,它們的行為是相同的,但如果文件很大(100+行),您可以看到它們兩者之間的明顯差異。
有關這些命令的附加資訊: