一次曲折的bug调试经历

标签: bug 调试 经历 | 发表时间:2015-11-20 14:19 | 作者:
出处:http://www.iteye.com
Bug调试是让程序员最头痛的任务,因为它就像狄仁杰断案一样,需要抓住任何的蛛丝马迹、展开丰富的推理联想,一次次的尝试,才有可能解决疑问命案——不然程序员会死,不是加班熬夜熬死,就是让老板开除,郁闷而死。

最近我在操作一个页面时,程序出现了这样的错误:
Fatal error: mysql error: [1: Can't create/write to file '/var/tmp/#sql_9469_0.MYI' (Errcode: 28)]

错误是mysql服务器抛出的,是致命错误,我以前没有遇到、也没有见到过这样的错误,但错误提示信息还是很丰富、明确的。不像以前曾遇到的错误提示,一点价值都没有。

用谷歌搜索,搜索出了很多相关信息页面,说明这个错误还是比较普遍的。基本可以断定这个错误是由于硬盘没有足够的剩余空间导致的,特别是错误信息里提到的Errcode: 28,这个错误代码有明确的意义,在命令行里使用perror命令:
$ perror 28
OS error code  28:  No space left on device

似乎引起错误的原因已经找到了,如果是硬盘空间不足,只需要扩充存储空间或删除一些无用的文件就行了。那是真的因为硬盘空间不足吗?使用df命令查看一下:



意外的是,系统还有充足的空间,系统盘只使用了15%,数据盘只使用了25%。奇怪吧,错误提示信息和真正情况并不能统一。

调试bug时遇到挫折常见的,我没有别的办法,怀疑找错了方向,但现有的线索也只有这些,怎么办呢,我觉得还是应该在网上搜索,也行会有新的发现。

果然,在一篇文章里看到有人说Errcode: 28所指示的No space并不一定是指空间不足,也可能是磁盘上的文件数过多,这位网友这样说:
I had same problem but disk space was okay (only 40% full). Problem were inodes, I had too many small files and my inodes were full.

You can check inode status with df -i

他说的这个问题我是遇到过的,linux文件系统里对文件数是有限制的,当文件数达到最大数量是,你将无法新增文件。错误信息里提到了无法读写tmp目录下的临时文件,也行正是因为无法创建新的文件。

那么使用df -i会是什么结果呢?让我吓一跳,在/dev/vda1盘上的文件数竟然快到200多万。看来文件就出自这里了。

下面的任务是找到哪个目录里藏了这么多文件。我使用了笨办法,手工从根目录一个一个的搜:
find DIR_NAME -type f ¦ wc -l

上面的命令可以统计出指定目录下一共有多少个文件。这是个体力活儿,但体力活儿是最容易出结果的,没用多久,我就发现了一个可疑目录:
/var/spool/postfix/maildrop

这个目录下竟然有180万个文件。

看来凶手就是它了。只要将maildrop下的文件全部删掉,磁盘文件数会全部释放,问题也就解决了。可是,为什么会有这么多文件,为什么会在postfix目录下,这个问题如果不搞清楚,相同的服务器异常不久后还会出现。

那么, postfix;是个东西,而maildrop又是个什么东西。

原来postfix是一个邮件服务器软件:
引用

What is Postfix? It is Wietse Venema’s mail server that started life at IBM research as an alternative to the widely-used Sendmail program. Now at Google, Wietse continues to support Postfix.

而maildrop是邮件队列,里面存放的都是一个个邮件。

可问题又来了,哪里来的这么多邮件,谁发给谁的?

我从maildrop下载了一个邮件文本,打开一看,是发给root用户的,邮件的内容是Cron Daemon执行信息。

祸首原来是任务调度程序,这几百万封邮件都是它发的,每执行完一个Cron任务,它都会发给root一份任务完成情况的邮件。在/etc/crontab文件里陈列着30多个定时调度任务,而且很多任务执行的频度很高,所以才在短时间里发送了这么多的文件。

根源是找到了,只要禁止这些调度任务给root发邮件,系统文件数就不会大量增加,我的程序就不会出现Errcode: 28错误了,可我不能简单的删除这些调度任务来禁止它们发邮件。对/etc/crontab文件熟悉的系统管理员会知道,就在它的前几行是配置信息:
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

其中第三行是配置邮件的,它指明要把邮件发给root用户,只需要把这行信息改成MAILTO="",它就再也不发邮件了。

到此为止,问题算是彻底解决了,但回顾一下,一个mysql的异常的原因竟然是由于Cron调度发邮件导致的,风马牛不相及的事情,真有点像蝴蝶效应,亚马逊丛林里蝴蝶扇动翅膀,最终导致太平洋上风暴。软件开发中的调试bug就是这样的不可思议。

来自: http://jicc.cc/

感谢 mengyidan1988 投递这篇资讯

资讯来源: http://jicc.cc/

已有 1 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [bug 调试 经历] 推荐:

一次曲折的bug调试经历

- - ITeye资讯频道
Bug调试是让程序员最头痛的任务,因为它就像狄仁杰断案一样,需要抓住任何的蛛丝马迹、展开丰富的推理联想,一次次的尝试,才有可能解决疑问命案——不然程序员会死,不是加班熬夜熬死,就是让老板开除,郁闷而死. 最近我在操作一个页面时,程序出现了这样的错误:. 错误是mysql服务器抛出的,是致命错误,我以前没有遇到、也没有见到过这样的错误,但错误提示信息还是很丰富、明确的.

找bug记(1)

- BTK 4eVeR - BlogJava-庄周梦蝶
    转载请注明出处 http://www.blogjava.net/killme2008/archive/2011/07/10/354062.html.     上周在线上系统发现了两个bug,值得记录下查找的过程和原因. 以后如果还有查找bug比较有价值的经历,我也会继续分享.     第一个bug的起始,是在线上日志发现一个频繁打印的异常——java.lang.ArrayIndexOutOfBoundsException.

找bug记(2)

- gengmao - BlogJava-庄周梦蝶
    这篇blog迟到了很久,本来是想写另一个跟网络相关bug的查找过程,偷偷懒,写下最近印象比较深刻的bug. 这个bug是我的同事水寒最终定位到的.     前几个月同事报告称有一个线上MQ集群会同一时间抛出ArrayIndexOutOfBoundsException这个异常,也就是数组越界.

Scrum中管理bug

- - CSDN博客研发管理推荐文章
如果bug来自于正在开发的sprint. 会在task阶段就被QA/Scrum Master/Product Owner标记为有bug,并且Story不能被置为done状态,这个很容易解决. 如果bug来自于已经结束的sprint,那么怎么办呢. 理想状态下是将bug放到backlogs中,然后由product owner调整其优先级,并决定放在后面的哪一个sprint中修复.

Fix Bug的五个阶段

- Sirius - 酷壳 - CoolShell.cn
下面的文章和《各种流行的编程方式》有异曲同工,请你不要理解错了. 一个非常严重和困难的bug,能够成就一个饱经沧桑深受压力的有经验的专业程序员的职业生涯. 经受这种考验的创伤程度,相当你受到了一次严重的身体伤害,离婚,或是家庭成为的离世. 研究人员在研究了计算机编程心理学后,得出了一个程序员们在解决一个困难的bug时的心路里程.

mysql order by和limit共用bug

- - 数据库 - ITeye博客
 在mysql下执行没有问题,可以得到预期结果. 但是用jdbc执行的时候就得不到预期结果了. 官网地址:http://bugs.mysql.com/bug.php?id=32933. 以下转载:http://bbs.chinaunix.net/thread-1276235-1-1.html. 我想从一个表中检索所有标题含有“中国”的数据,将它们按id排序,取前5条,所以我写了以下语句.

Java 7被发现含有严重bug

- Jingzhi - Solidot
甲骨文在Java 7中作出某些改变时,可能没很好的进行测试;但在发现严重bug后,它仍按时间表推出了Java 7. Java 7和Java 6都存在相同的bug,不同之处是前者默认启用,而后者没有. HotSpot Loop优化中的bug可能会导致JVM崩溃,或者是执行错误. Bug影响了多个Apache项目,包括Apache Lucene Core和Apache Solr.

Glibc改变导致bug出现

- allengaller - Solidot
在网上通过Flash插件听MP3遭遇破音的Linux用户也许需要去看下Fedora bugzilla,但这个bug的根源颇有些周折: Glibc开发者改动了memcpy()函数实现,它在理论上只是对目前的处理器进行优化,但不幸的是改动暴露了代码中的bug,开发者忽略了传递给memcpy()函数的源和目标数组不能重叠的规定.