一次 RM -RF 引发的“惨案”

最近在产品上清理日志的时候不小心把产品的一个重要目录给清空了,导致程序一段时间内运行异常。所以在这里和大家分享一下,以此为鉴,务必谨慎使用rm -rf命令。

事情的经过是这样的,当天下午大概14点左右磁盘报警,占用超过了85%, 经排查发现是/alidata1/setupTms3/jboss-eap-6.4/%LOG_DIRECTORY%/tire2e/这个目录下的indexInitializer.log文件较大, 有两三个,每个占用了几个G的磁盘空间,查看log4j.xml发现是log level设置为了DEBUG,所以导致输出了很多日志,于是修改了log4j.xml中的配置,但是由于这个配置需要上版本之后才能生效,所以在上版本之前我先通过命令rm -rf /alidata1/setupTms3/jboss-eap-6.4/%LOG_DIRECTORY%/tire2e/indexInitializer.log.*将该日志给删除了,以腾出部分的磁盘空间,然后又配置了一个定时任务去清理该日志,防止磁盘再次报警,于是通过crontab -e添加了一个每天下午五点的定时任务0 17 * * * rm -rf /alidata1/setupTms3/jboss-eap-6.4/%LOG_DIRECTORY%/tire2e/indexInitializer.log.*, 事情到这里还是挺顺利的,但是下午五点定时任务执行后,“惨案”发生了,目录/alidata1/setupTms3/jboss-eap-6.4/被清空,从而导致Jboss中的应用程序运行异常,事后通过大概2-3个小时时间才恢复了该目录,并重启了应用, 从而解决了这个“惨案”。

在应用恢复之后,我就在想为什么我的命令明明是清理indexInitializer.log.*这些文件,但是最后却把jboss目录给清空了呢? 于是就去查了一下cron job的日志:

Jul 21 17:00:01 tmsprod4 CROND[26461]: (root) CMD (rm -rf /alidata1/setupTms3/jboss-eap-6.4/)

发现实际上17点运行的命令是rm -rf /alidata1/setupTms3/jboss-eap-6.4/,这也就解释了为什么jboss目录会被清空,但是为什么rm -rf /alidata1/setupTms3/jboss-eap-6.4/%LOG_DIRECTORY%/tire2e/indexInitializer.log.*命令在执行的时候变成了rm -rf /alidata1/setupTms3/jboss-eap-6.4/呢? 进一步查看的crontab的文档(man -f crontab),找到了这样一段说明:

The "sixth" field (the rest of the line) specifies the command to be run. The entire command portion of the line, up to a newline or a "%" character, will be executed by
/bin/sh or by the shell specified in the SHELL variable of the cronfile. A "%" character in the command, unless escaped with a backslash (), will be changed into newline
characters, and all data after the first % will be sent to the command as standard input.

从这一段描述可以看出,% 在没有被\转义的情况下,会被替换为换行符, 而且%之后的内容会作为输入传递给%之前的命令。到这里问题的原因就清楚了,因为路径中包含了%, 从而导致命令被分割成了两部分rm -rf /alidata1/setupTms3/jboss-eap-6.4/LOG_DIRECTORY%/tire2e/indexInitializer.log.*, 前面回报crontab执行,后面则是前面命令的输入。所以最后导致jboss的目录被清空。

虽然最后问题解决了,原因也查到了,但是还是提醒一下大家谨慎使用rm -rf, 或者使用mv移动文件到某个deleted的文件夹,然后定时清空该文件夹,这样可以保证文件在一定时间内还能恢复。
另外通过这次事件也发现了自己的一些不足,还需要努力学习!!