tail -f结合perl重定向无输出,同类命令正常,求解析
问题分析与解决方案
这是个典型的管道缓冲问题,我来给你拆解清楚为什么会出现这种差异:
核心原因:perl在管道中的块缓冲行为
当tail -f的输出通过管道传给perl时,perl默认会启用块缓冲模式——也就是它会攒够一大块数据(通常是4KB或8KB,取决于系统)才会把内容输出到stdout(也就是你的file2)。而tail -f是持续逐行输出内容的,短时间内根本凑不够一个块的大小,所以perl一直不会把内容flush到file2里,看起来就像没有写入任何内容。
对比其他能正常工作的场景
我们逐个看你提到的成功案例,就能明白缓冲模式的影响:
tail -f file1 > file2:直接重定向到文件时,tail本身的输出是行缓冲模式,每产生一行内容就会立刻写入文件。tail -f file1 | perl -pe '$_':当perl的stdout指向终端时,它会自动切换为行缓冲模式,每处理一行就输出一行,所以你能实时看到内容。tail file1 | perl -pe '$_' > file2:tail会一次性把file1的所有内容输出完毕,这些内容足够填满perl的块缓冲,或者tail输出EOF时,perl会自动flush所有缓冲到文件。tail -f /tmp/file1 | while read line; do echo $line | perl -pe '$_' > /tmp/file2 ; done:这里每次循环都会启动一个新的perl进程,每个perl只处理一行内容就退出,进程退出时会自动清空所有缓冲,所以内容能被写入文件。
解决方法:强制perl使用行缓冲
有几种简单的方式可以让perl在管道中也用行缓冲:
- 使用
-l参数(该参数会自动处理换行符,同时开启行缓冲):tail -f file1 | perl -lpe '$_' > file2 - 在perl脚本中手动设置输出缓冲:
这里的tail -f file1 | perl -pe '$|=1; $_' > file2$|=1是perl的特殊变量设置,用来强制stdout无缓冲(实际效果就是行缓冲)。 - 用
stdbuf命令强制修改缓冲模式(适用于任何管道中的命令):tail -f file1 | stdbuf -oL perl -pe '$_' > file2-oL参数表示将stdout设置为行缓冲模式。
内容的提问来源于stack exchange,提问作者vibl
相关产品推荐
相关产品推荐

