当你部署网站、恢复备份,或从另一台机器复制项目文件时,许多文件和目录的权限往往会变得不一致。在这些情况下,chmod 配合 -R 选项可以一次性修复整个目录树。
本指南将介绍如何使用 chmod -R 递归修改权限、如何使用 find 为文件和目录分别设置不同权限,以及如何避免常见错误。
如需以可视方式构建权限模式并复制生成的命令,可以使用交互式 chmod 计算器。
理解权限数字
Linux 权限由三个数字表示。每个数字是读(4)、写(2)和执行(1)之和:
| 数字 | 权限 | 含义 |
|---|---|---|
| 7 | rwx | 读、写、执行 |
| 6 | rw- | 读和写 |
| 5 | r-x | 读和执行 |
| 4 | r-- | 只读 |
| 0 | --- | 无权限 |
这三个数字依次代表所有者(owner)、所属组(group)和其他人(others)。例如,755 表示所有者拥有完全访问权限(rwx),而组和其他人只能读和执行(r-x)。
如需全面了解权限系统,请参阅《理解 Linux 文件权限》。
使用 chmod -R
-R 选项告诉 chmod 将权限递归地应用到某个目录及其内部的全部内容。其基本语法为:
chmod -R MODE DIRECTORY
例如,要为 /var/www/html 下的所有文件和子目录设置 755:
chmod -R 755 /var/www/html
使用符号模式实现相同修改:
chmod -R u=rwx,go=rx /var/www/html
只有 root 用户、文件所有者,或拥有 sudo 权限的用户才能更改文件权限。运行 chmod -R 时要格外小心,因为它会修改目标目录下每一个条目。
为文件和目录设置不同权限
在大多数情况下,文件和目录不应具有相同的权限。目录需要执行位(execute bit)才能 cd 进入,而普通文件通常并不需要它。
最常见的模式是目录 755、文件 644。使用 find 命令可以分别针对不同类型进行设置。
使用数字模式:
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
使用符号模式:
find /var/www/html -type d -exec chmod u=rwx,go=rx {} \;
find /var/www/html -type f -exec chmod u=rw,go=r {} \;
find 命令会搜索匹配 -type d(目录)或 -type f(文件)的条目,并通过 -exec 将每一个传递给 chmod。
在处理大量文件时,-exec 方式会对每个条目各运行一次 chmod。使用 xargs 一次性传入多个条目会显著更快:
find /var/www/html -type d -print0 | xargs -0 chmod 755
find /var/www/html -type f -print0 | xargs -0 chmod 644
-print0 和 -0 选项用于处理包含空格或特殊字符的文件名。
在递归 chmod 中使用大写 X
大写 X 权限是一个快捷方式,它只对目录以及已经设置了至少一个执行位的文件添加执行权限。这样可以避免把普通文件变成可执行:
chmod -R u=rwX,go=rX /var/www/html
这条命令为所有人设置读权限、为所有者设置写权限,并且会对目录以及原本就带有执行位的文件设置执行权限——全部在一条命令中完成,无需使用 find。
常见权限模式
| 模式 | 目录 | 文件 | 适用场景 |
|---|---|---|---|
| 755 / 644 | rwxr-xr-x | rw-r--r-- | Web 服务器内容 |
| 750 / 640 | rwxr-x--- | rw-r----- | 私有 Web 应用(组访问) |
| 700 / 600 | rwx------ | rw------- | 用户私有文件(SSH 密钥、配置文件) |
| 775 / 664 | rwxrwxr-x | rw-rw-r-- | 共享项目目录 |
安全注意事项
如果将递归权限更改应用到错误的目录,可能会破坏你的系统。请牢记以下几点:
- 切勿运行 <code>chmod -R 777 /</code> 或以根文件系统为目标。这会让系统上每个文件都获得完全访问权限,并可能导致系统无法启动。
- 使用 <code>--preserve-root</code> 来防止意外修改 <code>/</code>。与 <code>rm</code> 不同,chmod 不会自动启用该选项,因此只要递归更改涉及根文件系统附近,就要自己加上该标志:
chmod -R --preserve-root 755 /some/directory
- 在按下回车之前,务必仔细检查目标路径。在 <code>chmod -R 755 / var/www</code>(注意 <code>/</code> 后面的空格)中,一个错位的空格会把 <code>755</code> 应用到整个根文件系统。
- 在 GNU chmod 中,递归模式默认采用 <code>-H</code> 行为。它仅在符号链接本身作为命令行参数传入且指向目录时才跟随该链接,而不会遍历递归过程中发现的每一个符号链接。
- 如果你需要不同的遍历行为,可使用 <code>-L</code> 跟随所有目录符号链接,或使用 <code>-P</code> 避免跟随符号链接。这些标志从 GNU coreutils 9.5 开始提供,因此在使用更旧版本的系统(包括 Ubuntu 24.04(coreutils 9.4)和 Debian 12(coreutils 9.1))上并不存在。在依赖它们之前,先运行 <code>chmod --version</code> 确认你的版本。
- 在不受信任的用户可以修改的目录树上应避免使用 <code>-L</code>。它可能会跟随一个指向预期目录树之外的符号链接。如果在 chmod 遍历目录树时链接发生变化,命令可能会作用于不同的目标。
验证权限
要检查文件和目录的权限,可以使用带 -l 选项的 ls 命令:
ls -l /var/www/html/
drwxr-xr-x 2 www-data www-data 4096 Feb 13 10:00 css -rw-r--r-- 1 www-data www-data 8421 Feb 13 10:00 index.html drwxr-xr-x 3 www-data www-data 4096 Feb 13 10:00 images
第一个字符表示条目类型(d 代表目录,- 代表文件)。接下来的九个字符依次显示所有者、组和其他人的权限。
要递归验证权限,添加 -R 选项:
ls -lR /var/www/html/
故障排查
Operation not permitted:你没有更改该文件的权限。请使用 sudo 运行命令,或切换到文件所有者。
chmod: cannot access ‘path’:没有那个文件或目录——目标路径不存在。在运行 chmod 之前,先用 ls 核实路径。
在挂载的驱动器上权限未改变:NTFS 和 FAT 等文件系统不支持 Linux 权限。权限是在挂载时通过 fmask 和 dmask 挂载选项设置的。
执行 chmod -R 755 后文件变成了可执行:对一切使用 755 会让普通文件也变为可执行。请使用 find 分别为目录设置 755、为文件设置 644,或者使用大写 X 快捷方式。
快速参考
如需可打印的快速参考,请参阅 chmod 速查表。
| 命令 | 说明 |
|---|---|
| chmod -R 755 dir/ | 为目录树设置 755 |
| chmod -R u=rwX,go=rX dir/ | 所有人可读、所有者可写;目录及已可执行文件加执行位 |
| find dir/ -type d -exec chmod 755 {} \; | 仅为目录设置 755 |
| find dir/ -type f -exec chmod 644 {} \; | 仅为文件设置 644 |
| find dir/ -type d -print0 | xargs -0 chmod 755 | 更快速地修改目录权限 |
| find dir/ -type f -print0 | xargs -0 chmod 644 | 更快速地修改文件权限 |
| chmod -R --preserve-root 755 /path | 防止意外修改 / |
| chmod -R g+w dir/ | 递归添加组写权限 |
| chmod -R o-rwx dir/ | 移除其他人的所有权限 |
| ls -lR dir/ | 递归验证权限 |
常见问题
chmod 默认递归吗?不。不加 -R 时,chmod 只会更改你在命令行中指定的文件和目录,目录内部的一切都保持不变。当你希望整个目录树都改变时,再加上 -R。
755 和 644 有什么区别?使用 755 时,所有者可读、写、执行,而其他人可读和执行;使用 644 时,所有者可读和写,而其他人只能读。目录用 755,普通文件用 644。
chmod -R 会跟随符号链接吗?在 GNU chmod 中,-R 默认使用 -H 行为。这意味着它仅在符号链接作为命令行参数传入且指向目录时才跟随该链接。使用 -L 可跟随所有目录符号链接,或使用 -P 在遍历时避免跟随符号链接。这两个标志都需要 coreutils 9.5 或更新版本,因此在 Ubuntu 24.04、Debian 12 等较旧系统上请先运行 chmod --version 确认。在不受信任用户可修改的目录树上应避免使用 -L,因为符号链接可能把 chmod 引向预期目录树之外的位置。
可以撤销递归 chmod 吗?没有内置的撤销功能。如果你更改了错误目录的权限,必须手动恢复,或从备份中还原。运行 chmod -R 之前,务必核实目标路径。
如何更改目录中所有文件的权限?使用 find 配合 -type f 只针对文件,再把每一个交给 chmod:
find /path/to/directory -type f -exec chmod 644 {} \;
这样目录权限保持不变。对于庞大的目录树,使用 xargs 可以获得更好的性能:
find /path/to/directory -type f -print0 | xargs -0 chmod 644
chmod -R 777 会做什么?chmod -R 777 为目录树中所有文件和目录的每个人设置完全的读、写、执行权限:
chmod -R 777 /path/to/directory
这是一个严重的安全风险。系统上的任何用户都可以读取、修改或删除这些文件。在生产系统、Web 服务器目录或任何包含敏感数据的路径上都应避免使用它。对于 Web 内容,请改用目录 755、文件 644。
chmod 中的大写 X 是什么意思?大写 X 只为目录以及已经带有执行位的文件添加执行权限。它非常适合在不把普通文件变成可执行的情况下递归应用权限。
总结
chmod -R 命令会递归地更改整个目录树的权限。在大多数使用场景中,可以将 find 与 chmod 结合使用,为文件和目录设置不同权限,或者使用大写 X 快捷方式以一条命令完成。如需更全面地了解权限系统,请参阅《理解 Linux 文件权限》。