Shell:stdbuf 解决实时输出问题

基础知识

缓冲类型分为三种:

  1. 无缓冲
  2. 行缓冲
  3. 全缓冲

stderr的缓冲类型 默认就是无缓冲。

stdout的缓冲类型与输出介质有关:

  • 屏幕或者终端:行缓冲
  • 重定向文件、管道:全缓冲

        一般情况下程序输出介质都是屏幕或者终端,采用的都是行缓冲,也就是实时输出。

但是当程序输出介质为重定向文件或者管道时,内核为了性能优化,可能变成非实时的。究其原因也就是因为pipe的缓冲区问题。

举例

例子

tail -f access.log | cut -d' ' -f1 | uniq

发现没有任何输出

分析

        首先tail程序通过read调用读取文件中的内容,然后将读取的数据写入stdout,由于tail的输出是管道,需要拷贝到内核。(tail程序比较特殊,在有新数据产生时,会主动调用fflush,刷新缓冲区),内核中第一个缓冲区如果不写满,cut程序便读取不到tail写入的数据(原因1)。由于cut程序本身也是缓冲的(原因2),输出是管道,这里也会等待缓冲区满(原因3),uniq程序才能读取到数据。最终导致了没有任何输出。

        类似的程序还有 tcpdump -l ,grep --line-buffered , sed --unbuffered 提供了参数使其变成非缓冲的。

解决方案

知道原因后,其实也就是告诉程序我不要缓冲,实时给我写就好。linux提供了 stdbuf 命令

#stdbuf -oL command
tail -f ~/access.log | stdbuf -oL cut -d' ' -f1 | uniq

其中,o表示输出流,L表示行缓冲。

        这样主要遇到换行符,就会将缓冲输出到指定对象。而不会等到缓冲区完全写满后,才让下游读取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术探索者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值