写了个Bug,误执行rm -fr /*,瞬间背后一凉( 三 )

  • 发现常用命令无法使用的时候 , 没有重启服务器 , 不然服务器就起不来了 , 也没有关闭 SSH 会话 , 不然无法在重新连接 SSH 会话了 , 也就无法进行操作了 。
  • 如果以上两点都没做好 , 服务器恢复的难度就加大了很多 , 更严重的是五一节就没的过了 。
    写了个Bug,误执行rm -fr /*,瞬间背后一凉
    本文插图
    预防误执行 rm -fr /*
    既然 rm -fr /* 是残忍的凶器 , 那么预防它是很有必要的 , 接下来跟大家讨论讨论预防它的几种方案 。
    方案一:rm -rf 删除目录时要判断目录
    #!/bin/bash work_path=`pwd` #如果目录不为空 , 才执行删除操作 if [ ${work_path} != '''' ];then rm -fr ${work_path}/* fi在执行删除目录操作前 , 先判断要删除的目录是否为空 , 不为空才执行删除操作 。
    方案二:Shell 脚本指定 set -u
    执行脚本的时候 , 如果遇到不存在的变量 , Bash 默认忽略它 。
    #!/bin/bash echo $a echo hello上面代码中 , $a 是一个不存在的变量 , 执行结果如下 。
    $ bash test.sh hello可以发现 , echo $a 输出了一个空行 , Bash 忽略了不存在的 $a , 然后继续执行 echo hello 。
    最好是遇到变量不存在 , 脚本应该报错 , 而不是一声不响地往下执行 。
    set -u 就用来改变这种行为 , 在脚本加上它 , 遇到不存在的变量就会报错 , 并停止执行 。
    #!/bin/bash set -u rm -fr $a/* echo hello运行结果如下:
    $ bash test.sh test.sh: line 4: a: unbound variable可以看到 , 因为 a 是未定义变量 , 脚本报错了 , 并且不再执行后面的语句 。
    方案三:safe-rm 替换 rm
    safe-rm 是一个开源软件工具 , 这名字听起来就很安全嘛 , 所以它是用来替代不太安全的 rm 。
    它可以在 /etc/safe-rm.conf 中配置路径黑名单 , 定义哪些不能被 safe-rm 删除 。
    我们可以将 safe-rm 更名为 rm , 假设定义了 /etc/ 无能被删除 , 那么删除 /etc 时就会报错:
    $ rm -rf /etc/ safe-rm: skipping /etc/方案四:建立回收站机制
    Windows 是有回收站的 , 即使误删了 , 也可以在回收站恢复 。 所以 , 我们也可以在 Linux 实现回收站的机制 。
    实现思路:
    • 删除文件时 , 它并不真正执行删除操作 , 而是将文件移动到一个特定目录 , 可以设置定时清除回收站 , 或者在回收站里面的文件大小达到一定容量时(或者用时间做判断)执行删除操作以腾出空间 。
    • 可以写个 Shell 脚本替换 rm 命令 , 或者在需要删除文件的时候使用 mv 命令将文件移动到回收站 。
    ① 创建回收站目录
    mkdir /home/.trash ② 编写 remove.sh 脚本 , 内容如下:
    写了个Bug,误执行rm -fr /*,瞬间背后一凉
    本文插图
    ③ 修改 ~/.bashrc ,用我们自建的 remove.sh 替代 rm 命令:
    alias rm=''sh /home/remove.sh'' ④ 设置 crontab , 定期清空垃圾箱 , 如每天 0 点清空垃圾箱:
    0 0 * * * rm -rf /home/.trash/* ⑤ 最后 , 执行以下命令 , 使之生效:
    source ~/.bashrc方案五:根文件挂载成只读
    在 /etc/fstab 文件 , 把 / 文件系统挂载成只读的方式 。
    写了个Bug,误执行rm -fr /*,瞬间背后一凉
    本文插图
    其中 remount,ro , 就表示只读的方式挂载 。
    只读的方式挂载后 , 进行删除操作是无法成功的:
    写了个Bug,误执行rm -fr /*,瞬间背后一凉
    本文插图
    事后反思
    涉及到 rm -fr 命令的代码 , 要留个心眼 , 要反复检查 , 要做好预防误执行 rm -fr /* , 并在测试机验证完后 , 再拖到实体机上跑 , 千万不可大意 。