你把一个脚本拷贝到服务器上运行,结果收到 "Permission denied"(权限拒绝)的报错;打开一个日志文件,又遇到同样的提示。归根结底,这两件事是同一个原因:Linux 中每个文件都带有一组权限位,系统在允许你操作文件之前,会先检查这些权限位。
在 Linux 中,文件权限、属性以及所有权共同决定了系统进程和用户对文件的访问级别。这保证了只有经过授权的用户和进程才能访问特定的文件和目录。
本指南将讲解如何读取 ls -l 输出中的权限位、读/写/执行权限对文件和目录分别意味着什么,以及如何使用 chmod 命令(符号模式与数字模式)来修改权限。
Linux 文件权限
Linux 的基础权限模型是:为系统中的每个文件关联一个所有者(owner)和一个所属组(group),并为三类不同的用户分配访问权限:
- 文件所有者。
- 所属组的成员。
- 其他人(即其余所有用户)。
文件的所有权可以使用 chown 和 chgrp 命令来修改。
每一类用户都可以被授予三种类型的权限:
- 读权限(read)。
- 写权限(write)。
- 执行权限(execute)。
借助这套机制,你可以精确控制哪些用户能够读取文件、写入文件或执行文件。
要查看文件权限,可以使用 ls 命令:
ls -l file_name
第一个字符表示文件类型:普通文件为 -,目录为 d,符号链接为 l,也可以是其他特殊文件类型。随后的九个字符表示文件权限,分成三组三位(triplet)。第一组显示所有者的权限,第二组显示所属组的权限,最后一组显示其他所有人的权限。
在权限位之后,可能会跟随一个可选的附加字符。+ 通常表示启用了访问控制列表(ACL);. 表示存在安全上下文且没有其它可选访问方式。如果两者都不适用,ls 会留空该位置。其余字段依次显示硬链接数、所有者、所属组、文件大小、修改时间以及文件名。
在上面的示例中,rw-r--r-- 表示文件所有者拥有读和写权限(rw-),而所属组与其他人仅拥有读权限(r--)。
三组权限中的每一组都可以由以下字符组合而成,而同一个字符在文件和目录上代表的意义并不相同:
权限对文件的影响
权限对目录(文件夹)的影响
目录是一种特殊的文件,它可以包含其它文件和子目录。
修改文件权限
可以使用 chmod 命令修改文件权限。只有 root 用户、文件所有者,或者拥有 sudo 权限的用户才能修改文件权限。使用 chmod 时要格外谨慎,尤其是在递归修改权限时。该命令可以接受以空格分隔的一个或多个文件/目录作为参数。
权限可以通过符号模式(symbolic)、数字模式(numeric)或参考文件来指定。
符号(文本)模式
使用符号模式时,chmod 命令的语法格式如下:
chmod [OPTIONS] [ugoa…][-+=]perms…[,…] FILE...
第一组标志([ugoa…])称为用户标志(user flags),用于定义将要修改权限的用户类别。
- u —— 文件所有者。
- g —— 所属组的成员。
- o —— 其他所有用户。
- a —— 所有用户,等同于 ugo。
如果省略用户类别,chmod 会将其视为 a,但受当前 umask 屏蔽的权限不会受到影响。
第二组标志([-+=])称为操作标志(operation flags),用于定义权限是被移除、添加还是设置:
- - —— 移除指定的权限。
- + —— 添加指定的权限。
- = —— 将当前权限更改为指定的权限。如果在
=之后没有给出任何权限,则指定用户类别的所有权限都将被移除。
权限(perms...)通过以下字母中的一个或多个显式设置:r、w、x、X、s 和 t。当需要将权限从某一用户类别复制到另一类别时,使用 u、g、o 中的单个字母。
当为多个用户类别设置权限([,…])时,使用逗号(不含空格)来分隔不同的符号模式。
下面是一些在符号模式下使用 chmod 命令的示例:
- 仅赋予所属组执行该文件的权限,但不允许读和写:
chmod g=x filename - 移除所有用户的写权限:
chmod a-w filename - 递归移除其他用户的执行权限:
chmod -R o-x dirname - 移除除文件所有者外所有用户的读、写、执行权限:
chmod og-rwx filename(同样也可用以下形式实现:chmod og= filename) - 赋予文件所有者读、写、执行权限,所属组只读权限,其他用户无任何权限:
chmod u=rwx,g=r,o= filename
数字模式
使用数字模式时,chmod 命令的语法格式如下:
chmod [OPTIONS] NUMBER FILE...
使用数字模式时,你可以同时为全部三类用户(所有者、所属组、其他人)设置权限。
权限数字可以是三位数或四位数。使用三位数时,第一位代表所有者的权限,第二位代表所属组的权限,最后一位代表其他所有人的权限。
每一种读、写、执行权限都对应以下数值:
- r(读)= 4
- w(写)= 2
- x(执行)= 1
- 无权限 = 0
特定用户类别的权限数字,等于该类别各项权限数值之和。
要以数字模式确定文件权限,需要分别计算每个用户类别的合计值。例如,若要赋予所有者读、写、执行权限,所属组读和执行权限,而其他用户仅读权限,则使用以下数值:
- 所有者:rwx=4+2+1=7
- 所属组:r-x=4+0+1=5
- 其他人:r--=4+0+0=4
通过以上方法,我们得到数字 754,即目标权限。
若要设置 setuid、setgid 以及粘滞位(sticky bit)标志,需使用四位数。
使用四位数时,第一位按以下数值计算:
- setuid = 4
- setgid = 2
- sticky bit = 1
- 无特殊位 = 0
后三位数字的含义与三位数时相同。
如果第一位是 0,则可以省略,用三位数表示该模式。数字模式 0755 等同于 755。
想深入了解这三个标志在文件和目录上的作用,以及各自的适用场景,请参阅我们关于 setuid、setgid 和粘滞位 的指南。
你可以使用 stat 命令以数字形式查看文件权限:
stat -c "%a" file_name
下面是一些在数字模式下使用 chmod 命令的示例:
- 赋予文件所有者读、写权限,所属组与其他用户仅读权限:
chmod 644 file - 赋予所有者读、写、执行权限,所属组读和执行权限,其他用户无任何权限:
chmod 750 file - 在共享目录上赋予所有人读、写、执行权限,并加上粘滞位。请将此仅用于确实需要每个用户都能创建文件的临时目录;至于为何“全局可写”在其它地方存在风险,请参阅 chmod 777 的含义:
chmod 1777 dirname - 为文件赋予所有者读、写权限,对目录赋予完全访问权限,同时在整个目录树中移除所有组和他人的权限:
chmod -R u=rwX,go= dirname其中大写X会为目录以及本身已带执行位的文件添加执行权限,但并不会让每个普通文件都变成可执行。
新建文件的默认权限
你不必在每次创建文件时都手动设置权限。通常情况下,程序为新普通文件请求 666 模式,为新目录请求 777 模式,然后系统会清除掉被 umask 覆盖的权限位。程序也可以请求更严格的模式;此外,父目录上的默认 ACL 也可能决定最终的权限。
查看当前的掩码:
umask
当掩码为 022 时,所属组和其他人的写位被清除,因此新文件为 644、新目录为 755。更严格的掩码 077 会清除这两类的所有位,得到 600 和 700。关于如何计算掩码以及如何使其永久生效,请参阅我们的 umask 指南。
快速参考
如需可打印的速查表,请参阅 chmod 速查表。
常用权限值:
| Mode | Symbolic | Who can do what |
|---|---|---|
| 777 | rwxrwxrwx | 所有人可读、写、执行 |
| 755 | rwxr-xr-x | 所有者完全访问;所属组和其他人读、执行 |
| 750 | rwxr-x--- | 所有者完全访问;所属组读、执行;其他人无权限 |
| 700 | rwx------ | 所有者完全访问;所属组和其他人无权限 |
| 664 | rw-rw-r-- | 所有者和组可读、写;其他人仅读 |
| 644 | rw-r--r-- | 所有者读、写;所属组和其他人仅读 |
| 600 | rw------- | 所有者读、写;所属组和其他人无权限 |
| 400 | r-------- | 所有者仅读;所属组和其他人无权限 |
符号模式 chmod 示例:
| Command | Effect |
|---|---|
| chmod u+x file | 为所有者添加执行权限 |
| chmod g-w file | 移除所属组的写权限 |
| chmod o= file | 移除其他人的所有权限 |
| chmod a+r file | 为所有人添加读权限 |
| chmod u=rwx,g=rx,o= file | 为所有类别设置精确权限 |
| chmod -R u=rwX,go=rX dir | 赋予所有人目录访问权限,但不会让每个文件都变成可执行 |
常见问题
chmod 与 chown 有什么区别? chmod 修改文件上的权限位(读、写、执行);chown 修改文件的所有者和所属组。两者都会影响谁可以访问文件,但控制的是不同方面。
chmod 777 是什么意思?它安全吗? 777 为所有者、所属组以及其他所有用户赋予读、写、执行权限。它几乎不适用于任何场景,对于包含敏感数据或由服务执行的文件,应尽量避免使用,因为它允许系统上的任何人对文件进行修改或运行。
为什么目录需要执行权限? 对目录而言,执行权限允许你进入该目录,并按名称访问其中的条目。如果没有执行权限,你只能在有限情况下列出目录内容,却无法使用 cd 等命令进入目录或在其中打开文件。
什么是粘滞位?何时应该使用它? 在一个可写、可搜索的目录上,粘滞位(模式 1xxx,在 ls -l 中显示为 t)只允许文件所有者、目录所有者或 root 删除或重命名其中的文件。它常用于 /tmp 这类共享目录,以防止用户互相删除彼此的文件。
什么是 setuid?为什么它很危险? 当 setuid 设置在一个可执行程序上时,该程序将以文件所有者的权限而非调用者的权限运行。例如 /usr/bin/passwd 就是 setuid root,以便普通用户能够修改自己的密码。设计不良的 setuid 程序可能造成权限提升风险。Linux 会忽略解释型脚本上的 setuid 和 setgid 位。
如何以数字模式查看权限? 使用 stat 命令:stat -c "%a %n" file,它会将八进制权限值与文件名一同打印出来。
结语
在 Linux 中,文件的访问权限通过分配给三类对象——所有者、所属组和他人——的权限位来控制。使用带符号模式或数字模式的 chmod 来修改权限,使用 ls -l 或 stat 来查看权限。如需聚焦的命令参考,请参阅 chmod 命令指南。