Chinaunix首页 | 论坛 | 博客
  • 博客访问: 622574
  • 博文数量: 142
  • 博客积分: 116
  • 博客等级: 入伍新兵
  • 技术积分: 1445
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-28 08:37
文章分类

全部博文(142)

文章存档

2017年(7)

2016年(57)

2015年(48)

2014年(30)

我的朋友

分类: LINUX

2016-06-18 12:08:32

一般我们使用tail -f来跟踪文件变化(或tail -F来对付轮转日志)。

但是在tail加上管道(例如tail -f | xxcmd )后,会发现输出可能有延时,
就是说,日志文件变化了,但管道命令并没有及时输出结果。要等到日志
变化达到一定量时才输出。

发生这种现象,就是因为IO缓冲机制造成的。
缓冲是一种有效提高IO效率的方法,把频繁的读写请求积累到一定程度后再
一次性的与IO设备交互操作。

IO缓冲有3种,无缓冲,行缓冲,和全缓冲。

无缓冲,就是不使用缓冲机制。面向字节的设备?(stderr)
行缓冲,缓冲,直到遇到换行符。一般用于终端设备。
全缓冲,缓冲,直到buffer满。一般用于块设备。

在终端窗口中执行tail命令,是面向终端设备的,会使用行缓冲,
所以日志中每写入一行,立刻就会输出。
当使用管道时,会变为使用全缓冲,这样一来,就要等到日志中
写入的字节数填满buffer后才会输出。

tail命令是如何判断,如何转换缓冲方式的,还没有来的及研究,
根据下面的实验现象,
tail -f加grep或sed,没有问题。但再加一层管道,就有问题。
tail -f加awk,有问题。


先记录一下几种解决方法。
一,使用stdbuf命令。它是coreutils包中的命令,一般系统都已安装。
它可以修改命令的缓冲方式。
例如  stdbuf -oL tail 就把tail的输出设置为行缓冲。

但是,有些命令,在命令中自己会设置缓冲方式,这就会覆盖stdbuf的设置。
还有一些命令是不使用流(stream)的(像cat和dd),stdbuf对他们无效。

二,把tail的标准输出重定向到标准错误上,并把标准错误也给管道。
因为stderr是无缓冲的。
例如  tail -f >&2 |& awk



实验结果:

a.log是另一个进程每秒写入的。

  1. $ tail -fn0 a.log
  2. 2016/06/17 22:52:08
  3. ^C
  4. $ tail -fn0 a.log |grep .
  5. 2016/06/17 22:52:12
  6. ^C
  7. $ tail -fn0 a.log |grep .|grep .
  8. ^C
  9. $ stdbuf -oL tail -fn0 a.log |grep .|grep .
  10. ^C
  11. $ stdbuf -oL tail -fn0 a.log |stdbuf -oL grep .|grep .
  12. 2016/06/17 22:52:34
  13. 2016/06/17 22:52:35
  14. ^C
  15. $ tail -fn0 a.log |stdbuf -oL grep .|grep .
  16. 2016/06/17 22:53:01
  17. 2016/06/17 22:53:02
  18. 2016/06/17 22:53:03
  19. ^C
  20. $ tail -fn0 a.log |grep .|grep .
  21. ^C
  22. $ tail -fn0 a.log |grep .|stdbuf -oL grep .
  23. ^C
  24. $ tail -fn0 a.log >&2 |& grep .|grep .
  25. 2016/06/17 22:53:45
  26. 2016/06/17 22:53:46
  27. ^C
  28. $ tail -fn0 a.log|awk '{print}'
  29. ^C

另外补充一点,
当我们使用协程时,一定要注意使用行缓冲,不然可能造成死锁。

阅读(4733) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~