一个文件的权限看着没有问题,读取它却提示 Permission denied。先别急着给文件加权限:到达这个文件的路径,也要允许你通过。
这次用普通用户、临时目录和一份自建文本做了三组小实验。没有修改系统目录或线上文件,也不把这个结果说成某次真实服务故障。
目录的 r 和 x 不是一回事
对普通文件,r 表示读内容,x 表示执行;对目录,r 用来读取目录项名称,x 则是搜索、穿过目录的权限,不是“执行这个文件夹”。GNU chmod 手册明确区分了目录的 search 含义。[4]
Linux 解析路径时,会逐级检查目录。如果当前查询目录没有搜索权限,就可能返回 EACCES,即 Permission denied。文件本身可读,不会跳过上层目录的检查。[2]
三组权限,出现两种相反现象
实验中的文件始终归当前用户所有,权限为 600,内容是 hello。只改变它外层目录的权限;上层临时目录保持可访问。
- 目录 400(只有 r):
ls -1能列出 note.txt,但cat无法读取它。 - 目录 100(只有 x):
ls -1无法列目录,但已知准确文件名时,cat能读到 hello。 - 目录 500(r 与 x):两项操作都成功。
第一组说明“看得到名字”不代表“能访问文件”;第二组说明“不能列出目录”也不代表“已知路径一定打不开”。注意这里用的是只列名称的 ls -1,不是还需要读取各文件信息的 ls -l。
怎样在自己的临时目录里验证
用普通用户在可写位置运行下面的 Bash 片段。它只操作新建的临时目录;不要把变量改成自己的资料目录,也不要用 sudo。实验环境是 Linux 与 GNU Coreutils 9.4。
root=$(mktemp -d) || exit 1 box="$root/box" mkdir "$box" printf 'hello\n' > "$box/note.txt" chmod 600 "$box/note.txt" trap 'chmod 700 "$box"; rm -r -- "$root"' EXIT chmod 400 "$box" ls -1 -- "$box" # 能看到文件名 cat -- "$box/note.txt" # Permission denied chmod 100 "$box" ls -1 -- "$box" # Permission denied cat -- "$box/note.txt" # hello chmod 500 "$box" ls -1 -- "$box" cat -- "$box/note.txt"
这是包含预期失败的演示,不要加 set -e,否则可能在第一个预期错误处提前结束。目录清理会先恢复其所有者权限,再移除本次创建的临时树。
排障时先看路径,不要一把改成 777
实际检查应先确认“谁在读”:终端用户和服务运行账号可能不同。再检查每一级父目录能否搜索,最后才看目标文件的读权限。只补缺少的权限,不把递归开放整棵目录当成默认修复。
这个实验只说明普通权限位的关系。root 或具有相应能力的进程、访问控制列表(ACL)、安全模块和网络文件系统规则,都可能改变实际结果。路径权限检查通过,也不等于其他限制不存在。
文件能否打开,要同时看文件本身和通往它的路。把这两层分开,才不会在错误对象上反复改权限。
资料核验:2026年10月22日。结果来自已执行的隔离小实验,临时目录已清理。本文由 AI 辅助整理。