你把一个脚本拷贝到服务器上运行,结果收到 "Permission denied"(权限拒绝)的报错;打开一个日志文件,又遇到同样的提示。归根结底,这两件事是同一个原因:Linux 中每个文件都带有一组权限位,系统在允许你操作文件之前,会先检查这些权限位。

在 Linux 中,文件权限、属性以及所有权共同决定了系统进程和用户对文件的访问级别。这保证了只有经过授权的用户和进程才能访问特定的文件和目录。

本指南将讲解如何读取 ls -l 输出中的权限位、读/写/执行权限对文件和目录分别意味着什么,以及如何使用 chmod 命令(符号模式与数字模式)来修改权限。

Linux 文件权限

Linux 的基础权限模型是:为系统中的每个文件关联一个所有者(owner)和一个所属组(group),并为三类不同的用户分配访问权限:

  • 文件所有者。
  • 所属组的成员。
  • 其他人(即其余所有用户)。

文件的所有权可以使用 chownchgrp 命令来修改。

每一类用户都可以被授予三种类型的权限:

  • 读权限(read)。
  • 写权限(write)。
  • 执行权限(execute)。

借助这套机制,你可以精确控制哪些用户能够读取文件、写入文件或执行文件。

要查看文件权限,可以使用 ls 命令:

ls -l file_name

第一个字符表示文件类型:普通文件为 -,目录为 d,符号链接为 l,也可以是其他特殊文件类型。随后的九个字符表示文件权限,分成三组三位(triplet)。第一组显示所有者的权限,第二组显示所属组的权限,最后一组显示其他所有人的权限。

在权限位之后,可能会跟随一个可选的附加字符。+ 通常表示启用了访问控制列表(ACL);. 表示存在安全上下文且没有其它可选访问方式。如果两者都不适用,ls 会留空该位置。其余字段依次显示硬链接数、所有者、所属组、文件大小、修改时间以及文件名。

在上面的示例中,rw-r--r-- 表示文件所有者拥有读和写权限(rw-),而所属组与其他人仅拥有读权限(r--)。

三组权限中的每一组都可以由以下字符组合而成,而同一个字符在文件和目录上代表的意义并不相同:

权限对文件的影响

权限对目录(文件夹)的影响

目录是一种特殊的文件,它可以包含其它文件和子目录。

提示: 在 Linux 中,目录是包含其它文件和目录的特殊类型文件。

修改文件权限

可以使用 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...)通过以下字母中的一个或多个显式设置:rwxXst。当需要将权限从某一用户类别复制到另一类别时,使用 ugo 中的单个字母。

当为多个用户类别设置权限([,…])时,使用逗号(不含空格)来分隔不同的符号模式。

下面是一些在符号模式下使用 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 会清除这两类的所有位,得到 600700。关于如何计算掩码以及如何使其永久生效,请参阅我们的 umask 指南。

快速参考

如需可打印的速查表,请参阅 chmod 速查表。

常用权限值:

ModeSymbolicWho can do what
777rwxrwxrwx所有人可读、写、执行
755rwxr-xr-x所有者完全访问;所属组和其他人读、执行
750rwxr-x---所有者完全访问;所属组读、执行;其他人无权限
700rwx------所有者完全访问;所属组和其他人无权限
664rw-rw-r--所有者和组可读、写;其他人仅读
644rw-r--r--所有者读、写;所属组和其他人仅读
600rw-------所有者读、写;所属组和其他人无权限
400r--------所有者仅读;所属组和其他人无权限

符号模式 chmod 示例:

CommandEffect
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 -lstat 来查看权限。如需聚焦的命令参考,请参阅 chmod 命令指南。