从命名管道(cat或tail -f)连续读取


16

我已配置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

有人可以解释为什么吗?

两者之间有什么区别吗?

Answers:


18

cat继续阅读直到获得EOF。管道仅在输入得到EOF时才在输出上产生EOF。日志记录守护程序正在打开文件,对其进行写入并使其保持打开状态(就像对常规文件一样),因此永远不会在输出中生成EOF。cat只是继续阅读,每当耗尽管道中的当前内容时就会阻塞。

您可以自己手动尝试:

$ mkfifo test
$ cat test

在另一个终端:

$ cat > test
hello

另一个端子将输出。然后:

world

另一个端子将有更多输出。如果现在使用Ctrl-D输入,则另一个cat也将终止。

在这种情况下,cat和之间唯一可观察到的区别tail -f是日志记录守护程序是终止还是重新启动:cat在管道的写端关闭时将永久停止,但是tail -f在守护程序重新启动时将继续运行(重新打开文件)。


抱歉,您的示例中看不到“世界”的来源:)
Alexander Mills

从你的打字进去。
迈克尔·荷马

1
然后,键入world,然后,“ world”出现在另一个终端中。
Michael Homer

2

和之间的缓冲也有所不同。您可以查看以下内容:cattail -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。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.