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 commandtail -f ~/access.log | stdbuf -oL cut -d' '-f1 | uniq

其中的参数,o表示输出流,L表示行缓冲。 这样主要遇到换行符,就会将缓冲输出到指定对象。而不会等到缓冲区完全写满后,才让下游读取。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容