Linux权限报错排查:从文件权限到安全策略的六步定位法
运维中遇到 Permission denied 或 Operation not permitted 时,按身份确认、文件权限、进程用户、SELinux/AppArmor、内核限制、服务特殊场景六步排查,快速定位根因并修复。
遇到 Permission denied 先别急着改权限,确认触发错误的身份和完整路径。到报错现场执行 whoami 和 id,核对当前用户和所属组。再翻日志把完整路径抠出来,别只看半截报错。比如 Nginx 报 403,大概率是静态文件没给读权限;SSH 密钥登录失败,先检查 ~/.ssh 是否 700、authorized_keys 是否 600,权限放太开反而会被拒绝。
第二步:逐层核对文件权限
用 ls -l 扫一遍目标路径,重点核对读、写、执行三位是否够用。目录没有 x 权限是进不去的,这点容易忽略。部分服务对权限有硬性要求:SSH 的 ~/.ssh 必须 700,authorized_keys 得 600;MySQL 配置文件如果 other 可读会直接报警。改权限用 chmod,属主不对用 chown 调整。注意别让普通用户进程去操作 root 属主的文件,某些场景下即使 777 也过不了安全策略。
第三步:确认进程实际运行用户
文件权限对了还不够,得看进程跑在哪个用户下。用 ps aux 过滤服务名,确认 worker 进程的用户身份。比如 php-fpm 的 pool 用户对 session 目录没写权限,登录状态就存不进去;Nginx worker 对站点目录没读权限,静态资源照样 403。如果进程跑在 nobody 下而文件属主是 root,要么改服务配置里的 user 指令,要么把文件属主改成进程用户,二选一。
第四步:排查 SELinux 和 AppArmor
CentOS/RHEL 上权限明明对了还是被拒绝,大概率是 SELinux 在拦。临时执行 setenforce 0 切到宽容模式测试,故障消失就坐实了。接着用 ausearch -m avc -ts recent 或 sealert 查看具体拒绝日志,用 chcon 或 semanage fcontext 改文件上下文,必要时用 audit2allow 生成策略模块加载。Ubuntu/Debian 同理,aa-status 查看哪些进程被 AppArmor 管控,aa-complain 临时切抱怨模式定位,再到 /etc/apparmor.d/ 下改配置重载。生产环境别直接关闭安全策略,定位完记得补规则。
第五步:检查内核能力与参数限制
有些报错连 root 都绕不过,得往内核层面查。普通用户绑 80 端口会失败,可以给二进制文件打 setcap cap_net_bind_service=+ep,或调 net.ipv4.ip_unprivileged_port_start。dmesg 里出现 denied 字样,可能是 kernel.yama.ptrace_scope 等安全参数在起作用。排查时把 /etc/sysctl.conf 里最近改过的可疑项先注释掉,sysctl -p 应用后复测,缩小范围比盲目改配置靠谱。
第六步:典型服务踩坑排查
MySQL 数据目录不光要 mysql 用户能读写,上级目录也不能卡它进去;自定义数据路径时 SELinux 上下文一定记得同步改。Docker 挂主机目录时,容器内 uid 和宿主机对不上是常见问题,要么构建镜像时对齐用户 id,要么挂卷前 chown -R 把目录改成容器进程对应的 uid。Nginx 上传文件失败,除了检查 php 配置,还可能是 client_body_temp_path 临时目录没给 worker 用户写权限。排查时对照官方文档给最小权限,别一上来就 777。