主要观点:多年来一直困扰的终端管道缓冲问题,直到几周前才理解。管道有时会“卡住”不显示输出,原因是程序通常会缓冲输出再写入管道,grep
等程序根据输出目标(终端或管道)决定缓冲方式,一些命令会缓冲输出,不同编程语言的默认print
语句也可能缓冲,按下Ctrl-C
时管道缓冲区内容会丢失,重定向到文件也会缓冲,给出了避免缓冲的多种方法。
关键信息:
tail -f /some/log/file | grep thing1 | grep thing2
可能无输出,因grep thing1
缓冲数据。grep
根据输出目标决定缓冲方式,终端为行缓冲,管道为块缓冲。- 一些不缓冲输出的命令如
tail
、cat
、tee
,常见缓冲输出的命令及禁用方式。 - 不同编程语言默认
print
语句缓冲情况及禁用方法。 - 按下
Ctrl-C
时管道程序处理及可能的解决方法(找到tcpdump
的 PID 并kill -TERM
)。 - 避免缓冲的 5 种方法:运行快速结束程序、使用
grep
的--line-buffered
标志、用awk
、使用stdbuf
、使用unbuffer
。
重要细节:
grep
的缓冲由libc
的BUFSIZ
变量控制,不同程序的缓冲大小可能不同。- 测试不同系统版本的命令可能存在差异。
stdbuf
的使用有局限性,unbuffer
可能有副作用但通常有效。- 作者不确定这种情况的常见程度,提出可设置环境变量来禁用缓冲的想法及相关设计难点。
- 文中未讨论行缓冲与无缓冲输出的区别、
stderr
与stdout
缓冲的不同、操作系统 TTY 驱动的缓冲以及其他需要刷新输出的原因。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。