事情的起因是这样的。。。
今天早上我们突然发现我们的跳板机干净
了很多。
什么叫干净了很多呢?就是原本下面非常多的临时文件,脚本、软件包统统不见了。
「为什么这么乱,就不要问了~ 公司在科技部的投入一直不够,历史原因」
当时的第一想法是:
哪位同学清理磁盘空间了,因为实在太干净了,只剩下几个必要的目录其它的文件全被删除了。「安全原因这里就不放图了」
很快我们发现事情可能不是想像中那么简单。。。。
因为,原来放在家目录下的脚本也被删除了。。。
这时,我们的第一想法是服务器被入侵了,毕竟遇事先找别人原因,但随后 dmesg
lastlog
简单排查就排除这块疑虑了,而且公司有专门的信安团队,我们暂且抛开这个维度。
但文件就是莫名消失了也太奇怪了,找不到问题心里也涔的慌。。。
既然磁盘文件大量丢失,所以排查磁盘容量监控这个维度是不错的角度。。
监控
果然,发现有两个可疑时间点。一个是 07/31 11:00, 一个是 08/02 05:00.
这两个时间点都有非常有特点,所以能提供更为精细的思路。都是整点!!
随后小伙伴反馈 07/31 11:00 的磁盘异常是人为手动清理磁盘,但家目录未做法理。那可疑点就只有 08/02 05:00 这个时间点了。
找到可疑点,接下来的排查就容易多了,
我们找到最近几天的所有rm
操作,不就行了?
命令历史
这一连串的操作下来,一番操作猛如虎,实际只有250.因为涉及到rm的操作实在太多了。有接近500
条。而且多少是正常的rm
.有些是cd
到某目录下的rm
.
按这维度查下来,今天一天怕是要耗在这。
回头想了想,还是回到了 08/02 05:00这个时间点,可疑性太大了。
crontab
排查crontab后,发现确实有凌晨5点的脚本,但这条crontab是上周五加入的,要出问题也应该是周六就出问题了,为什么今天早上才出现异常呢?
虽是这么想,但也只有他嫌疑最大了,所以还是从他下手了
但大家有没有发现一个问题...那就是这个脚本也是存放在家目录下的?。。。
也就是这个脚本也被删除了。死无对症。。。。
好在,写脚本的同学本地有保留。原脚本「脱敏后」内容如下:
week=`date +%w`
#每周6备份一个,保留25周(半年),然后每天替换报存一个最新备份,防止最坏情况主机故障导致前七天没备份
if [[ "$week" == "6" ]];then
cd /mnt/bak; ls -tr | head -n -25 | xargs rm
file=`/usr/bin/ssh root@ip_host "ls -rt /opt/backups |tail -1"`
echo "`date` Now backup $file"
scp root@ip_list:/opt/backups/$file /mnt/backup/bak/ && echo "`date` $file ok" >/tmp/backup.log||echo "`date` $file fail" >/tmp/backup.log
else
cd /mnt/bak_lastest;ls -tr|xargs rm
file=`/usr/bin/ssh root@ip_list "ls -rt /opt/backups |tail -1"`
echo "`date` Now backup $file"
scp root@ip_list:/opt/backups/$file /mnt/backup/bak_lastest/ && echo "`date` $file ok" >/tmp/backup.log||echo "`date` $file fail" >/tmp/backup.log
fi
/mnt/bak
删除25条旧文件,再备份/mnt/bak_lastest
,删除所有文件,再备份。好了,这样就能解释为什么脚本是周五加入,但一直到周日才出问题的原因了。因为,除了crontab做了定时时间,脚本里也做了时间判断。
如果脚本周五加入,周六没出问题,周日出了问题,那么可以确定肯定是 else
逻辑出问题了。
仔细看了下眼,瞬间恍然大悟!!!。。。。。
经常写脚本的同学应该已经知道问题所在了。
大家看这条语句
cd /mnt/bak_lastest;ls -tr|xargs rm
问大家一个问题,如果 /mnt/bak_lastest
不存在,会发现什么问题...
是的。
脚本在删除脚本所在目录的匹配到的所有文件。。。。
至此,真相大明,也真诚的感受到了什么叫“前人挖坑,后人跳了”。。哈哈
原来,最近业务在做nfs
归档,旧的nfs
的文件要逐步迁移到新的nfs
上。所以运维同学便修改了一些备份脚本,对脚本中的旧目录做了目录批量替换。
这项工作原本应该由脚本作用完成,但实际工作中可能并不会如意,比如员工离职等情况再正常不过。
所以,碰到修改别人脚本或代码的时候,一定要小心再小心。这其实是软件工程学里经常会遇到这样的 《成本沉没》 问题。就是老代码没人愿意维护,宁愿写一套新的也不愿意修改,宁愿重写新功能,也不愿意改别人代码的现象。
类似如上问题其实有很多,最精典的案例可能是如下的删系统根脚本了。
#!/bin/bash
ABC_PATH=abc
/bin/rm -rf ${ABC_PATH}/
如上脚本其实有非常大的风险,且在企业中一再发生,尤其多发生在老手身上。
ABC_PATH
如果这个变量因为某些原因取不到会发生什么事情。是的,命令会变成
/bin/rm -rf /
如果有同学讲,Linux
在系统层已经屏蔽了这个命令,那如果脚本是如下这样,后果相当酸爽
#!/bin/bash
ABC_PATH=abc
/bin/rm -rf ${ABC_PATH}/*
我想,你应该看懂了吧。。
那么这个简单的脚本应该怎么优化呢?其它大家多一点点思考就可以完全避免这个问题了
优点:不会造成毁灭性伤害, 缺点:但不是所有公司都有这样的实力存储永久性问题
#cd /mnt/bak; ls -tr | head -n -25 | xargs rm
find /mnt/bak/ -name "*backup.tar" -a -ctime +25 -exec rm -f {} \;
必须有文件名匹配 必须指定好目录 必须多方黑折盒逻辑测试
cd /mnt/bak; ls -tr | head -n -25 | xargs rm
cd /mnt/bak && ls -tr | head -n -25 | xargs rm
相对来讲, && ||
比;
要好很多。建议加强使用,避免;
的无脑使用
0 5 * * * /bin/bash /root/backup_git_new.sh >> /tmp/backgit_new.log 2&>1
优化为
0 5 * * * /bin/bash -x /root/backup_git_new.sh >> /tmp/backgit_new_`date +\%Y\%m\%d-\%H\%M\%s`.log 2&>1
即详细日志输出,又按日期做好标识
0 5 * * * /bin/bash -x /data/sa/cronscript/backup_git_new.sh >> /tmp/backgit_new_`date +\%Y\%m\%d-\%H\%M\%s`.log 2&>1
解决本次自身脚本被删除的问题。且良好的规范有助于解决”乱“的问题
0 1 * * * /bin/bash -x /data/sa/cronscript/backup_script.sh >> /tmp/backup_script_`date +\%Y\%m\%d-\%H\%M\%s`.log 2&>1
前人栽树后人乘凉,前人挖坑后人填