Linux shell 误操作
shell脚本在日常运维中是必不可少会应用到,下面是自己亲身经历过的一件事。会了定期清除日志,编写了一个shell脚本,内容如下:
[root@centos-01 tmp]# more remote_log.sh #!/bin/bash # # PRO_LIST="/tomcat-6.0.53/logs" #move file for PRO_PATH in $PRO_LIST do if [ ! -d $PRO_PATH ];then echo "-----$PRO_PATH path no exist-------" break
else find $BAK_PATH/* -type f -mtime +60 -exec rm -rf {} \; fi done
内容很简单,大家应该能发现问题,其中倒数第三行中$BAK_PATH 变更是不存在的。
以上脚本如果在服务器上运行的话就惨了。
下面是我在测试环境下做的实验,大家都不要测试了。其实是我在生产中遇到的,当时蒙了一瞬间,立刻按下了ctrl+c。但发现系统在次登录已经无法登录了,很多命令无法使用,还好当时有一个终端在连接着,查看了一下发现/bin目录下的文件被删除了一部分。后来我通过sftp命令从别的系统上下载了/bin目录下的文件。系统基本是恢复了。这次还好是幸运的。
[root@centos-01 tmp]# sh remote_log.sh rm: cannot remove ‘/home/w_nfs/test’: Permission denied rm: cannot remove ‘/media/CentOS_BuildTag’: Read-only file system rm: cannot remove ‘/media/EFI/BOOT/BOOTIA32.EFI’: Read-only file system rm: cannot remove ‘/media/EFI/BOOT/BOOTX64.EFI’: Read-only file system
执行上面的脚本后,会随机删除系统上的文件。
经过这次事故后,我深深的爱上了以下两行命令
set -o nounset
在默认情况下,遇到不存在的变更,会忽略并继续执行,而这往往不符合预期,加入该选项,可以避免恶果扩大,终止脚本的执行。
set -o errexit
在默认情况下,遇到执行出错,会跳过并继续执行,而这往往不符合预期,加入该选项,可以避免恶果扩大,终止脚本的执行。
增加会脚本如下
#!/bin/bash # set -o nounset set -o errexit PRO_LIST="/tomcat-6.0.53/logs" #move file for PRO_PATH in $PRO_LIST do if [ ! -d $PRO_PATH ];then echo "-----$PRO_PATH path no exist-------" break else find $BAK_PATH/* -type f -mtime +60 -exec rm -rf {} \; fi done
执行结果如下,这样做安全多了。ansible-playbook 就显得更友善一些。
[root@centos-01 tmp]# sh remote_log.sh remote_log.sh: line 13: BAK_PATH: unbound variable