为什么管道有时会被“卡住”:缓冲

主要观点:多年来一直困扰的终端管道缓冲问题,直到几周前才理解。管道有时会“卡住”不显示输出,原因是程序通常会缓冲输出再写入管道,grep等程序根据输出目标(终端或管道)决定缓冲方式,一些命令会缓冲输出,不同编程语言的默认print语句也可能缓冲,按下Ctrl-C时管道缓冲区内容会丢失,重定向到文件也会缓冲,给出了避免缓冲的多种方法。

关键信息:

  • tail -f /some/log/file | grep thing1 | grep thing2可能无输出,因grep thing1缓冲数据。
  • grep根据输出目标决定缓冲方式,终端为行缓冲,管道为块缓冲。
  • 一些不缓冲输出的命令如tailcattee,常见缓冲输出的命令及禁用方式。
  • 不同编程语言默认print语句缓冲情况及禁用方法。
  • 按下Ctrl-C时管道程序处理及可能的解决方法(找到tcpdump的 PID 并kill -TERM)。
  • 避免缓冲的 5 种方法:运行快速结束程序、使用grep--line-buffered标志、用awk、使用stdbuf、使用unbuffer

重要细节:

  • grep的缓冲由libcBUFSIZ变量控制,不同程序的缓冲大小可能不同。
  • 测试不同系统版本的命令可能存在差异。
  • stdbuf的使用有局限性,unbuffer可能有副作用但通常有效。
  • 作者不确定这种情况的常见程度,提出可设置环境变量来禁用缓冲的想法及相关设计难点。
  • 文中未讨论行缓冲与无缓冲输出的区别、stderrstdout缓冲的不同、操作系统 TTY 驱动的缓冲以及其他需要刷新输出的原因。
阅读 17
0 条评论