今天临近下班时,测试部门突然对我说,我们的系统重启(Linux系统)后无法启动了。

   吃了晚饭便去公司排查问题,看了从串口输出的系统启动日志后,发现在加载完网卡驱动后,就卡住再也不输出了,于是第一反应便认为可能是网卡驱动不兼容当前这个硬件。但反过来推导一下,之前不都启动的很正常,而且这台设备也已经投入测试有一两个星期了,于是便否定了这种猜测。

   认真查看了下系统启动的输出日志发现,这个脚本的启动顺序刚好在我们自己写的网卡IP配置脚本和SSH服务脚本之前,不得不说运气真背。现在的情况是:无法从串口进入后台系统,也无法用ssh工具进行登录,系统确实已经初始化完成了,只是应用程序无法启动!

   这可真是一个不幸的消息,同时也是一个幸运的消息。不幸是因为,我们的设备都是经过封装的,如果这个时候要进系统后台,得把设备用螺丝刀把螺丝卸掉,搬台显示器接上,键盘架上。幸运的是,这样的问题还没到客户现场。经过十几分钟的操作,终于准备就绪,接上电源,2U设备的上电轰鸣声确实有点给力。

   几分钟后,系统顽固的又卡在之前看到的最后的串口输出界面。tty0是没法进了,只得按ALT+F2进入第二控制台。试着输入ps  ls  cat都可以看到输出,运气还算没背到家。试着输入ifconfig,shit!居然没有任何输出,连圆环接口lo都没显示,再一次证明了之前的判断是正确的,网卡还没正常初始化!

   这个时候ps命令简直就是救命稻草了,先ps aux看下进程到底卡在哪里了,发现是在启动第五个脚本的时候卡住了,而且tty0屏幕上没有任何错误提示,肯定是该死的command > /dev/null 2>&1 .

   此时可以推断出应该是在启动第5个脚本和启动第6个脚本之前。手动运行下第5个启动脚本,结果跟还是tty0上的结果!没办法,硬着头皮跟进去吧,啊,好多的if  else 各种判断。只好按我以前的经验,截断验证,echo真是个好东西,隔一段code ,echo一下,最终定位到一个脚本,这就是罪魁祸首了,跟进去,发现它的功能是扫描一个目录下的所有软件,并生成对应文件名+xml扩展名结尾,而且这个脚本是我写的!!里面代码我还记得,当时我为了赶进度,直接copy的另一个脚本里的功能代码,都没经过仔细推敲,好吧,我单独run你!果然是它卡住了,先把这个脚本的核心代码弄上来,免得不好讲下文了:

#!/bin/bash
SOFT_PATH=/var/www/html/
XML_PATH=/var/www/html/softxml
cd SOFT_PATH/soft
FILE=$(ls *)
for file in $FILE
do
    echo "Process $file..."
    md5=$(md5sum $file | awk '{print $1}')
cat >$XML_PATH/$file.xml<<EOF
<MD5>
    <SOFT>$md5</SOFT>
</MD5>
done

   这个里面有好几处错误。

   第一,当soft目录下文件名带有空格的时候,for循环会把空格当作文件名分隔符,这是bug1

   第二,当文件名以-开头时,如:-12.txt for循环内部也会产生恐慌。bug2

   第三,本次灾难的源头,当文件名为: guozi - 12.txt里,“-”前后包含空格。脚本就会卡住,也就是系统加载启动脚本时,无法继续运行了!!如下图:

shell脚本实战——大灾难源于小细节,由文件名中的“-”引发的灾难_Linux

其实这就是在以下语句卡住了:

md5sum - | awk '{print}'

让我们来看一看为什么会卡住,输入命令md5sum --help查看:

shell脚本实战——大灾难源于小细节,由文件名中的“-”引发的灾难_Linux_02

发现当格式为:md5sum - 时,是从终端读取字符,也就是等待用户进行输入,当系统启动时,谁来输入呢?当然是无限期的傻傻等待了。

当我们输入以下命令:完了后以CTRL+D结束时就能看到输入字符的MD5值了:

#md5sum -
hello   #在这里回车 并按CTRL+D
b1946ac92492d2347c6235b4d2611184  - #输出结果

把修改后的脚本也搬上来吧

#!/bin/bash
SOFT_PATH=/var/www/html/
XML_PATH=/var/www/html/softxml
cd $SOFT_PATH/soft
ls ./* | while read file   #这里的./是有用意的哦,不信自己去实践下吧,呵呵
do
    echo "Process $file..."
    md5=$(md5sum "$file" | awk '{print $1}')  #注意这里的双引号
cat >$XML_PATH/$file.xml<<EOF
<MD5>
    <SOFT>$md5</SOFT>
</MD5>
done

   最后总结一下:当我们觉得自己基础已经掌握好了的时候,往往就是产生bug的根源,这个时候我想起以前看别人教程时的一句话:你们没基础的就是最好的基础,那些有基础的往往学不好,为什么呢? 回过头来想一想,其实道理很简单,那就是有基础的总喜欢跳着学,以致于错误过很多细节,没基础的,反而会稳打稳扎,从而把知识掌握的很透彻。细节决定成败,从这一次的排错来看,虽然花了一晚上的时间,用来解决问题并总结问题,这已经算是最大的收获了!