背景
在执行shell脚本的时候,常常是将日志一行行的输出。但是对于一些需要观察服务状态的执行结果的时候,一行行的输出会导致日志看起来很不友好。有没有办法让日志输出不换行呢?
分析
我们常常可以看到这样的效果:
iptables: Applying firewall rules: [ OK ]
在日志输出开始时,输出的是:
iptables: Applying firewall rules:
当操作完成的时候,就会输出OK,并在前面一行在末尾加上。
这样让人看上去两次的日志是有关联的,非常友好。
然而我们平时输出日志时没有考虑输出的显示问题,结果类似这样:
iptables: Applying firewall rules
OK
如果日志输出的不规范,很多时候都无法将这两行关联到一起。或者说这个OK到底是什么操作的结果都无法辨别。所以往往都要去看原始的脚本来确定。这样往往增加了维护的成本。
在shell中,输出日志使用最多的就是echo。
默认情况下,echo就是将指定的内容输出为一行。输出多次,就形成了多行。
在《Shell中echo输出带有颜色的日志的实现方法》一文中,我介绍了echo实现有颜色输出的效果,用的是echo的-e参数。而换行参数则用的是-n。
假如我们现在要输出如下的内容:
restart iptables service: OK
now, go!
我们要先输出restart iptables service:,然后执行重启iptables服务的操作,并将结果追加到第一行。第一行输出完毕后,再将结果输出为一整行。
下面是示例shell代码:
echo -n "restart iptables service:"
service iptables restart 2>&1 1>&/dev/null
if [ "$?" == "0" ];then
echo " OK"
echo "now, go"
else
echo "FAIL"
exit 1
fi
在重启iptables服务后,使用$?对结果进行判断,如果结果为0则表示操作成功,如果失败则不为0。判断之后再决定如何往后输出。只有成功了才能输出OK,以及输出第二行的结果。如果失败了,就只输出FAIL,并执行exit 1,用1作为退出码。失败了就不要继续往后执行了。
2>&1 1>&/dev/null
这一句的作用是将标准错误重定向到标准输出,再将标准输出重定向到/dev/null设备。说人话就是,不输出重启iptables服务的任何日志,以免干扰下面的日志的输出,变得混乱。而我们可以根据命令执行的返回码来判断成功与否。
需要注意的是,echo的输出是接着上一次的输出的末尾的。也就是说,第一个echo使用了-n参数,那么第二个不需要-n参数就可以在第一个的日志结尾输出。输出完后就换行了。
效果:
别看这一小段代码,这是一段规范性的脚本。而据我发现,很多写脚本的同学,其实都只是简单堆命令而已,完全不知道规范脚本。即使前面报错飞起,最后还提示执行成功。
请不要笑,这种事情正发生在互联网的大厂里哦。shell编程和shell脚本以及linux命令很多人都分不清楚。别小看echo一个参数,我并不是小题大做。但是你会用这个,都能和很多人拉开差距。往往高手写出来的脚本,规范整齐,日志有条不紊,清晰明了。脚本绝对不是简单的命令堆砌,逻辑和一般编程语言一样严密。或者你只看日志输出就可以判断一个人的shell脚本的水平。
这里分享的echo输出多行,也就是一个细节。当大量细节积累之后,你就会有一览众山小的感觉了。
总结
日志换行和不换行,会让日志看起来天差地别。好的日志看起来如沐春风,不好的日志看起来让人狂躁不已。