第九章 权限

前言

  1. 传统的 UNIX 操作系统与那些传统的 MS-DOS 操作系统不同,区别在于它们不仅是多重任务处理系统,而且还是多用户系统。
  2. 为了保证多用户功能实际可用,Linux 系统特别设计了一种方案来保护当前用户不受其他用户操作的影响。
  3. 本章将介绍系统安全的基础知识以及如下命令的使用:
  • id: 显示用户身份标识
  • chmod: 更改文件的模式
  • umask: 设置文件的默认权限
  • su: 以另一个用户的身份运行shell
  • sudo: 以另一个用户的身份来执行命令
  • chown: 更改文件所有者
  • chgrp: 更改文件所属群组
  • passwd:更改用户密码

所有者、组成员和其他所有用户

  1. 我们在第四章讲解文件系统时,当试图查看类似 /etc/shadow 的文件时,会遇到下面的问题:
    1
    2
    3
    4
    [me@linuxbox ~]$ file /etc/shadow
    /etc/shadow: regular file, no read permission
    [me@linuxbox ~]$ less /etc/shadow
    /etc/shadow: Permission denied
  2. 产生这种错误信息的原因是,作为一个普通用户,没有读取这个文件的权限。
  3. 在 UNIX 安全模型中,一个用户可以拥有 (own) 文件和目录。当一个用户拥有一个文件或者目录时,它将对该文件或目录的访问权限拥有控制权。
  4. 用户又归属于一个群组 (group) ,该群组由一个或者多个用户组成,组中用户对文件和目录的访问权限由其所有者授予。除了可以授予群组访问权限之外,文件所有者也可以授予所有用户一些访问权限。在 UNIX 术语中,所有用户是指整个世界 (world) 。
  5. 使用 id 命令可以获得用户身份标识的相关信息,如下所示:
    1
    2
    [me@linuxbox ~]$ id
    uid=500(me) gid=500(me) groups=500(me)
  6. 查看 id 命令的输出结果。在创建用户账户的时候,用户被分配一个称为用户 ID 或者 uid 的号码。
  7. 为了符合人们的使用习惯,用户 ID 与用户名一一映射。同时用户将被分配一个有效组 ID 或者称为 gid ,而且该用户也可以归属其他用户群组。
  8. 前面的例子是在 Fedora 系统中运行的结果。在其他系统中,比如 Ubuntu 系统,输出结果可能有一些不同。
    1
    2
    3
    [me@linuxbox ~]$ id
    uid=1000(me) gid=1000(me)
    groups=4(adm), 20(dialout), 24(cdrom), 25(floppy), 29(audio), 30(dip), 44(video), 46(plugdev), 108(lpadmin), 114(admin), 1000(me)
  9. 我们可以发现,两个系统中用户的 uid 和 gid 号码是不同的。原因很简单,因为在 Fedora 系统中,普通用户账户是从 500 开始编号的,而在 Ubuntu 系统中则是从 1000 开始编号。同时我们也可以发现,Ubuntu 系统中的用户归属于更多的群组。这和 Ubuntu 系统中的用户归属于更多的群组。这和 Ubuntu 系统管理系统设备和服务权限的方式有关。
  10. 用户账户定义在文件 /etc/passwd 中,用户组定义在文件 /etc/group 文件中。在创建用户账户和群组时,这些文件随着文件 /etc/shadow 的变动而修改,文件 /etc/shadow 中保存了用户的密码信息。
  11. 对于每一个用户账户,文件 /etc/passwd 中都定义了对应用户的用户 (登录) 名、uid、gid、账户的真实姓名、主目录以及登录 shell 信息。
  12. 如果查看文件 /etcpasswd 和文件 /etc/group 的内容,那么你将会发现除了普通用户账户信息之外,文件中还有对应于超级用户 (uid=0) 和其他不同种类的系统用户的账户信息。
  13. 许多类 UNIX 系统会把普通用户分配到一个公共群组中 (比如,users) ,然而现在的 Linux 操作则是创建一个独一无二的,只有一个用户的群组,而且组名和用户的名字相同。这使得特定类型的权限分配变得更加容易。

读取、写入和执行

文件模式

  1. 基本介绍
  • 对文件和目录的访问权限是按照读访问、写访问以及执行访问来定义的。
  • 当我们查看 ls 命令的输出结果时,可以得到一些线索,了解其实现方式。
    1
    2
    3
    [me@linuxbox ~]$ > foo.txt
    [me@linuxbox ~]$ ls -l foo.txt
    -rw-rw-r-- 1 me me 0 2012-03-03 14:52 foo.txt
  • 列出输出结果中的前 10 个字符表示的是文件属性 (file attribute) ,其中第一个字符表示文件类型 (file type) 。
  • 文件属性中剩下的 9 个字符称为文件模式 (file mode) ,分别表示文件所有者、文件所属群组以及其他所有用户对该文件的读取、写入和执行权限。
  • 在文件属性中,第一部分代表文件类型、第二部分代表所有者权限、第三部分代表组权限、第四部分代表其他用户权限。
  1. 文件属性
第一部分 第二部分 第三部分 第四部分
- rwx rw- r–
  1. 文件类型
属性 文件类型
- 普通文件
d 目录文件
l 符号链接。注意对于符号链接文件,剩下的文件始终是 rwxrwxrwx ,它是一个为属性值。符号链接指向的文件属性才是真正的属性
c 字符设备文件。该文件类型表示以字节流形式处理数据的设备,如终端或调制解调器
b 块设备文件,该文件类型表示以数据块方式处理数据的设备,如硬盘驱动或者光盘驱动
  1. 模式属性
属性 文件 目录
r 允许打开和读取文件 如果设置了执行权限,那么允许列出目录下的内容
w 允许写入或者截短文件,如果也设置了执行权限,那么目录中的文件允许被创建、被删除以及被重命名 但是该权限不允许重命名或者删除文件。是否能重命名和删除文件由目录权限决定
x 允许把文件当作程序一样执行。用脚本语言写的程序文件必须被设置为可读,以便能被执行 允许进入目录下
  1. 权限属性实例
文件属性 含义
-rwx—— 普通文件,文件所有者具有读取、写入和执行权限。组成员和其他所有用户都没有任何访问权限
-rw——- 普通文件,文件所有者具有读取和写入权限。组成员和其他所有用户都没有任何访问权限
-rw-r–r– 普通文件,文件所有者具有读取和写入权限。文件所有者所在群组的成员可以读取该文件。该文件对于所有用户来说都是可读的。
-rwxr-xr-x 普通文件,文件所有者具有读取、写入和执行权限。其他所有用户也可以读取和执行该文件
-rw-rw—- 普通文件,只有文件所有者和文件所有者所在群组的成员具有读取和执行权限
lrwxrwxrwx 符号链接。所有的符号链接显示的都是伪权限属性,真正的权限属性由符号链接指向的实际文件决定
dwxrwx—- 目录文件。文件所有者和所有者所在群组的成员都可以进入该目录,而且可以创建、重命名和删除该目录下的文件
drwxr-x— 目录文件。文件所有者可以进入该目录,而且可以创建、重命名和删除该目录下的文件。所有者所在群组的成员可以进入该目录,但不能创建、重命名和删除该目录下的文件

chmod - 更改文件模式

  1. chmod 基本介绍
  • 我们可以使用 chmod 命令来更改文件或目录的模式 (权限) 。需要注意的是只有文件所有者和超级用户才可以更改文件或目录的模式。
  • chmod 命令支持两种不同的改变文件模式的方法-八进制数字表示法和符号表示法。
  1. 八进制数字表示法
  • 八进制数字表示法指的是使用八进制数字来设置所期望的权限模式。因为每个八进制数字对应着 3 个二进制数字,所以这种对应关系正好可以和用来存储文件模式的结构方式一一映射。
  • 通过使用 3 位八进制数字,我们可以分别设置文件所有者、组成员和其他用户 (world) 的文件模式。
  • 虽然看起来,要记住八进制和二进制之间的映射关系好像不是那么简单,但是实际上,常用的也就只有这几个而已:7(rwx)、6(rw-)、5(r-x)、4(r–) 和 0(—) 。
  1. 二进制和八进制方式表示文件模式
八进制 二进制 文件模式
0 000
1 001 –x
2 010 -w-
3 010 -wx
4 100 r–
5 101 r-x
6 110 rw-
7 111 rwx
  1. 符号表示法
  • chmod 命令支持一种符号表示法来指定文件模式。
  • 符号表示法分为三部分:更改会影响谁、要执行哪个操作以及要设置哪种权限。
  • 可以通过字符 u、g、o 和 a 的组合来指定要影响的对象。
  • 如果没有指定字符,则假定使用 all 。
  • 操作符 + 表示添加一种权限,- 表示删除一种权限,= 表示只有指定的权限可用,其他所有的权限都被删除。
  1. chmod 命令符号表示法
符号 含义
u user 的简写,表示文件或者目录的所有者
g 文件所属群组
o others 的简写,表示其他所有用户
a all 的简写,是 u,g 和 o 三者组合
  1. chmod 命令符号表示法实例
符号 含义
u+x 为文件所有者添加可执行权限
u-x 删除文件所有者的可执行权限
+x 为文件所有者、所属群组和其他所有用户添加可执行权限,等价于 a+x
o-rw 除了文件所有者和所属群组之外,删除其他所有用户的读写权限
go=rw 除了文件所有者之外,设置所属群组和其他所有用户具有读写权限。如果所属群组或者其他所有用户之前已经具有可执行权限,那么删除他们的可执行权限
u+x,go=rx 为文件所有者添加可执行权限,同时设置所属群组和其他所有用户具有读权限和可执行权限。指定多种权限时,需用逗号分隔

umask - 设置默认权限

  1. umask 命令控制着创建文件时指定给文件的默认权限。它使用八进制表示法来表示从文件模式属性中删除一个位掩码。参见下面的例子:
    1
    2
    3
    4
    5
    6
    [me@linuxbox ~]$ rm -f foo.txt
    [me@linuxbox ~]$ umask
    0002
    [me@linuxbox ~]$ > foo.txt
    [me@linuxbox ~]$ ls -l foo.txt
    -rw-rw-r-- 1 me me 0 2012-03-06 14:53 foo.txt
  2. 首先删除 foo.txt 文件存在的所有副本,以保证一切都是重新开始。
  3. 下一步,运行不带任何参数的 unmask 命令,查看当前掩码值,得到的值是 0002 (0022 是另一个常用默认值) ,它是掩码的八进制表示形式,接着创建文件 foo.txt 的一个新实例,查看该文件的权限。
  4. 可以发现,文件所有者和组都获得了读写权限,而其他所有用户则只获得读权限。其他所有用户没有写权限的原因在于掩码值。重复执行该实例,不过这次是自己设置掩码值。
    1
    2
    3
    4
    5
    [me@linuxbox ~]$ rm foo.txt
    [me@linuxbox ~]$ umask 0000
    [me@linuxbox ~]$ > foo.txt
    [me@linuxbox ~]$ ls -l foo.txt
    -rw-rw-rw- 1 me me 0 2012-03-06 14:58 foo.txt
  5. 在设置掩码为 0000 (实际上是关闭该功能) 时,可以看到其他所有用户也拥有写权限了。

更改身份

  1. 基本介绍
  • 在很多时候,我们会发现可以拥有另一个用户的身份是很有必要的。
  • 我们经常会需要获得超级用户的特权来执行一些管理任务,但是也可以变成另一个普通用户来执行这些任务,就好像是在测试一个账户。
  • 有三种方法用来转换身份,具体如下:
    • 注销系统并以其他用户的身份重新登录系统。
    • 使用 su 命令。
    • 使用 sudo 命令。
  1. 因为大家都知道如何操作第一种方法,而且它不如其他两种方法来的方便,所以这里跳过第一种方法。
  2. 在 shell 会话状态下,使用 su 命令将允许你假定为另一个用户的身份,既可以以这个用户的 ID 来启动一个新的 shell 会话,也可以以这个用户的身份来发布一个命令。
  3. 使用 sudo 命令将允许管理者创建一个称为 /etc/sudoer 的配置文件,并且定义一些特定的命令,这些命令只有赋予为假定身份的特定用户才允许执行。
  4. 选择使用哪个命令在很大程度上取决于使用的 Linux 发行版本。有些发行版本可能对两个命令都支持,但是它的系统配置可能只是偏向于其中一个。

su - 以其他用户和组 ID 的身份来运行 shell

  1. su 命令用来以另外一个用户来启动 shell 。该命令的一般形式如下:
    1
    su [-[l]] [user]
  2. 如果包含 -l 选项,那么得到的 shell 会话界面将是用于指定用户的登录 shell (login shell) 界面。这就意味着,该指定用户的运行环境将被加载,而且其工作目录也将更改为该指定用户的主目录。
  3. 如果没有指定用户,那么默认假定为超级用户。需要注意的是,-l 可以缩写为 - ,而且这一形式经常被使用。我们可以通过以下的操作来以超级用户的身份启动 shell 。
    1
    2
    3
    [me@linuxbox ~]$ su -
    Password:
    [root@linuxbox ~]#
  4. 在输入 su 命令后,系统会提示输入该超级用户的密码。如果密码输入正确,那么将会出现新的 shell 提示符,该提示符表示该 shell 将拥有超级用户的特权 (提示符的末尾字符是 # ,而不是 $ ) ,而且当前的工作目录现在也是用于超级用户的主目录 (通常情况下为 /root ) 。
  5. 一旦进入了这个新的 shell 环境,我们就可以以超级用户的身份执行命令了。在使用结束时,输入 exit ,将返回到之前的 shell 环境。
    1
    2
    [root@linuxbox ~]# exit
    [me@linuxbox ~]$
  6. 我们也可以使用 su 命令执行单个命令,而不需要开启一个新的交互式命令界面,操作方式如下
    1
    su -c 'command'
  7. 使用这种格式,单个命令行被传递到一个新的 shell 环境下执行,而是希望在新的 shell 环境下执行。
    1
    2
    3
    4
    5
    6
    [me@linuxbox ~]$ su -c 'ls -l /root/*'
    Password
    -rw------- 1 root root 754 2011-08-11 03:19 /root/anaconda-ks.cfg
    /root/Mail:
    total 0
    [me@linuxbox ~]$

sudo - 以另一个用户的身份执行命令

  1. sudo 命令在很多方面都类似于su命令,但是它另外还有一些重要的功能。管理者可以通过配置 sudo 命令,使系统以一种可控方式,允许一个普通用户以一个不同的用户身份 (通常是超级用户) 执行命令。
  2. 在特定情况下,用户可能被限制为只能执行一条或者几条特定的命令,而对其他命令没有执行权限。另一个重要的区别在于,使用 sudo 命令并不需要输入超级用户密码。
  3. 使用 sudo 命令时,用户只需要输入自己的密码来进行认证。
  4. 比如说,配置 sudo 命令来允许普通用户运行一个虚构的备份程序 (称为 backup_script) ,这个程序需要超级用户权限。
  5. 通过 sudo 命令,该程序将会以如下方式运行。
    1
    2
    3
    [me@linuxbox -]$ sudo backup_script
    Password:
    System Backup Starting...
  6. 在输入 sudo 命令后,系统将提示输入用户自己的密码 (而不是超级用户的密码) ,而且一旦认证通过,指定的命令就被执行。
  7. su 命令和 sudo 命令之间的一个重要区别在于 sudo 命令并不需要启动一个新的 shell 环境,而且也不需要加载另一个用户的运行环境。
  8. 这意味着,使用 sudo 命令的时候并不需要用单引号把命令引起来。
  9. 需要注意的是,我们可以通过指定不同的选项来改变命令执行的效果。
  10. 查看 sudo 命令的帮助页面可以获得更多的细节内容。
  11. 要想知道 sudo 命令可以授予权限,可以使用 -l 选项来查看,具体如下:
    1
    2
    3
    [me@linuxbox ~]$ sudo -l
    User me may run the following commands on this host:
    (ALL) ALL

chown - 更改文件所有者和所属群组

  1. chown 基本介绍
  • chown 命令用来更改文件或者目录的所有者和所属群组。使用这个命令需要超级用户权限。
  • chown 命令的语法格式如下:
    1
    chown [owner][:[group]] file ...
  • chown 命令更改的是文件所有者还是文件所属群组,或者对两者都更改,取决于该命令的第一个参数。
  1. chown 命令参数实例
参数 结果
bob 把文件从当前所有者更改为用户 bob
bob:users 把文件所有者从当前所有者更改为用户 bob ,并把文件所述群组更改为 users 组
:admins 把文件所属群组更改为 admins 组,文件所有者不变
bob: 把文件所有者从当前所有者更改为用户 bob ,并把文件所述群组更改为用户登录时所属的组
  1. chown 案例
  • 假设有两个用户-拥有超级用户权限的 janet 和没有该权限的 tony 。
  • 用户 janet 想要从她的主目录复制一个文件到用户 tony 的主目录中。
  • 因为用户 janet 希望 tony 能够编辑该文件,所以 janet 把该文件的所有者从 janet 更改为 tony ,具体操作如下
    1
    2
    3
    4
    5
    6
    7
    [janet@linux ~]$ sudo cp myfile.txt ~tony
    Password:
    [janet@linux ~]$ sudo ls -l ~tony/myfile.txt
    -rw-r--r-- 1 root root 8031 2012-03-20 14:30 /home/tony/myfile.txt
    [janet@linux ~]$ sudo chown tony: ~tony/myfile.txt
    [janet@linux ~]$ sudo ls -l ~tony/myfile.txt
    -rw-r--r-- 1 tony tony 8031 2012-03-20 14:30 /home/tony/myfile.txt
  • 这里我们可以看到,用户 janet 首先把文件从她的目录复制到用户 tony 的主目录中。
  • 接下来,janet 把该文件的所有者从 root (使用 sudo 命令的结果) 更改为 tony 。
  • 通过在第一个参数末尾加上冒号, janet 也把文件的所属群组更改成了 tony 登录系统时所属的组,该组名碰巧也叫 tony 。

chgrp - 更改文件所属群组

  1. 在更早的 UNIX 版本中,chown 命令只能更改文件的所有者,而不能改变文件所属群组。
  2. 为了达到这个目的,我们可以使用一个独立的命令 chgrp 来实现。该命令除了限制多一点之外,和 chown 命令使用方式几乎相同。

权限的使用

  1. 假设有两个用户,分别命名为 bill 和 karen 。他们都有音乐 CD 集,并想要创建一个共享目录,在该目录下他们各自以 Ogg Vorbis 格式或者 MP3 格式存储音乐文件。用户 bill 通过 sudo 命令获得了超级用户的访问权限。
  2. 第一件需要做的事情,就是创建一个 bill 和 karen 为成员的组。通过使用 GNOME 的图形化用户管理工具,bill 创建了一个组,命令为 music ,并且把 bill 和 karen 添加到该组中。
  3. 接下来,bill 创建了存储音乐文件的目录。
    1
    2
    [bill@linuxbox ~]$ sudo mkdir /usr/local/share/Music
    Password:
  4. 因为 bill 正在操作的对象是他的主目录之外的文件,所以他需要拥有超级用户的权限。新创建的目录具有以下的所有权和权限。
    1
    2
    [bill@linuxbox ~]$ ls -ld /usr/local/share/Music 
    drwxr-xr-x 2 root root 4096 2012-03-21 18:05 /usr/local/share/Music
  5. 可以看到,这个目录由 root 用户所有,而且权限值为 775 。要使得该目录可共享,bill 需要更改该目录的所有群组,而且该组需要具有写入权限。
    1
    2
    3
    [bill@linuxbox ~]$ sudo chown :music /usr/local/share/Music
    [bill@linuxbox ~]$ sudo chmod 775 /usr/local/share/Music
    arwxrwxr-x 2 root music 4096 2012-03-21 18:05 /usr/local/share/Music
  6. 它意味着当前我们已经有了 /usr/local/share/Music 目录,该目录由 root 用户所有,而且 music 组拥有该目录的读写权限。 music 组的成员为 bill 和 karen ,因此 bill 和 karen 都可以在目录 /usr/local/share/Music 下创建文件。其他用户列出了该目录下的内容,但不能在该目录下创建文件。
  7. 在当前的权限下,在 Music 目录下创建的文件和目录拥有目录 bill 和 karen 的常规权限。
    1
    2
    3
    [bill@linuxbox ~]$ > /usr/local/share/Music/test_file
    [bill@linuxbox ~]$ ls -l /usr/local/share/Music
    -rw-r--r-- 1 bill bill 0 2012-03-24 20:03 test_file
  8. 第一个问题是,系统中默认掩码是 0022 ,这将不会允许组成员对属于组内其他成员的文件执行写入操作。
  9. 如果共享目录中只包含文件,那么这倒不是问题,但是因为该目录下将存放音乐文件,而音乐文件一般都是按照艺术家和唱片集的层次结构来组织分类的,所以组成员需要拥有能在同组其他成员创建的目录下创建文件和目录权限。需要把 bill 和 karen 使用的掩码值更改成 0002 。
  10. 第二个问题是,由成员创建的每一个文件和目录都将设置为归属于该用户的有效组,而不归属 music 组。可以通过对该目录设置 setgid 位来修复这个问题。
    1
    2
    3
    [bill@linuxbox ~]$ sudo chmod g+s /usr/local/share/Music
    [bill@linuxbox ~]$ sudo -ld /usr/local/share/Music
    drwxrwxr-x 2 root music 4096 2012-03-24 20:03 /usr/local/share/Music
  11. 现在来测试一下,看看是否新的权限修复了这个问题。bill 把它的掩码值设置为 0002 ,删除了之前的测试文件,又创建了一个新的测试文件和目录。
    1
    2
    3
    4
    5
    6
    7
    [bill@linuxbox ~]$ umask 0002
    [bill@linuxbox ~]$ rm /usr/local/share/Music/test_file
    [bill@linuxbox ~]$ > /usr/local/share/Music/test_dir
    [bill@linuxbox ~]$ ls -l /usr/local/share/Music
    drwxrwxr-x 2 bill music 4096 2012-03-24 20:24 test_dir
    -rw-rw-r-- 1 bill music 0 2012-03-24 20:22 test_file
    [bill@linuxbox ~]$
  12. 当前创建的文件和目录都具有正确的权限,允许 music 组内的所有成员在 Music 目录下创建文件和目录。
  13. 最后剩下的一个问题是关于 umask 命令的。umask 命令设置的掩码值只能在当前 shell 会话中生效,在当前 shell 会话结束后,则必须重新设置。

更改用户密码

  1. 本章的最后一个主题就是用户如何为自己设置密码 (如果拥有超级用户权限,那么也可以为其他的用户设置密码) 。
  2. 使用 passwd ,可以设置或者更改密码。该命令的语法格式如下。
    1
    passwd [user]
  3. 如果更改的是用户自己的密码,那么只需要输入 passwd 命令。接下来 shell 将会提示用户输入旧密码和新密码。
    1
    2
    3
    [me@linuxbox ~]$ passwd
    (current) UNI password:
    New UNIX password:
  4. passwd 命令会试着强迫用户使用强密码。也就是说,它会拒绝接受太短的密码、与之前的密码相似的密码、字典中的单词作为密码或者是太容易猜到的密码。
    1
    2
    3
    4
    5
    6
    7
    8
    [me@linuxbox ~]$ passwd
    (current) UNIX password:
    New UNIX password:
    BAD PASSWORD: is too similar to the old one
    New UNIX password:
    BAD PASSWORD: it is WAY too short
    New UNIX password:
    BAD PASSWORD: it is based on a dictionary word
  5. 如果你具有超级用户的权限,那么可以通过指定一个用户名作为 passwd 命令的参数来为另一个用户设置密码。
  6. 对于超级用户,你还可以使用该命令的其他选项来设置账户锁定、密码失效等功能。

参考文章

  • 转载:Linux 命令行大全