9
20
2018
8

永远不要 tail -f 管道

本文来自依云's Blog,转载请注明。

运维同事为了收集日志,配置程序将日志写入一个命名管道。然后他在外边拿 tail -f 去读,结果发生了灵异事件。通过 strace 可以看到,tail 进程读取了日志,但是却并没有再输出来。但是如果不启动输出日志的程序,而是在实例启动之后再进去往管道里写数据,却又是可以立即得到 tail 的输出的。

很奇怪的行为,一群人在那里研究半天,猜测是不是环境变量造成的啊,是不是放后台组执行造成的啊,是不是 XYZ 啊。——典型的「霰弹枪式」除错法

我当时也被带沟里了。于是跑去尝试复现,接着去读 tail 的源码。花了好久才明白这是一个很简单的问题:tail -f 的语义首先是 tail 这个词本身——先读文件最末尾的数据(默认是十行),然后再是 -f 选项的语义,即在文件更新时接着读取数据并输出。所以,当程序往里边写日志时,管道写端一直没关闭,tail 就一直读不到文件结束,也就无法确定最后十行是什么。当他们测试的时候,因为使用的是 echo shell 命令,打开文件、写入数据、关闭。这样 tail 一下子就读取到了文件末尾,然后把数据输出来了。接下来就是边读边输出了。

其实这种使用方法本身就很奇怪了,以至于这个执行流是兼容许多系统的 tail 的各种分支里,最最不常规、无可奈何的那一个分支。你都用管道了,cat 一下嘛。如果怕遇到管道被 reopen 的情况,就在 while true 里 cat 就好。

这个事件中,我也是见识了很多人解决问题的奇怪思路:「我猜猜猜。猜对了哦耶,猜错了,哎呀编程好难啊,Linux 系统好难啊……」猜你妹啊!你长的是大脑又不是骰子,用逻辑一步一步地取得结果不好吗!

有一个小游戏——猜数字。比如甲确定一个 1 到 1000 之内的整数,然后乙来猜。每当乙给出一个猜测时,甲回应猜对了,还是过大或者过小。如果乙知道什么叫二进制的话,乙可以保证在十次之内猜中的。

计算机系统和编程世界里,最棒的一点是确定性和逻辑性。虽然经常也不是像上例那样完全确定的,但至少比起人类社会要容易确定得多。特别是在有源码的时候。所以解决问题的路线也很简单,顺着问题的症状一路回溯,确认然后排除那些没有问题的部分,逐步缩小问题所在的范围,直接你看见它。就跟上边的猜数字游戏或者地毯式搜索一样。每一次猜测都是带着排除一部分没有问题的地方而去,而不是明明有证据表明某个地方不可能有问题,你还偏偏怀疑问题在那里,做无用功。

就像调查一个凶案,这些人放着有作案嫌疑的人不管,非要费劲地去调查那些有相当好的不在场证明的人。

Arch Linux 中文社区这边也有很多这种人。出了问题描述不清楚症状。新手嘛,没经验也没学习过如何描述事实,讲不清楚也没什么,引导对方获取截屏、日志,逐步排查问题就好了嘛。可就是有些热心人,喜欢提出自己的猜测。重点是:都不尝试证实猜测是否属实,就急着上解决方案。结果就是,我询问细节事实的消息没人理,求助者试试这个,试试那个,最终问题能否解决,就跟买彩票能否中奖一样,全凭运气。

Category: Linux | Tags: Arch Linux fifo linux 社群 | Read Count: 22908
Ivan 说:
Sep 21, 2018 04:43:05 AM

关于最后一段,有些热心人喜欢提出自己猜测,是由于求助者提供的资料不够详细,希望快速找到问题。提出猜测的同时,提供相应的解决方案也无可厚非,关键是求助者需要判断自己是否符合所猜测的情况再去尝试解决方案。

Ivan 说:
Sep 21, 2018 05:22:36 AM

你也没向微信交保护费吗,微信浏览器禁止打开了。。

laixintao 说:
Sep 21, 2018 10:53:00 AM

这点非常重要也很难,如果能做到这样也就不算新手了。

http://teahour.fm/2017/12/12/why-vscode-is-better-than-atom.html

这个 fm 里面,吕鹏也吐槽 Atom 团队在优化性能的时候没有经过测试和推理,而是全靠猜:我们改用了 React 的虚拟 DOM,提高了性能…… 过段时间:我们又弃用了虚拟 DOM……

Avatar_small
依云 说:
Sep 21, 2018 11:40:50 AM

所以别用微信浏览器啊。Arch Linux 中文论坛也早就被腾讯禁了的。

Avatar_small
依云 说:
Sep 21, 2018 11:43:15 AM

你对求助者的要求太高了。不断有人提出猜测,最经常的结果就是,求助者不断地尝试,最后失望而去。

「多快好省」要不得啊。

x.b.y 说:
Sep 25, 2018 07:43:10 PM

看来是被小白气的上头了。。。消消气。

话说tail -F /var/log/messages | egrep --line-buffered
还是可以用用的嘛

我打包的linux image总是带一个diagnose脚本,把我所有的猜测都写进去了,也许你可以发布自己的diagnose pack?

Avatar_small
依云 说:
Sep 26, 2018 12:58:17 AM

messages 是普通文件当然可以好好地 tail -F 啦。

以后可以试试。遇到想理的求助帖,写一个脚本扔过去,收集了信息自动传回来。不过很多人联网有问题呢……

x.b.y 说:
Sep 26, 2018 10:44:59 AM

哈哈哈,我审题不清。这真是一个少见的用法,放着好好的socket不用,非要管道,还没注意EOF用错了。要不是你提醒用cat就可以了,我也差点把IOselect拿出来了。。。印象中管道都是管理子进程的。随便用用不好。

屏显就好了,收日志还要搭个服务器,那可犯不着了。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

| Theme: Aeros 2.0 by TheBuckmaker.com