chmod 命令
您知道如何重命名您无法读取的文件吗?更进一步,您知道其他用户如何重命名您的文件吗?您是否曾经从另一台主机通过 ftp 下载程序,却无法运行它?
文件权限的主题,以及如何使用 chmod 命令来操作它们,是开始了解这些情况的好起点。
首先,让我们创建一个文件并检查它的长列表。(为了适应杂志版面,本文中的所有列表都经过修剪。)
$ touch test_file $ ls -l test_file -rw-rw-r-- 1 eric users
由于是我创建了这个文件,因此第三列显示我的用户名作为文件所有者,第四列显示我的用户组,这是有道理的。(在某些系统中,用户组名可能与用户名相同。)当您按照这些示例操作时,您将看到您的用户名代替 “eric”。
目录列表的最左列显示文件的 模式。模式是用于指代文件权限的术语。ls 将文件类型和模式一起显示为十个单字符字段的分组
类型字段有几个有效值。为了本教程的目的,我们只关注两个:空 (-) 表示普通文件,d 表示目录。
其他三列涵盖了三种 类别 的访问权限,这些权限存储在类 Unix 文件系统中的每个文件中。Linux(和 Unix)根据用户所有权、用户组所有权和其他(或世界)来评估访问权限。
对于这些类别中的每一个,权限都根据三种 操作 进行评估:读取 (r)、写入 (w) 和执行 (x)。上面的权限指定了所有者的“完全”访问权限,用户组的读取和写入权限,以及其他用户的仅读取权限(一种不寻常的组合,用于演示)。这些权限指定了
文件的所有者被允许读取、写入和执行该文件。
任何属于拥有该文件的用户组的成员的用户都被允许写入该文件。
任何其他用户只能读取该文件。
如果 test_file 是一个非常重要的文档,我们不希望任何人能够修改或删除它,我们需要从用户组中删除写入权限
$ chmod g-w test_file $ ls -l test_file -rw-r--r-- 1 eric users
我们看到用户组的 w 现在被 - 替换,表示用户组 users 的成员被拒绝写入权限。
如果 test_file 包含敏感信息,只有用户组 users 的成员才能查看
$ chmod o-r test_file $ ls -l test_file -rw-r----- 1 eric users
现在我们看到模式字段的最后三元组,它指定了其他用户的权限,都是短划线。这意味着不属于 users 组的其他用户没有任何权限对 test_file 执行任何操作。
chmod 模式的命令行用法如下所示
chmod [options] new-mode filename
新模式以 八进制模式 或 符号模式 指定。我们将首先介绍符号模式。在第一个示例中,我们使用 g-w 删除用户组的写入权限。您可能可以猜到,g 代表用户组,- 代表删除,w 代表写入权限。
$ chmod g+wx test_file $ ls -l test_file -rw-rwx--- 1 eric users
此操作为用户组添加了写入和执行权限。
让我们看一个这些权限在实际操作中的示例。
$ chmod u-rwx test_file $ ls -l test_file ----rwx--- 1 eric users $ cat test_file cat: test_file: Permission denied $ cat .profile > test_file bash: test_file: Permission denied
我们无法显示文件的内容,因为我们没有读取自己文件的权限。当我们指定 u-rwx 给 chmod 时,我们删除了用户(文件所有者)的所有访问权限。当我们尝试将另一个文件的内容添加到其中时,我们也遭到拒绝,因为我们删除了写入权限。(我应该注意,rm 仍然能够删除此文件,尽管它通常会请求确认。)
$ chmod u+rwx test_file $ ls -l test_file -rwxrwx--- 1 eric users
当我们指定 u+rwx 时,所有权限都会恢复。从我们拥有的文件中删除权限不会影响我们恢复权限的能力,因为模式 不 存储在文件中。它存储在称为 inode 条目的结构中。只有文件所有者(和 root 用户)可以修改它。
让我们看一下 chmod 选项的摘要,然后深入介绍每个选项
用户
u 用户(所有者)
g 用户组
o 其他(世界)
a 所有(用户、用户组和其他)
操作
+ 添加
- 删除
= 精确设置
模式
r 读取
w 写入
x 执行
X 有条件地设置执行
s 设置 UID 或设置 GID
t 设置“粘滞位”
$ chmod a+rwx test_file $ ls -l test_file -rwxrwxrwx 1 eric users
这演示了在使用符号模式时,用户的第四个可能的符号。我们使用 a 一次为所有用户类别设置完全权限。让我们删除该文件并重新开始,以演示 = 运算符与 + 和 - 运算符之间的区别。(从现在开始,我们将假设您知道如何获取目录列表,并且不会列出 ls 命令。)
$ rm test_file $ touch test_file -rw-rw-r-- 1 eric users $ chmod g+x test_file -rw-rwxr-- 1 eric users
这为用户组添加了执行权限。
$ chmod g=x test_file -rw---xr-- 1 eric users
= 运算符将用户组的权限设置为执行,这样做删除了读取和写入权限。虽然 + 和 - 设置或取消设置指定的权限,但 = 将 精确地 设置指定的模式,并删除任何其他模式。
当引用文件时,读取、写入和执行模式非常直接。读取和写入允许用户分别检查和修改/删除文件中的数据。执行允许用户执行 shell 脚本或二进制程序。如果您从一台主机通过 ftp 下载程序到另一台主机,然后尝试在不设置执行权限的情况下运行它,它将失败,因为 ftp 不会设置执行权限。
对于目录,规则可能稍微复杂一些。
读取权限允许用户检查目录的内容。
$ mkdir test_dir $ touch test_dir/foo $ ls test_dir foo $ chmod u-r test_dir $ ls test_dir ls: test_dir: Permission denied
写入权限允许用户修改 目录的内容。这意味着,如果文件权限允许,目录上缺少写入权限不会阻止用户修改目录中的文件。它 确实 会阻止用户重命名、移动、删除或创建目录中的任何文件。这是因为目录实际上是一个文件,其中包含文件名列表,因此读取和写入权限控制对该列表的访问。
$ chmod u=rx test_dir dr-xrwxr-x 2 eric users $ touch test_dir/bar touch: test_dir/bar: Permission denied $ mv test_dir/foo ./foo mv: cannot move `test_dir/foo' to `./foo': Permission denied
此属性也以另一种方式起作用。由于写入权限允许修改目录条目,因此用户可以移动或重命名文件,而无需权限检查内容。这是关注重要目录的写入权限的一个非常好的理由。
为了演示
$ ls -l test_dir -rw-rw-r-- 2 eric users foo $ chmod u=rwx test_dir $ chmod u=rx test_dir/foo $ cat .bashrc > test_dir/foo bash: test_dir/foo: Permission denied $ mv test_dir/foo ./foo $ ls test_dir (It's empty) $ ls foo foo (It's in our present directory.)
目录的执行权限(也称为搜索权限)也非常重要。执行权限对于 访问 目录是必要的。
$ chmod u=rwx test_dir
$ cp ~/.bashrc test_dir
(any text file will do)
$ chmod u=rw test_dir
$ cd test_dir
bash: test_dir: Permission denied
$ cat test_dir/.bashrc
cat: test_dir/.bashrc: Permission denied
此 .bashrc 副本对我们没有太大用处。但是,为目录设置执行权限而不设置读取或写入权限可能会派上用场。
$ chmod u=x test_dir
$ cat test_dir/.bashrc
(we see the contents of the file)
$ ls test_dir
ls: test_dir: Permission denied
仅具有执行权限的目录可用于“隐藏”文件。只有知道确切文件名和路径的用户才能访问它们;这包括数据文件和程序。
让我们回到 test_file 来检查 X 选项。
$ chmod u=rw,g=r,o=r test_file -rw-r--r-- 1 eric users $ chmod o+X test_file -rw-r--r-- 1 eric users $ chmod u+x test_file -rwxr--r-- 1 eric users $ chmod o+X test_file -rwxr--r-x 1 eric users
在第一个命令中,我们看到可以通过使用逗号分隔模式规范,一次为多个类别设置选项。在这里,我们设置模式,以便任何用户都没有执行权限。在第二个命令中,我们尝试使用 X 为其他用户设置执行权限。这失败了,因为 X 仅在其中一个类别已经具有执行权限时才起作用。当我们为所有者添加执行权限时,X 为其他用户设置了执行权限。
s 选项设置或删除设置 UID (SUID) 和设置 GID (SGID) 模式。这些模式在 UNIX/Linux 安全性方面非常重要。当文件设置了 SUID 模式时,执行它的进程在程序执行期间具有文件所有者的有效权限。
例如,程序 dip 用于创建 SLIP 网络连接。这需要 root 访问权限,因为创建网络接口设备需要 root 访问权限。dip 程序可以属于 root 用户并设置 SUID 模式,而不是强迫用户成为 root 用户才能使用 dip,这将需要用户知道 root 密码。
$ ls -l /usr/sbin/dip -r-s--x--- 1 root dip
用户执行字段中的 s 表示已设置 SUID 模式。SUID 模式的另一个用途示例是 passwd 程序,它允许用户修改 passwd(或 shadow)文件。
出于安全原因,SUID 位只能影响二进制程序;它对 Linux 中的 shell 脚本没有影响。
SGID 模式设置用户组而不是所有者,并使用(例如)g+s 设置。它还有另一个用途。
当用户创建新文件时,用户组所有权默认为用户的默认用户组,该用户组在 passwd 文件中列出。有时用户属于多个用户组,并且想要共享文件。SGID 模式可以为此提供一种方便的方法。如果为目录设置了 SGID 模式位,则在该目录中创建的新文件将属于该用户组,而与创建者的默认用户组无关。如果您属于多个用户组,请尝试这样做。(您可以使用 id 命令检查您属于哪些用户组。默认用户组列在最前面,您可以使用 chgrp 命令将文件的用户组所有权更改为您所属的另一个用户组。)
$ mkdir test_dir $ chgrp nondefault test_dir $ chmod g+s test_dir $ touch test_dir/foo $ ls -l test_dir/foo -rw-rw-r-- 1 eric nondefault
SUID 和 SGID 模式可能是一个安全漏洞。但是,当谨慎使用时,它们是非常有价值的工具,实际上通过提供重要密码的替代方案来增强系统安全性。
指定用户类别可用于简化复制权限。
$ chmod g=u test_file -rwxrwxr-x 1 eric users
这会将权限从用户复制到用户组。所有类别都可以在 +、- 或 = 运算符的右侧以这种方式使用。
$ chmod o-u test_file -rwxrwx--- 1 eric users
这将清除其他用户拥有的用户的所有权限。
上面列出的最后一个模式是 t 选项,称为“粘滞位”。此模式实际上在命令行上受支持,以便与来自较旧操作系统的 shell 脚本兼容。Linux 不需要它。如果安装指南指示您使用它,它实际上什么也不做。
文件访问模式也可以使用八进制表示法设置。此语法是通过将模式字段相加构建的。对于每个用户类别,字段的计算方式如下
4 读取
2 写入
1 执行
任何类别的完全权限都将是 7,没有权限将是 0。
$ chmod 754 test_file -rwxr-xr-x 1 eric users
类别以 ls 显示它们的相同顺序传递给 chmod。我们设置的模式按以下方式分解
Owner = 4 + 2 + 1 = 7 Group = 4 + 1 = 5 World = 4 = 4
八进制模式很方便,因为其他实用程序(如 find)期望以这种方式表示模式。
在八进制模式下,SUID 和 SGID 通过在用户模式 之前 的另一列中指定它们来设置。对于 SUID 使用 4,对于 SGID 使用 2,对于两者都使用 6
$ chmod 4755 test_file -rwsr-xr-x 1 eric users
Chmod 还提供了一些命令行选项来简化管理任务。对于在目录树中更改文件权限,请使用 -R。
$ chmod -R g-w test_dir
这将删除 test_dir 及其下所有文件中用户组的写入权限。
为了控制来自 chmod 的消息输出,请使用 -c、-v 和 -f
$ chmod -v 700 test_file mode of test_file changed to 0700 (rwx------)
此选项使 chmod 显示 test_file 的权限是如何设置的。-c 选项使 chmod 仅在文件更改时显示消息,-f 选项抑制有关无法更改的文件的消息。
Chmod 还提供了 --version 选项来显示版本,以及 --help 来查看简短的帮助消息。
Eric Goebelbecker (eric@cnct.com) 是路透社美国公司 (Reuters America, Inc.) 的系统分析师。他为使用市场数据检索和操作 API 的交易室和后台运营部门的客户(主要是金融机构)提供支持。在他的业余时间(每周约 15 分钟...),他阅读哲学并研究 Linux。