Linux 权限拒绝:用 chmod、chown、ACL 和 umask 排查无法读写
线上最常见的一类报错是 Permission denied。很多人第一反应是 chmod 777 或把属主改成 root,这样往往只是把问题盖住,还留下隐患。正确做法是先确认「哪个进程、以哪个用户、访问哪条路径」,再对照权限位、属主和 ACL。
先确认身份和目标
进程报权限错误时,先记下报错路径,再确认进程实际身份,不要默认就是当前登录用户:
ps -o user,uid,gid,cmd -p <PID>
id <用户名>
namei -l /path/to/file
ls -ld /path/to /path/to/file
namei -l 会把路径上每一级目录的属主和权限列出来。很多「文件本身看起来可写,却仍然失败」的原因,是中间某一级目录缺少执行位(x),内核走不到那一层。
对照属主、属组和权限位
ls -l /path/to/file
stat /path/to/file
先看文件属于哪个用户和组,再看进程是 owner、group 还是 other。权限是 640 时,同组可读不可写,其他人不可读;若服务跑在 app 用户下,而文件属主是 deploy,又不在同一组,写日志就会失败。改权限前先决定该改属主还是该改组:
chown app:app /var/log/app
chmod 640 /var/log/app/app.log
chmod 750 /var/log/app
不要一上来 chmod 777。目录对属主给 rwx、对组给 rx 通常就够用。改完用原来的用户测一次:sudo -u app touch /var/log/app/test,比只看数字更可靠。
新建文件权限不对,查 umask
有时目录权限没问题,应用新写出的文件却总是 600 或 640,导致其他进程读不到。这往往是 umask 在起作用。umask 会从默认权限里抠掉一些位:文件默认 666,目录默认 777,再减去 umask。
umask
sudo -u app bash -c 'umask; touch /tmp/t; ls -l /tmp/t'
交互 shell 的 umask 和 systemd 拉起的服务不一定相同。服务应在单元里用 UMask= 明确指定,不要假设会继承某个用户的 bashrc。需要组内共享写入时,目录可加 setgid:chmod 2770 /data/share,这样新建文件会继承目录的属组。
权限位看着对,再查 ACL 和特殊属性
ls -l 权限列末尾如果出现 +,说明还有 POSIX ACL,普通 chmod 看到的并不是完整规则:
getfacl /path/to/file
lsattr /path/to/file
用 setfacl 核对是否多授或漏授了某个用户。若文件被加上 i 不可变属性,即使用户是属主也无法写入或删除,需要先处理属性,而不是反复 chmod。还要排除只读挂载和安全模块拒绝,这些在审计日志里能看到,权限位本身可能完全正确。
小结
遇到 Permission denied,先用进程身份和 namei -l 把路径逐级核对,再决定是 chown、chmod 还是改组。新建文件权限异常查 umask 和 setgid;ls -l 带加号时补查 ACL,写不进再看不可变属性和安全模块。少用 777,按身份对号入座,这类故障会清晰得多。
- 点赞
- 收藏
- 关注作者
评论(0)