Linux 文件权限:chmod、chown 和 sudo 示例详解
Linux 文件权限由三组 rwx 决定,分别针对所有者、所属组和其他人;使用 chmod 修改,既可以用符号形式(chmod u+x),也可以用数字形式(chmod 755,其中 r=4、w=2、x=1)。chown 用于更改所有者,需要管理员权限的操作通过 sudo 执行;出现 Permission denied 通常意味着你的用户对文件或路径上的某个目录缺少所需权限。
Linux 文件权限回答的问题是“谁可以对文件做什么”。每个文件都有所有者、所属组,以及三组权限:针对所有者、针对所属组和针对其他所有人。权限用 chmod 修改,所有者用 chown 修改,需要管理员身份的操作通过 sudo 执行。下面我们讲解如何读懂权限、如何修改权限,以及如何解决 Permission denied 错误。
如何查看文件权限
权限可以在 ls -l 的输出中看到:
$ ls -l
-rw-r--r-- 1 alice developers 1204 Oct 10 14:02 notes.txt
-rwxr-xr-x 1 alice developers 356 Oct 10 14:05 deploy.sh
drwxr-x--- 2 alice developers 4096 Oct 10 13:50 secrets
前十个字符的含义如下:
- 第一个字符是类型:
-表示普通文件,d表示目录,l表示符号链接。 - 第 2–4 个字符是所有者(user)的权限。
- 第 5–7 个字符是所属组(group)的权限。
- 第 8–10 个字符是其他人(others)的权限。
之后依次是硬链接数、所有者(alice)、所属组(developers)、大小、时间和文件名。查看单个文件时,stat 命令很方便:
$ stat -c '%A %a %U:%G %n' deploy.sh
-rwxr-xr-x 755 alice:developers deploy.sh
r、w、x 的含义
同一种权限对文件和目录的含义不同,这是造成混淆的主要原因。
| 权限 | 对文件 | 对目录 |
|---|---|---|
r(read,读) | 读取内容 | 查看文件列表(ls) |
w(write,写) | 修改内容 | 在目录中创建、删除和重命名文件 |
x(execute,执行) | 作为程序运行 | 进入目录(cd),并通过路径访问其中的文件 |
请注意:对于目录,只要有 w 和 x 权限,就可以删除其中的文件,即使你对文件本身没有写权限。没有目录的 x 权限,即使文件本身允许读取,也无法打开目录中的文件。
系统按以下顺序检查权限:如果你是所有者,就应用所有者的权限;否则,如果你属于文件所属组,就应用组权限;否则,应用其他人的权限。root 用户会跳过读写的权限检查。
数字形式:755、644、600
每种权限都有一个数值:r = 4,w = 2,x = 1。三组权限各自的数值相加,得到一个 0 到 7 之间的数字。
| 数字 | 权限 | 计算 |
|---|---|---|
| 7 | rwx | 4+2+1 |
| 6 | rw- | 4+2 |
| 5 | r-x | 4+1 |
| 4 | r-- | 4 |
| 0 | --- | 0 |
下面几组常用的权限值值得记住:
| 模式 | 形式 | 用途 |
|---|---|---|
644 | rw-r--r-- | 普通文件、配置文件、HTML |
755 | rwxr-xr-x | 目录、脚本和程序 |
600 | rw------- | 私有 SSH 密钥、包含密码的文件 |
700 | rwx------ | 目录 ~/.ssh、个人目录 |
640 | rw-r----- | 由服务所属组读取的配置文件 |
777 | rwxrwxrwx | 所有人可做所有操作——几乎永远不需要 |
chmod 命令:如何修改权限
数字模式
数字形式一次性设置全部权限:
chmod 644 index.html
chmod 755 deploy.sh
chmod 600 ~/.ssh/id_ed25519
符号模式
符号形式只修改指定的部分,不影响其他权限。对象:u 所有者,g 所属组,o 其他人,a 所有人。操作:+ 添加,- 移除,= 精确设置。
chmod +x deploy.sh # 允许运行
chmod u+x,g-w file # 所有者可执行,组去掉写权限
chmod o-rwx secrets/ # 其他人没有任何权限
chmod g=rx app/ # 组只保留读取和进入目录的权限
递归修改:文件和目录分别处理
-R 选项会把权限应用到整个目录树。但 chmod -R 755 会让所有文件都变成可执行,这通常并不需要。更好的做法是用 find 分别处理文件和目录:
find /srv/site -type d -exec chmod 755 {} +
find /srv/site -type f -exec chmod 644 {} +
还有一个简短的写法:大写的 X 只会给目录,以及已经具有执行权限的文件添加执行权限。
chmod -R u=rwX,go=rX /srv/site
chown 命令:更改所有者和所属组
只有 root 可以更改文件的所有者,因此 chown 通常要通过 sudo 运行。
sudo chown alice report.txt # 所有者
sudo chown alice:developers report.txt # 所有者和所属组
sudo chown :www-data index.html # 仅所属组
sudo chown -R www-data:www-data /var/www/site
如果只想更改所属组,可以使用单独的命令 chgrp:sudo chgrp developers report.txt。你所属的组可以用 id 或 groups 查看。
$ id
uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo),1001(developers)
把用户加入某个组:sudo usermod -aG developers bob。选项 -a 必不可少:没有它,用户会被从所有其他附加组中移除。新组在重新登录后才会生效。
sudo:以管理员身份执行操作
sudo 以 root(或其他指定用户)的身份执行一条命令,并要求输入你自己的密码,而不是 root 的密码。所有调用都会写入日志,因此可以看出是谁执行了什么操作。
sudo apt update
sudo systemctl restart nginx
sudo -u postgres psql # 以 postgres 用户的身份运行
sudo -i # 交互式的 root shell
sudo -l # 查看我被允许执行哪些命令
谁可以执行什么操作,由 /etc/sudoers 和 /etc/sudoers.d/ 目录中的文件规定。编辑这些文件时只能使用 sudo visudo:它会检查语法,因此文件中的错误不会让你失去 sudo 权限。在 Ubuntu 中,sudo 权限通过加入 sudo 组授予;在 RHEL 系列系统中,则通过 wheel 组授予。
# /etc/sudoers.d/deploy — 用户 deploy 只允许重启 nginx
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx
为什么 sudo echo > file 不起作用
这是一个常见的陷阱:
$ sudo echo "127.0.0.1 test.local" >> /etc/hosts
bash: /etc/hosts: Permission denied
重定向 >> 是由你的 shell 执行的,而不是由 sudo 执行的,因此文件是在没有 root 权限的情况下打开的。正确的做法是使用 tee:
echo "127.0.0.1 test.local" | sudo tee -a /etc/hosts
Permission denied:原因和解决方法
Permission denied 表示内核拒绝了你的进程的操作。排查步骤始终相同:我是谁(id),文件的所有者和权限是什么(ls -l),路径上每个目录的权限是什么(namei -l)。
$ namei -l /srv/app/config/app.env
f: /srv/app/config/app.env
drwxr-xr-x root root /
drwxr-xr-x root root srv
drwxr-x--- deploy deploy app
drwxr-xr-x deploy deploy config
-rw-r----- deploy deploy app.env
可以看到,目录 app 对其他人是关闭的:不属于 deploy 组的用户无法继续深入,无论文件本身的权限如何。
脚本无法运行
$ ./deploy.sh
bash: ./deploy.sh: Permission denied
文件没有执行权限。解决办法是 chmod +x deploy.sh,或者通过解释器运行:bash deploy.sh。如果分区是以 noexec 选项挂载的(/tmp 常见这种情况),就无法直接运行其中的文件,只能使用第二种方法。
无法写入系统目录
/etc、/usr、/var/www 中的文件属于 root 或系统用户。一次性修改可以使用 sudo;长期工作则应该把权限授予某个组,而不是授予所有人。
Web 服务器返回 403
Nginx 或 Apache 以 www-data 用户运行(在 Debian 和 Ubuntu 中)。它需要读取文件的权限,以及路径上所有目录的 x 权限。解决方法:sudo chown -R www-data:www-data /var/www/site,或者将目录设为 755、文件设为 644。
SSH 不接受密钥
如果密钥的权限过于开放,SSH 会拒绝使用。私钥的权限必须是 600,目录 ~/.ssh 必须是 700,服务器上的 authorized_keys 文件必须是 600。
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 ~/.ssh/authorized_keys
无法访问 Docker
出现 permission denied while trying to connect to the Docker daemon socket 说明你不在 docker 组中。执行 sudo usermod -aG docker $USER,然后重新登录。请注意,这个组的成员实际上等同于拥有 root 权限。
为什么 chmod 777 是个坏主意
“直接 chmod 777 就行了”的建议确实能消除错误,但它会让系统中的每个用户和每个进程都能写入该文件。如果 Web 应用被攻破,攻击者就能篡改这些文件。正确的做法是弄清楚哪个用户需要访问,然后通过所有者或所属组只授予他所需的权限。
umask:默认权限
新建文件的权限会受 umask 掩码影响。常见的值 022 会让文件以 644 创建,目录以 755 创建。
$ umask
0022
总结
Linux 的权限就是三组 rwx,分别针对所有者、所属组和其他人。chmod 以数字(755、644、600)或符号形式修改权限,chown 修改所有者,sudo 则允许以 root 身份执行单独的命令。遇到 Permission denied 时,请检查用户、文件权限以及路径上每个目录的权限,不要用 777 来掩盖问题。用户、组、权限和 sudo 都会在 Linux 课程中结合实践详细讲解。
常见问题
chmod 755 是什么意思?
所有者可以读、写和执行(7),所属组和其他人可以读和执行(5)。这是目录和脚本的标准设置。
chmod 和 chown 有什么区别?
chmod 修改权限(允许对文件做什么),chown 修改所有者和所属组(这些权限属于谁)。
怎样给用户 sudo 权限?
在 Ubuntu 和 Debian 中,执行 sudo usermod -aG sudo 用户名 将其加入 sudo 组;在 RHEL 系列系统中,加入 wheel 组。重新登录后生效。
4755 权限和 SUID 位是什么?
最前面的数字 4 表示启用 SUID:程序以文件所有者的身份运行,而不是以启动者的身份运行。例如 passwd 就是这样工作的;在 ls 的输出中,所有者的 x 位置会显示为 s。
为什么 root 可以读取权限为 000 的文件?
内核不会对 root 检查普通的读写权限。若要限制 root,只能借助其他机制,例如 SELinux、AppArmor,或者不可变属性 chattr +i。