别改 rm 本身,而用别名、trash-cli 或 chattr +i 防护;alias rm='rm -i' 在脚本和非 TTY 环境失效,且不防 -f;trash-cli 移动文件至回收站,全场景生效;chattr +i 是唯一内核级防护,连 root 也无法删除。

直接上结论:别改 rm 本身,而是用别名、封装或替代工具控制行为;chattr +i 是唯一能真正拦住 rm -rf 的内核级手段,但必须慎用。
alias rm='rm -i' 为什么不够用
这个别名看似简单有效,实际在脚本、管道、非交互终端里完全不触发提示——rm -i 只在标准输入是终端时才问你“remove file?”,否则静默执行。更麻烦的是,一旦你在某个子 shell 或容器里忘了加载 ~/.bashrc,它就彻底失效。
- 它对
rm -f、rm -rf无效:加了-f就强制跳过确认 - 无法防护变量为空导致的路径塌缩,比如
rm -rf $DIR/*中$DIR未定义 → 变成rm -rf /* - 多人共用服务器时,每个用户都得单独配置,root 用户默认不读普通用户
.bashrc
trash-cli 替代 rm 是最实用的日常方案
它不删除文件,而是把文件移到 ~/.local/share/Trash 下,保留原始路径结构,支持恢复。关键是它不依赖交互,所有场景(脚本、cron、SSH 非 TTY)都生效。
- 安装后直接用
trash命令:比如trash important.log - 清空回收站用
trash-empty,支持按天清理:trash-empty 7(清空 7 天前的) - 想批量恢复?
trash-list查看条目,再用trash-restore选编号还原 - 注意:它不能跨文件系统移动(比如从
/home到/mnt/usb),会退化为复制+删除
chattr +i 是唯一能硬扛 rm -rf 的方案
这个属性由 ext2/3/4/xfs 文件系统内核实现,不是 shell 层面的障眼法。一旦设置,连 root 执行 rm、mv、echo > file 都会报 Operation not permitted。
- 锁定单个文件:
sudo chattr +i /etc/sudoers - 锁定整个目录(含子项):
sudo chattr +i /etc/ssh—— 注意:这会让 sshd 启动失败,如果它需要写临时密钥 - 只禁删除、不禁修改?用
+d:sudo chattr +d /var/log/audit.log - 检查是否生效:
lsattr /path/to/file,输出里有i或d字符才算成功
别碰 --no-preserve-root 和递归变量拼接
这两个是绝大多数惨案的直接导火索,不是配置问题,是操作习惯问题。
-
rm -rf / --no-preserve-root这种命令,只要出现在任何脚本、历史记录或自动化任务里,就是定时炸弹 - 所有带
*或/*的rm -rf必须包裹变量判断:[ -n "$LOG_DIR" ] && rm -rf "/var/log/$LOG_DIR/" - 生产环境脚本开头加防护:比如
set -u(未定义变量报错)、set -e(命令失败即退出) - 别信“我就删一行”,
rm -rf $DIR和rm -rf $DIR/在$DIR为空时结果完全不同
真正难的不是加保险,而是让保险在所有上下文里都起作用——别名只管交互式 shell,trash-cli 覆盖大部分场景,chattr +i 守住最关键的几个文件。其它都靠写脚本时多敲两行判断,和每次敲 rm 前下意识盯三秒路径。











