我已配置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+行),您可以看到它们两者之间的明显区别。
关于这些命令的其他信息: