drwxr-xr-x 是什么意思?Linux 权限 755 详解
逐字符解析 drwxr-xr-x,说明目录权限为何对应 755、目录上的 x 为何表示进入或遍历,并解释为什么 chmod 777 不是正确的修复方法。
drwxr-xr-x 的含义
drwxr-xr-x 表示一个目录:其所有者可以修改目录内容,其他用户都可以读取并进入该目录,但不能修改其中的内容。用八进制表示时,该权限模式为 755。Linux 会在每行 ls -l 输出的开头显示这 10 个字符。它们始终按相同顺序表示相同含义,因此掌握这一字符串后,就能理解所有类似权限字符串。
有一条规则优先于其他规则,因为它决定了您自己的测试是否有意义。root 用户不受权限位限制。内核向 root 授予 CAP_DAC_OVERRIDE 能力(绕过自主访问控制),因此 root 可以打开权限模式禁止访问的文件。本页中的所有示例对 root 都会成功,无论权限位如何设置。要观察这些规则实际生效,请使用普通用户登录。
逐个理解这10个字符
创建一个目录和一个文件供查看。以下操作不会影响新目录以外的任何内容。
mkdir -p ~/permdemo/inner
printf 'hello\n' > ~/permdemo/inner/notes.txt
ls -ld ~/permdemo ~/permdemo/inner ~/permdemo/inner/notes.txt在常见的默认 umask 022 下,两个目录行以 drwxr-xr-x 开头,文件行以 -rw-r--r-- 开头。
第1个字符表示文件类型,不是权限。d 表示目录。- 表示普通文件。l 表示符号链接。c 和 b 分别表示字符设备节点和块设备节点。s 表示套接字,p 表示命名管道。它位于八进制值之外,因此 drwxr-xr-x 会变成 755,而不是以 d 开头的值。
后面的9个字符分为3组,每组3个字符,顺序始终不变。
- 第2至第4个字符是 owner 三元组,适用于文件所有者的权限位。
- 第5至第7个字符是 group 三元组,适用于文件所属组的权限位。
- 第8至第10个字符是 other 三元组,适用于其他所有用户的权限位。
在一个三元组中,各位置始终依次表示 r、w 和 x;短横线表示对应权限位未启用。字母的位置不会改变。r-x 表示可读但不可写。-w- 表示可写但不可读,这是合法但少见的权限组合。
因此,drwxr-xr-x 可拆分为:目录的 d,所有者的 rwx,所属组的 r-x,以及其他用户的 r-x。
某些系统会显示第11个字符。末尾的点号 drwxr-xr-x. 表示文件带有 SELinux(security enhanced Linux)上下文。Fedora 和 Rocky 等 SELinux 发行版默认会显示该字符。末尾的加号 drwxr-xr-x+ 表示文件带有 POSIX ACL(access control list),即除这9个权限位之外的另一组规则。使用 getfacl <path> 查看这些额外规则。
目录上的 r、w 和 x 作用不同
这是初学者最容易理解错误的规则。文件和目录使用相同的字母,但它们授予的权限不同。
- 文件上的
r用于读取内容。目录上的r用于列出其中的名称,普通的ls需要此权限。 - 文件上的
w用于修改内容。目录上的w用于在其中添加和删除目录项。删除文件会修改目录,因此决定是否可以删除文件的是目录的写权限,文件自身的权限模式不起作用。 - 文件上的
x用于将其作为程序运行。目录上的x用于遍历目录,也就是内核可以在路径查找过程中解析其中的一个名称。
遍历是最容易让人困惑的部分。目录上的 x 不会执行任何操作。打开 /srv/site/index.html 需要对 / 具有 x,然后对 /srv 具有 x,再对 /srv/site 具有 x,最后对文件具有 r。如果路径中的某个目录缺少您所需的 x,查找就会在那里停止。即使路径末尾的文件对所有用户可读,调用方仍会针对整个路径收到 Permission denied。namei -l /srv/site/index.html 会以模式和所有者信息显示路径链中的每一步,因此您可以看到具体在哪一环停止。
目录具有 r 但没有 x 时,会处于一种值得识别的异常中间状态。普通用户可以列出名称,因为列出名称由 r 授予;但无法对任何目录项执行 stat,因此 ls -l 会在大小和模式列中填入问号,并为每个目录项打印 ls: cannot access ...: Permission denied。
将字母形式转换为 755
每组三个位表示一个三位二进制数。r 为 4,w 为 2,x 为 1。将已启用的位相加。
rwx为 4 + 2 + 1 = 7rw-为 4 + 2 = 6r-x为 4 + 1 = 5r--为 4---为 0
因此,drwxr-xr-x 对所有者为 7、对组为 5、对其他用户为 5,即 755。-rw-r--r-- 为 6、4、4,即 644。drwxrwxr-x 为 7、7、5,即 775;它相当于在 755 的基础上为组添加写权限。您无需手动计算字符,因为 stat 会同时显示这两种形式。
stat -c '%A %a %U %G %n' ~/permdemo ~/permdemo/inner/notes.txt%A 是字母形式,%a 是八进制形式,%U 和 %G 分别表示所有者用户和所有者组。
人们经常搜索的权限字符串
下面列出实际服务器上常见的权限模式、对应的八进制值,以及它们的典型用途。
-rw-r--r--为 644。服务只需读取的普通文件,例如配置文件或 HTML 页面。-rw-------为 600。机密文件,例如 SSH 私钥或应用的.env文件。-rw-rw-r--为 664。位于组共享目录中的文件,组内成员需要写入该文件。-rwxr-xr-x为 755。脚本和二进制文件,例如/usr/local/bin/backup.sh以及大多数/usr/bin。-rwx------为 700。只有所有者可以运行的私有脚本。drwxr-xr-x为 755。几乎所有系统目录,以及网站的文档根目录。drwx------为 700。~/.ssh,以及安全加固服务器上的主目录。drwxrwxr-x为 775。所有者所属的组可以写入的目录。drwxrwsr-x为 2775。与上面相同,但还设置了 setgid 位,因此其中新建文件会继承该目录的组。drwxrwxrwt为 1777。/tmp。末尾的t是 sticky 位,因此用户只能删除自己的文件。-rwsr-xr-x为 4755。以所有者身份运行的 setuid 二进制文件,例如/usr/bin/passwd和/usr/bin/sudo。-rw-rw-rw-为 666,drwxrwxrwx为 777。全局可写。在服务器上,这几乎总是错误配置。lrwxrwxrwx是所有符号链接显示的权限字符串。Linux 会忽略链接上的权限位并检查目标,因此该字符串完全没有实际意义。
适用哪一组权限三元组
下面是初学者容易弄错的第二条规则。内核只会选择一组权限三元组,然后停止检查。
如果您的用户 ID 与文件所有者匹配,内核会使用所有者三元组,不再检查组和其他用户的权限位。否则,如果文件所属的组是您所属的组之一,内核会使用组权限三元组。否则使用其他用户三元组。
这会产生两个结果。即使所有者三元组的权限最严格,也仍然使用它。模式为 0466 的文件显示为 -r--rw-rw-,其所有者只有读取权限,而其他所有人都可以写入。原因是第一次检查就匹配了所有者,后面的权限位不会再读取。这种配置是合法的,但初次遇到时很容易令人困惑。
组权限三元组由文件所属的组决定,而不是由您所属的组列表决定。ls -l 每行显示两个名称:先是所有者,再是组。只有第二个组对该文件的权限有影响。您属于 20 个组,只有文件所属的组是其中之一时,这些组身份才有帮助。
id
stat -c '%U %G %A %n' ~/permdemo/inner/notes.txtid 显示您的用户以及您所属的所有组。stat 显示文件的所有者和所属组。将两者进行比较,即可确定内核会为您使用哪一组权限三元组。
因此,共享目录通常会设置一个专用组和 setgid 位。sudo chmod 2775 /srv/shared 显示为 drwxrwsr-x。之后在该目录中创建的文件会继承目录的所属组,而不是创建者的个人组;新建的子目录也会继承 setgid 位。setgid 只设置所属组,不设置权限模式。默认 umask 为 022 时,目录中的新文件仍会以 644 创建,因此团队成员可以读取,但不能写入。要允许组写入,所有在该目录中工作的用户都需要使用 umask 002;或者在目录上配置默认 ACL。默认 ACL 会替代 umask,应用于其中创建的文件。为每个服务使用独立账户是这一问题的另一部分,详见 VPS 上每个服务使用一个 Linux 用户。
umask 决定每个新文件的模式
新文件的模式不是由您直接指定的,而是由创建它的程序指定,再减去 umask 清除的权限位。umask 是用于移除权限位的掩码,因此 umask 越大,文件的默认权限越严格。
大多数发行版的默认值是 022。创建普通文件的程序通常会请求 0666,创建目录的程序通常会请求 0777。umask 会从这两个请求中清除 022,因此文件得到 644,目录得到 755。这正是新 VPS 上最常见的一组权限。
umask
umask -S
touch ~/permdemo/new.txt && mkdir -p ~/permdemo/newdir
ls -ld ~/permdemo/new.txt ~/permdemo/newdirumask -S 会以字母形式输出相同的值,比 0022 更易读。要设置更严格的默认值,请在 ~/.profile 中设置 umask 027:文件为 640,目录为 750。这样,您的组可以读取您的工作内容,其他用户无法访问。这些结果以通常的 0666 和 0777 请求为前提。
需要注意两个限制。umask 只能清除权限位,不能添加权限位。对于请求 0666 的文件(touch 就会提出此请求),无论 umask 设置为何,都不会获得执行权限。程序如果只请求所有者访问权限,也会保留该限制:在 umask 为 022 或 027 时,mktemp 创建的文件均为 600,目录均为 700。systemd 服务不会读取您的 shell 配置文件,因此应在单元文件中设置该值。
[Service]
UMask=0027有一种情况会完全跳过 umask。如果父目录设置了默认 ACL,系统会忽略 umask,新文件的权限位改为来自继承的 ACL。
为什么网页文件使用 644、网页目录使用 755
Web 服务器以自己的账户运行。在 Debian 和 Ubuntu 上,该账户是 www-data;在 Rocky 和 Alma 上是 nginx。该进程需要读取所提供的文件,还需要遍历这些文件上层的目录。它没有理由写入这些文件,静态站点更不应允许这种操作。
文件权限 644 允许所有者写入,并允许所有用户读取,因此部署用户可以发布文件,Web 用户可以提供文件。目录权限 755 允许所有者写入,并允许所有用户遍历,因此 Web 用户可以沿路径访问文件,但不能添加或删除任何内容。这样,即使应用程序存在错误,也无法重写它正在提供的页面。
遍历权限会在这里造成问题。如果站点位于 /home/deploy/site,而 /home/deploy 的权限是 750,且 Web 用户不属于该目录的组,那么 Web 用户根本无法进入 home 目录。请求最终会返回 HTTP 403,并在 /var/log/nginx/error.log 中出现类似下面的日志行:
open() "/home/deploy/site/index.html" failed (13: Permission denied), client: 203.0.113.5其中的 13 是 EACCES,表示内核拒绝了权限请求。网络本身没有问题:端口正在监听,请求也已到达。这正是你还在学习 Linux 上监听端口的工作方式 时容易困惑的地方。运行 namei -l /home/deploy/site/index.html,沿目录链向下检查,找到第一个对其他用户不具备 x 的目录。
应用程序需要写入的目录(例如上传目录)是例外。应通过所有权授予写入权限,而不是放宽目录模式:sudo chown -R www-data:www-data /srv/site/uploads,并将模式保持为 755。只对确实需要写入的目录授予写权限。
chmod,不要扁平化整个目录树
chmod有两种形式。八进制形式一次设置全部 9 个权限位:chmod 644 notes.txt。符号形式只修改明确指定的权限,其余权限保持不变:chmod u+x deploy.sh为所有者添加执行权限,chmod go-w notes.txt移除组用户和其他用户的写入权限。
递归操作可能破坏目录树。chmod -R 755 .会将每个图像文件和配置文件都标记为可执行,因为 chmod无法区分脚本和 JPEG 文件。请改用大写的 X。
chmod -R u=rwX,go=rX ~/permdemo
stat -c '%a %n' ~/permdemo ~/permdemo/inner/notes.txt大写的 X会为目录设置执行权限,并保留原本任一位置已有执行权限的文件的执行权限。目录最终为 755,普通文件最终为 644,原本已可执行的脚本仍保持可执行。已有一个权限模式符合要求的文件时,chmod --reference=good.sh other.sh会将其权限复制到其他文件。
出现权限错误时看到的消息
bash: ./deploy.sh: Permission denied 表示脚本在适用于当前用户的权限三元组中没有 x 位,或其路径中的某个目录没有 x。chmod u+x deploy.sh 可修复第一种情况。
bash: ./deploy.sh: cannot execute: required file not found 是另一种名称容易误导的错误。x 位没有问题,但第一行指定的解释器不存在。通常原因是使用了 Windows 换行符,因此内核会查找名为 /bin/bash\r 的解释器。使用 sed -i 's/\r$//' deploy.sh 修复。
Permissions 0644 for '/home/deploy/.ssh/id_ed25519' are too open. 来自 SSH 客户端,因为其他账户可以读取私钥时,客户端会拒绝使用该私钥。密钥的权限应为 600,~/.ssh 的权限应为 700。完整的密钥处理说明见管理 SSH 密钥及其文件权限。
Authentication refused: bad ownership or modes for directory /home/deploy/.ssh 会出现在服务器的 journal 中,表示主目录或其 .ssh 允许组用户写入。sshd 的 StrictModes 设置会拒绝该密钥;从客户端看,这表现为突然出现密码提示,且没有任何解释。
sudo: /etc/sudoers is world writable 后跟 sudo: no valid sudoers sources found, quitting,表示 sudo 检查了自身配置文件的权限模式,并拒绝运行。该文件的权限应为 0440,绝不能允许所有用户写入。这通常是广泛递归执行 chmod 后的结果,也可能与上面的 sshd 消息同时出现;此时只能通过服务提供商的控制台恢复访问。
为什么 777 不是解决方案
777 会向机器上的所有账户,以及这些账户下运行的所有进程授予写入权限。服务器会让服务使用各自的用户运行,因此在 VPS 上,“所有人”涵盖的范围远大于笔记本电脑。被入侵的服务可以写入所有允许 777 写入的位置。
在 Web 根目录下,危害会直接发生。服务器同时提供服务的全局可写目录,会使文件上传漏洞变成植入脚本并再次请求该脚本的途径。
对于所有权问题,777 几乎总是错误的答案。表面现象是“应用无法写入此目录”。原因是该目录属于错误的用户。使用所有者为 sudo chown -R appuser:appuser /srv/app/storage、权限模式为 755 的目录即可解决:应用可以写入该目录,其他账户仍可以列出目录内容并进入目录,但不能向其中写入。在部署任何内容之前创建这些账户,应放在新 VPS 的前十分钟内完成。
全局写权限在一个常见位置是合理的,即 /tmp;它的权限写法是 drwxrwxrwt。末尾的 t 是 sticky bit:目录对所有用户可写,但用户只能删除自己拥有的文件。没有该位时,任何账户都可以删除其他账户的临时文件。
更改模式前先读取现有模式
这些命令只读取状态,因此可以在任何位置安全运行。
id
umask
stat -c '%A %a %U %G %n' ~/permdemo ~/permdemo/inner/notes.txt
namei -l ~/permdemo/inner/notes.txt
find ~/permdemo -perm -0002find <path> -perm -0002 会列出路径下所有设置了其他用户写入位的项。这是在有人使用 chmod 777 修复系统后审计主机的最快方法。
要确认某个服务账户能否进入目录,请以该账户身份进行检查。sudo -u www-data test -x /srv/site && echo yes || echo no 会在该用户拥有目录遍历权限时输出 yes,没有该权限时输出 no。以 root 身份检查没有意义,因为 root 会跳过此检查,结果始终是 yes。
FAQ
在 Linux 中,drwxr-xr-x 表示什么?
这是一个目录,开头的 d 表示目录,其权限模式为 755。所有者权限三元组为 rwx,因此所有者拥有全部权限。组权限三元组为 r-x,其他用户权限三元组为 r-x,因此其他用户都可以列出其中的名称并穿过该目录,但只有所有者可以添加或删除内容。使用 stat -c '%A %a %U %G %n' <path> 可以确认任意路径;该命令会并列输出字母形式和八进制形式。
为什么 Web 文件的权限是 644,而 Web 目录的权限是 755?
Web 服务器使用不同的账户运行;在 Ubuntu 上,该账户是 www-data。它需要读取所提供的文件,并穿过这些文件上方的每个目录,但不需要写入文件或目录。644 允许所有者写入,并允许其他用户读取。755 允许所有者写入,并允许其他用户穿过目录。应用确实需要写入的目录,应使用 chown 将其所有权交给该应用的用户,而不是放宽权限模式,让所有用户都能写入。
x 位是否表示我可以执行目录?
不是。对于目录,x 表示穿过目录,也就是内核解析路径时解析其中一个名称的权限。cd 需要该权限;打开其下的文件时也需要该权限。路径中的每个目录都需要 x,因此即使文件权限模式为 644,只要上层目录缺少供你使用的 x,该文件仍然无法访问。namei -l /path/to/file 会输出路径链中每个目录的权限模式,从而显示查找在哪一级停止。
chmod 777 是否有可能是正确的修复方法?
在服务器上几乎从来不是。它会向机器上的每个账户授予写权限,包括服务运行所使用的账户,因此某个服务遭到入侵后就可以改写该文件。应用无法写入目录时,真正的问题通常是所有权:sudo chown -R appuser:appuser /srv/app/storage 配合权限模式 755 可以让应用获得写入权限,同时其他账户仍可读取目录,但不能向其中写入。常见的例外是 /tmp 使用 1777;它之所以可行,是因为 sticky bit 会阻止用户删除其他用户的文件。
为什么 ls 会在权限后打印一个点或加号?
第 11 个字符表示九个权限位之外的规则。点号(如 drwxr-xr-x.)表示已附加 SELinux 安全上下文,这在 Fedora 和 Rocky 上很常见。加号(如 drwxr-xr-x+)表示已设置 POSIX ACL(访问控制列表),因此某个用户或组拥有权限,而这三组权限位不会显示这些权限。运行 getfacl <path> 可以列出这些额外条目。