chattr +i 是唯一真正让目录不可删除的方法,它通过内核 VFS 层拦截 unlink() 和 rename() 系统调用,使 rm -rf、mv、rmdir 全部失败并报“Operation not permitted”,且父目录加 i 后其下所有新建、删除、重命名操作均被拒绝。

chattr +i 是唯一真正让目录不可删除的方法
目录加 +i 后,rm -rf、mv、rmdir 全部失败,报 Operation not permitted——不是权限问题,而是内核 VFS 层直接拦截 unlink() 和 rename() 系统调用。这和文件加 +i 本质一致,但影响范围更大:父目录带 i,其下所有新建、删除、重命名操作都会被拒,无论子项本身有没有属性。
常见误操作:
-
chattr +i /etc/ssh后,sshd重启可能生成临时密钥失败,导致服务无法启动 -
chattr -R +i /path不等于“递归锁定所有子项”——-R只对当前命令执行时已存在的条目生效;后续新建的文件/目录不会自动继承i,但因父目录已锁,它们根本建不进去 - 用
chattr +a或+d对目录加锁?无效。+a仅对普通文件有意义(强制追加),+d在目录上不生效
执行前必须验证的三件事,缺一不可
命令返回 success 不代表真生效。静默失败是常态:
- 运行
df -T /path/to/dir,输出文件系统类型必须是ext4或xfs;nfs、tmpfs、btrfs(默认)、overlayfs(Docker 容器常见)均不支持i属性 - 检查挂载选项:
mount | grep "$(dirname /path/to/dir)",结果里不能含ro(只读挂载)或user_xattr=0 - 必须由真实 root 执行,不能在
chroot、LXC 容器或 systemd-nspawn 等受限命名空间里——否则lsattr看不到i,且解锁也无效
lsattr 显示 i 却仍能删?先查这几个点
lsattr /dir 输出含 i,但 rm -rf /dir 成功,说明锁没起作用:
- 你锁的是符号链接本身,不是目标目录:运行
readlink -f /dir确认真实路径,再对那个路径执行chattr +i - 目录所在分区是只读挂载:
mount | grep "$(dirname /dir)"若含ro,chattr实际被忽略 - 目录正被某个进程以写方式打开(如 tail -f 日志、rsync 正在同步),某些内核版本下
chattr +i会阻塞直到所有 fd 关闭
解锁必须和加锁路径完全一致
加锁用了绝对路径,解锁就不能用相对路径或软链接名:
- 错误:
chattr +i /etc/sudoers→chattr -i sudoers(相对路径,失败) - 错误:
chattr +i /etc/ssh→chattr -i ssh(同上) - 正确:
chattr -i /etc/sudoers、chattr -i /etc/ssh - 目录加了
i后想删子项?不行。必须先chattr -i /parent,再处理子项——不能跳过父目录直接操作内部
真正难的不是命令怎么敲,而是加完 +i 后,你是否清楚这个目录现在连 touch 都会失败,以及下次系统更新或服务重载时会不会卡住。


















