chattr +i 是唯一能真正防止 root 修改文件的方式,它在内核 VFS 层拦截 write、unlink、rename 等所有写类操作,错误统一返回 Operation not permitted;而 chmod 444 仅控制 POSIX 权限,root 可完全绕过。

不能靠 chmod 444 真正防住修改——root 或 sudo 用户仍能覆盖、删除、重命名。要让文件“只能被读取不能修改”,必须用 chattr +i,这是唯一在内核 VFS 层拦截所有写类操作(包括 write、unlink、rename)的方式。
为什么 chmod 444 不够用
chmod 444 只是清掉所有用户的写位,属于 POSIX 权限检查,root 完全绕过它:
-
sudo echo "x" > file成功覆盖 -
sudo rm file成功删除 -
sudo mv file old成功重命名 - 容器里以 root 运行的应用(如 nginx、redis)照样能写
它只适合:多人共用普通账户的开发环境,或打包阶段临时锁定源码——前提是没人有 root 权限。
chattr +i 才是真·只读锁定
chattr +i 设置不可变(immutable)属性,内核直接拒绝任何修改动作,错误统一为 Operation not permitted:
- 必须用 root 执行:
sudo chattr +i /path/to/file - 验证是否生效:
lsattr /path/to/file应显示末尾带i(如----i--------e---) - 生效后:
echo、vim、sed -i、rm、mv全部失败 - 解除锁定只能显式执行:
sudo chattr -i /path/to/file,没有“临时放行”机制
注意:chattr +i 对目录也生效——加了 i 的目录,无法新建、删除、重命名任何子项(哪怕子文件本身没加 i)。
哪些文件适合加 i 属性,哪些绝对不能碰
加 i 前必须确认该文件是静态、极少变更、且修改需人工介入:
- 适合加:
/etc/passwd、/etc/shadow、/etc/sudoers、/boot/grub2/grub.cfg、/etc/ssh/sshd_config(但 reload 会失败,需先解锁) - 绝对不能加:
/var/log/*.log(rsyslog 直接崩)、/var/lib/mysql/(mysqld 启动失败)、/etc/resolv.conf(NetworkManager 无法更新)、任何包管理器预期覆盖的文件(如升级时的sshd_config) - 加之前务必备份:
cp /etc/sudoers /backup/sudoers.$(date +%s),加完i后连cp都会失败
日志类文件该用 a 属性,不是 i
如果目标是“允许追加、禁止覆盖”,比如 /var/log/myapp.log,用 chattr +a:
sudo chattr +a /var/log/myapp.log-
echo "msg" >> file成功;echo "reset" > file失败 -
+a仅 root 可设,且不影响已有内容读写,只拦截truncate和覆盖写 - 不要对整个日志目录递归加
+i,否则logrotate移动旧日志会失败
真正防改,不是选命令,而是选对层级:chmod 是用户层护栏,chattr +i 是内核级锁死——错一层,防护就失效;而一旦加错位置(比如给数据库目录加 i),服务直接起不来。


















