从命名管道连续读取(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

相关内容