文件权限与属性

来自 Arch Linux 中文维基

文件系统权限属性来规范系统进程与文件和目录之间的交互。

警告: 权限和属性设置只能防范来自已经启动了的当前系统的攻击。为了防止数据被能物理访问该机器的人的接触,必须同时使用磁盘加密.

查看权限[编辑 | 编辑源代码]

使用ls命令的-l选项查看为目录内容设置的权限(或文件模式),例如:

$ ls -l /path/to/directory
total 128
drwxr-xr-x 2 archie users  4096 Jul  5 21:03 Desktop
drwxr-xr-x 6 archie users  4096 Jul  5 17:37 Documents
drwxr-xr-x 2 archie users  4096 Jul  5 13:45 Downloads
-rw-rw-r-- 1 archie users  5120 Jun 27 08:28 customers.ods
-rw-r--r-- 1 archie users  3339 Jun 27 08:28 todo
-rwxr-xr-x 1 archie users  2048 Jul  6 12:56 myscript.sh

第一栏是我们必须关注的内容。 以 drwxrwxrwx +为例,每个字符的含义在下表中说明:

d rwx rwx rwx +
文件类型,技术上不属于其权限。 有关可能值的说明,请参阅 info ls -n "What information is listed" 命令的输出。 所有者对文件的权限,如下所述。 该组对该文件的权限,如下所述。 所有其他用户对该文件的权限,如下所述。 一个指定备用访问方法是否适用于该文件的字符。 当此字符是空格时,没有备用访问方法。 .字符表示具有安全上下文的文件,但没有其他备用访问方法。 具有任何其他备用访问方法的文件用 +字符标记,例如在使用访问控制列表 (ACL) 的情况下.

权限三元组(也就是上面例子中的rwx)可以由以下字符(权限位)构成:

字符 文件效果 目录效果
读权限(第一个字符) - 不能读取该文件 不显示目录里的内容
r 可以读取该文件 能显示目录里的内容
写权限(第二个字符) - 不能修改该文件 不能修改目录中的内容
w 可以修改该文件 能修改目录中的内容(创建、重命名或删除文件或子目录);需要同时设置执行权限,否则本权限无效。
执行权限(第三个字符) - 不能执行该文件 无法使用 cd 命令访问该目录
x 可以执行该文件 能使用 cd 命令访问该目录。这是实践中唯一一个算是可以从父目录继承而来的权限。实际上,如果某文件或目录路径中的任何一个目录没有设置 x 权限, 就算最终访问的文件或目录设置了对应的权限也是打不开的。请参考path_resolution(7) 来了解更多。
s 当出现在用户(所有者)权限三元组时,代表 setuid 位; 当出现在组权限三元组时,代表 setgid 位;不会出现在对其他用户权限的三元组中;同时意味着设置了 x 权限。
S s 相同,但是未设置 x 权限;普通文件中很少见,并且对于目录是无效的。
t 粘滞位,只存在于对其他用户权限的三元组中;同时意味着设置了 x 权限。
T t 相同,但是未设置 x 权限 ;普通文件中很少见。

请参考 info Coreutils -n "Mode Structure"chmod(1) 以获得更详细的说明。

提示:您可以用 namei -l path 命令查看文件或者目录沿路的权限

案例[编辑 | 编辑源代码]

让我们用一些案例来解释说明:

drwx------ 6 archie archie  4096 Jul  5 17:37 Documents

Archie 具有对 Document 目录的完全访问权限。它可以列出、创建和重命名或删除 Documents 中的任何文件,无论其中文件的权限是什么。而它访问文件的能力取决于具体文件的权限。

dr-x------ 6 archie archie  4096 Jul  5 17:37 Documents

Archie 拥有完全访问权限,但他们不能创建、重命名或删除任何文件。他们可以列出文件,并且(如果文件的权限允许)可以访问文档中的现有文件。

d-wx------ 6 archie archie  4096 Jul  5 17:37 Documents

Archie 不能在 files 目录中执行 ls ,但是如果它知道现有文件的名称,就可以列出、重命名、删除或(如果文件的权限允许)访问该文件。此外,它们还能够创建新文件。

d--x------ 6 archie archie  4096 Jul  5 17:37 Documents

Archie 只能够在文件权限允许的情况下访问已知的文件。它不能列出目录中的文件,也无法创建、重命名或者删除任何文件。

要记得,我们在此介绍的是目录权限,这与单个文件权限无关。创建一个新文件时,修改的是目录。这就是为什么您需要有目录的写权限。

接下来我们看一些文件权限方面的例子:

-rw-r--r-- 1 archie web  5120 Jun 27 08:28 foobar

在这里,我们可以看到第一个字母不是 d 而是 -。所以我们知道它是一个文件,而不是一个目录。接下来,所有者的权限是rw-。所有者并没有拥有全部的三个权限可能很奇怪,但这个文件作为一个文本文件而不是一个可执行文件时,并不需要x 权限(但如果它包含 python 代码之类的内容,那么它很可能是可执行文件),我们可以用 Gedit、EMACS 等文本编辑器或者 R 之类的软件来读取它。该文件的组权限为 r-- ,因此该组的成员可以读取文件,但不能以任何方式对其进行写入/编辑,实际上就是把它设置为只读。最后是对其他用户的权限,被设置为与组权限一致,也是只读。

修改权限[编辑 | 编辑源代码]

chmod 是 Linux 和其他 Unix-like 操作系统中用来修改文件或者目录权限的命令。

以字符形式修改权限[编辑 | 编辑源代码]

想要修改文件的权限(或者叫访问模式),请在终端里使用 chmod 命令。以下是该命令的基本结构:

chmod who=permissions filename

其中的 who 是一个或者多个字母,代表要指定权限的对象,可以为:

  • u: 拥有该文件的用户
  • g: 该文件所属的用户组 .
  • o: 所有其他用户
  • a: 以上所有,等效于 ugo.

权限和上面 #查看权限所述的相同 (r, wx).

现在看一下使用这个命令的一些示例。假设您对“文档”目录进行了严格的保护,并希望拒绝除您之外的所有人在其中读取、写入和执行(或在本例中是拒绝搜索或查看)的权限。

修改前: drwxr-xr-x 6 archie web 4096 Jul 5 17:37 Documents

$ chmod g= Documents
$ chmod o= Documents

修改后: drwx------ 6 archie web 4096 Jul 6 17:32 Documents

在这里,因为您想要禁止所有权限,所以不要在 = 后面输入任何内容。如此修改后,除了文件所有者的权限为 rwx 之外,其他权限都是 -

您可以使用如下命令来恢复原来的状态:

再次修改前:drwx------ 6 archie web 4096 Jul 6 17:32 Documents

$ chmod g=rx Documents
$ chmod o=rx Documents

再次修改后:drwxr-xr-x 6 archie web 4096 Jul 6 17:32 Documents

在下一个例子中,您想给组及其他用户读取和执行权限,所以您可以在 = 后面输入相应的权限 rx,记得不要带空格。

您可以在 who 的地方输入多个字母,来同时给多个对象设置权限,如:

$ chmod go=rx Documents
注意: chmod 命令中的 who 字母或者权限位()字符的顺序是无关紧要的。chmod go=rx filechmod og=xr file 这两个命令的含义完全相同

接下来我们考虑第二个例子,假设您想让自己和 web 用户组中的用户(可能是您的同事)有 foobar 这个文件的读写权限, 但其他人只能读取它。那么操作如下:

修改前: -rw-r--r-- 1 archie web 5120 Jun 27 08:28 foobar

$ chmod g=rw foobar

修改后:-rw-rw-r-- 1 archie web 5120 Jun 27 08:28 foobar

这与第一个示例完全相同,但使用的是文件,而不是目录,并且您授予的是写入权限(这只是为了给出授予每个权限的示例)。

字符形式的捷径[编辑 | 编辑源代码]

chmod 命令允许使用 +- 而不是=从现有集合中添加和减去权限。这与上面的命令不同,后者实质上是重设权限(例如,要将权限从r--更改为rw- ,您仍然需要在 chmod 命令的=之后包含 rw。如果遗漏了r ,那么在使用=重设权限时,它将取消r的权限。使用+-可以通过添加或删除当前的权限集来避免这种情况)。

让我们用 +- 的方式复现一下前面给组添加写权限的例子:

修改前: -rw-r--r-- 1 archie web 5120 Jun 27 08:28 foobar

$ chmod g+w foobar

修改后:-rw-rw-r-- 1 archie web 5120 Jun 27 08:28 foobar

另一个例子,取消所有用户和组的写入权限。

修改前: -rw-rw-r-- 1 archie web 5120 Jun 27 08:28 foobar

$ chmod a-w foobar

修改后: -r--r--r-- 1 archie web 5120 Jun 27 08:28 foobar

另一个不同的捷径是特殊的 X 模式:实际上不存在这个模式,但它通常与 -R 选项(递归)一起使用,以设置只针对目录的执行权限,而不修改常规文件的权限,例如:

$ chmod -R a+rX ./data/

复制权限[编辑 | 编辑源代码]

您可以让 chmod 把某对象(比如所有者)的权限复制给其他对象(比如组或者所有人)。想要做到这一点,在 = 后面不要跟权限(rwx),而是输入另一个 who 字母。比如:

修改前 -rw-r--r-- 1 archie web 5120 Jun 27 08:28 foobar

$ chmod g=u foobar

修改后 -rw-rw-r-- 1 archie web 5120 Jun 27 08:28 foobar

这个命令的意思就是“把对组(g=)的权限设置为与所有者(=u)的权限相同”。请注意,您不能复制一组权限,也不能授予新的权限,以下是错误示范,chmod 会报错:

$ chmod g=wu foobar

数字形式[编辑 | 编辑源代码]

chmod 也可以用数字来设置权限。

使用数字是另一种方法,它允许您同时编辑所有者、组和其他人的权限,以及setuid、setgid和粘滞位。命令的基本结构如下:

$ chmod xxx filename

xxx 部分是一个三位数,其中的每一位可以是0到7之间的任何数字。第一位数字指所有者的权限,第二位数字指组的权限,而第三位数字指所有其他人的权限。

在这个数字表示法中,权限 rwx所对应的数值是:

r=4
w=2
x=1

要得到这个三位数,您要考虑为所有者、组和所有其他人设置哪些权限,然后将其对应的数值累加起来。例如,如果希望授予目录的所有者读写和执行权限,并希望 group 和其他所有人只有读写权限,那么通过计算可以得到如下数值:

  • 所有者: rwx=4+2+1=7
  • 组: r-x=4+0+1=5
  • 其他人: r-x=4+0+1=5
$ chmod 755 filename

这就相当于使用如下命令:

$ chmod u=rwx filename
$ chmod go=rx filename

若要以数字形式查看文件或目录的现有权限,请使用stat(1)命令:

$ stat -c %a filename

%a 指定以数字形式输出文件权限。

大多数目录被设置为 755 以允许所有者读取、写入和执行,但拒绝被其他所有人写入;文件通常是644 以允许所有者读取和写入,但允许其他所有人读取;请参考最后一个关于不可执行文件缺少x权限的说明,此处同理。

为了用实例来说明这一点,我们用数字方式复现一下前面举过的例子:

修改前:-rw-r--r-- 1 archie web 5120 Jun 27 08:28 foobar

$ chmod 664 foobar

修改后: -rw-rw-r-- 1 archie web 5120 Jun 27 08:28 foobar

如果这是一个可执行文件,同时您想向所有者和组授予可执行权限,则权限数字为774。或者,如果您希望每个人都只具有读取权限,则数字将为444。将r视为4,w视为2,以及x视为1,这可能是计算chmod xxx 文件名的权限数值最简单的方法。

但还有一种二进制方法,其中每个权限都代表一个二进制数,最后再将其转换为一个数字。它有点复杂,但为了完整起见,在此也介绍该方法。

对于以下权限组合:

-rwxrwxr-x

如果您在每个授予的权限下写1,而在每个未授予的权限下写0,则结果如下:

-rwxrwxr-x
 111111101

然后把它当成二进制数进行转换:

000=0	    100=4
001=1	    101=5
010=2	    110=6
011=3	    111=7

因此,上述值为775。

如果我们想从组中删除写权限:

-rwxr-xr-x
 111101101

因此,该值将为755,您可以使用 chmod 755 文件名删除可写权限。无论使用哪种方法,您最终都会得到相同的三位数。使用文本还是数字取决于个人偏好和打字速度。如果您希望将目录或文件还原为默认权限(例如所有者有读写和执行权限,但拒绝其他所有人的写权限),则使用chmod 755/644 文件名可能会更快。但如果您要将权限更改为比较少见的组合,则使用文本方法可能会更简单、更快,而不是尝试将其转换为数字,这可能会导致错误。对于只需要偶尔使用chmod的用户来说,这两种方法的速度都没有显著的差异。

您也可以用数字形式设置setuid, setgidsticky 权限位。

setuid=4
setgid=2
sticky=1

比如 chmod 2777 filename 将为每个人设置读/写/可执行位,并启用setgid位。

批量 chmod[编辑 | 编辑源代码]

通常,目录和文件不应具有相同的权限。如果需要批量修改目录树,请使用find选择性地修改其中一个或另一个。

若要只把目录权限修改为 755:

$ find directory -type d -exec chmod 755 {} +

若要只把文件权限修改为 644:

$ find directory -type f -exec chmod 644 {} +

修改所有者[编辑 | 编辑源代码]

chown 能够修改文件或者目录的所有者,这在某些情况下会更简单快捷。

比如,您要使用GParted为备份数据创建一个新分区。Gparted以root身份执行所有操作,因此默认情况下所有内容都属于root。这一切都很好,但当要向挂载的分区写入数据时,常规用户会没有权限。

brw-rw---- 1 root disk 8,    9 Jul  6 16:02 sda9
drwxr-xr-x 5 root root    4096 Jul  6 16:01 Backup

若您所见,/dev是由root所有的,而挂载点(/media/Backup也是一样。如果我们要修改挂载点的所有者,您可以执行如下命令:

修改前: drwxr-xr-x 5 root root 4096 Jul 6 16:01 Backup

# chown archie /media/Backup

修改后: drwxr-xr-x 5 archie root 4096 Jul 6 16:01 Backup

现在在无需调整权限的情况下,这个分区就可以由新的所有者 archie 写入了。(作为所有者,它本身就拥有 rwx 权限)

注意:
  • chown 总是会清除 setuid 和 setgid 权限位
  • 非 root 用户不能使用 chown 来把他们自己拥有的文件“送给”其他用户

访问控制列表(ACL)[编辑 | 编辑源代码]

Access Control Lists 通过允许为任何用户或组设置对任何文件的权限,为文件系统提供了额外的、更灵活的权限机制。

Umask[编辑 | 编辑源代码]

umask 实用程序用于控制文件创建模式掩码,该掩码确定了新创建文件的权限位的初始值。

文件属性[编辑 | 编辑源代码]

除了控制用户和组读、写和执行权限的文件权限之外,还有几个文件系统支持文件属性,这些属性可以进一步自定义允许的文件操作。

警告: 默认情况下, cprsync 和其他类似的程序不会保留文件属性

e2fsprogs 软件包内有 lsattr(1)chattr(1) 这两个可以列出和修改文件属性的工具。

以下是一些有用的属性,但并非所有的文件系统都支持每个属性。

  • a - 仅追加(append only):文件只能以追加的方式打开。
  • c - 压缩(compressed):为文件启用文件系统级的压缩。
  • i - 不变(immutable):无法被修改、删除、重命名或创建指向它的链接。只能由root用户设置。
  • j - 数据日志(data journaling):为文件的写入和元数据启用日志
  • m - 不压缩(no compression):为文件禁用文件系统级的压缩。
  • A - 禁用atim更新(no atime update):文件的 atime (访问时间)将不会被修改。
  • C - 禁用写时拷贝(no copy on write): 对于支持写时拷贝的文件系统,禁用写时拷贝。

查看 chattr(1) 以获得更详细的文件属性列表以及它们的作用。

比如,如果您想给某个文件设置不变(immutable)属性,使用如下命令:

# chattr +i /path/to/file

要删除文件上的属性,只需把 + 改为 -

扩展属性[编辑 | 编辑源代码]

根据 xattr(7):“扩展属性是与文件和目录永久关联的键值对”。有四个扩展属性类: security、 system、 trust 和 user。

警告: 默认情况下,cprsync 和其他类似的程序不会保留文件属性。请参考 #保留扩展属性.

扩展属性还用于设置能力(Capabilities).

用户扩展属性[编辑 | 编辑源代码]

用户扩展属性可用于存储有关文件的任意信息,比如:

$ setfattr -n user.checksum -v "3baf9ebce4c664ca8d9e5f6314fb47fb" foo.txt

使用getfattr来显示扩展属性:

$ getfattr -d foo.txt
# file: foo.txt
user.checksum="3baf9ebce4c664ca8d9e5f6314fb47fb"

如果要删除扩展属性:

$ setfattr -x user.checksum foo.txt

保留扩展属性[编辑 | 编辑源代码]

命令 所需的选项
cp --preserve=mode,ownership,timestamps,xattr
mv 默认会保留[注 1]
tar 创建tar档时用 --xattrs ,解压时用 --xattrs-include='*'
bsdtar 解压时用 -p
rsync --xattrs
  1. 当目标文件系统不支持扩展属性时,mv 会静默地丢弃这些扩展属性。

要在使用文本编辑器的时候保留扩展属性,您需要把他们配置为在保存时截断(truncate)文件而非使用 rename(2).[1]

技巧和窍门[编辑 | 编辑源代码]

Preserve root[编辑 | 编辑源代码]

使用 --preserve-root 选项来阻止 chmod 递归地从 / 修改文件权限。 这可以防止在系统范围内删除可执行位,从而破坏系统。要每次使用此标志,请在alias中设置它。参见 [2].

参见[编辑 | 编辑源代码]