Linux之权限

传统的UNIX操作系统与那些传统的MS-DOS操作系统不同,区别在于它们不仅是多重任务处理(multitasking)系统,而且还是多用户(multiuser)系统。
确切地说,这意味着什么呢?这意味着同一时间内可以有多个用户使用同一台计算机。虽然一台标准的计算机可能只包含一个键盘和一台显示器,但是它仍然可以同时被一个以上的用户使用。
例如,如果计算机连接到一个网络或者互联网中,远程用户可以通过ssh(安全shell)登录并且操作这台计算机。事实上,远程用户可以执行图形化应用程序,而且图形化的输出结果将会出现在远程显示器上。X窗口系统把这个作为基本设计理念的一部分,并支持这种功能。
为了保证多用户功能实际可用,系统特别设计了一种方案来保护当前用户不受其他用户操作的影响,毕竟,一个用户的操作不能导致计算机崩溃,一个用户的操作界面也不能显示属于另一个用户的文件。

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

当我们试图查看类似/etc/shadow的文件时,会遇到下面的问题

在这里插入图片描述

产生这种错误信息的原因是,作为一个普通用户,没有读取这个文件的权限。
在UNIX安全模式中,一个用户可以拥有(own)文件和目录。当一个用户拥有一个文件或者目录时,它将对该文件或目录的访问权限拥有控制权。反过来,用户又归属于一个群组(group),该群组由一个或多个用户组成,组中用户对文件和目录的访问权限由其所有者授予。除了可以授予群组访问权限之外,文件所有者也可以授予所有用户一些访问权限,在UNIX术语中,所有用户是指整个世界(world)。使用id命令可以获得用户身份标识的相关信息,如下所示

在这里插入图片描述
查看id命令的输出结果。在创建用户账户的时候,用户将被分配一个称为用户ID(user ID)或者uid的号码。为了符合人们的使用习惯,用户ID与用户名一一映射。同时用户将被分配一个有效组ID(primary group ID)或者称为gid,而且该用户也可以归属于其他的群组。
那么这些信息是从哪里来的呢?类似于Linux系统中的很多情况,这些信息来源于一系列的文本文件。用户账户定义在/etc/passwd文件中,用户组定义在/etc/group文件中,文件/etc/shadow中保存了用户的密码信息。
对于每一个用户账户,/etc/passwd中都定义了对应用户的用户(登录)名、uid、gid、账户的真实姓名、主目录以及登录shell信息。如果查看文件/etc/passwd和/ect/group的内容,那么你将会发现除了普通用户账户信息之外,文件中还有对应于超级用户(uid为0)和其他不同种类的系统用户的账户信息。
许多类UNIX系统会把普通用户分配到一个公共的群组中(比如users),然而现在的Linux操作则是创建一个独一无二的,只有一个用户的群组,而且组名和用户的名字相同,这使得特定类型的权限分配变得更加容易。

2.读取、写入和执行

对文件和目录的访问权限是按照读访问、写访问以及执行访问来定义的。当我们查看ls命令的输出结果时,可以得到一些线索,了解其实现方式。
在这里插入图片描述
列在输出结果中的前10个字符表示的是文件属性(file attribute,见下表),其中第一个字符表示文件类型

-   rw-   r--   r--
1   2     3     4
1:文件类型
2:所有者权限
3:组权限
4:其他用户权限
属性文件类型
.普通文件
d目录文件
l符号链接。注意对于符号链接文件,剩下的文件属性始终是rwxrwxrwx,它是个伪属性值,符号链接指向的文件的属性才是真正的文件属性
c字符设备文件。该文件类型表示以字节流形式处理数据的设备,如终端或调制解调器
b块设备文件。该文件类型表示以数据块方式处理数据的设备,如硬盘驱动或者光盘驱动

文件属性找中剩下的9个字符称为文件模式,分别表示文件所有者、文件所属群组以及其他所有用户对该文件的读取、写入和执行权限。
分别设置r(读取)、w(写入)和x(执行)的模式属性将会对文件和目录带来不同的影响

属性文件目录
r允许打开和读取文件如果设置了执行权限,那么允许列出目录下的内容
w允许写入或者截短文件;如果也设置了执行权限,那么目录中的文件允许被创建、被删除以及被重命名但是该权限不允许重命名或者删除文件 是否能重命名和删除文件由目录权限决定
x允许把文件当做程序一样执行。用脚本语言写的程序必须被设置为可读,以便能被执行允许进入目录下,例如cd directory

下表给出了一些文件属性设置的例子。

文件属性含义
-rwx------普通文件,文件所有者具有读取、写入和执行权限。组成员和其他所有用户都没有任何访问权限
-rw-------普通文件,文件所有者具有读取和写入权限,组成员和其他所有用户都没有任何访问权限
-rw-r–r–普通文件,文件所有者具有读取和写入权限,文件所有者所在群组的成员可以读取该文件。该文件对于所有用户来说都是可读的
-rwxr-xr-x普通文件,文件所有者具有读取、写入和执行权限,其他所有用户也可以读取和执行该文件
-rw-rw----普通文件,只有文件所有者和文件所有者所在群组的成员具有读取和写入的权限
lrwxrwxrwx符号链接。所有的符号链接文件显示的都是“伪”权限属性,真正的权限属性由符号链接指向的实际文件决定
d-wxrwx—目录文件,文件所有者和所有者所在群组的成员都可以进入该目录,而且可以创建、重命名和删除该目录下的文件
drwxr-x—目录文件,文件所有者可以进入目录,而且可以创建、重命名和删除该目录下的文件。所有者所在群组的成员可以进入该目录,但是不能创建、重命名和删除该目录下的文件

2.1 chmod更改文件模式

我们可以使用chmod命令来更改文件或者目录的目录的模式(权限)。需要注意的是只有文件所有者和超级用户才可以更改文件或者目录的模式。chmod命令支持两种不同的改变文件模式的方式,八进制数字表示法和符号表示法。

2.1.1 八进制数字表示法

八进制数字表示法指的是使用八进制数字来设置所期望的权限模式。因为每个八进制数字对应着3个二进制数字,所以这种对应关系正好可以和用来存储文件模式的结构方式一一映射

八进制二进制文件模式
0000
1001–x
2010-w-
3011-wx
4100r–
5101r-x
6110rw-
7111rwx

通过使用3位八进制数字,我们可以分别设置文件所有者、组成员和其他所有用户的文件模式。
在这里插入图片描述
通过传递参数600,我们可以设置文件所有者的读写权限,而取消组用户和其他所有用户的权限。
常用的几个映射关系:7(rwx)、6(rw-)、5(r-x)、4(r–)和0(—)

2.1.2 符号表示法

chmod命令支持一种符号表示法来指定文件模式。该符号表示法分为三部分:更改会影响谁、要执行哪个操作以及要设置哪种权限。可以通过字符u、g、o和a的组合来指定要影响的对象

符号含义
uuser的简写,表示文件或者目录的所有者
ggroup的简写,表示文件所属群组
oothers的简写,表示其他所有用户
aall的简写,是u、g、o的组合

如果没有指定字符,则假定使用all。操作符“+”表示添加一种权限,“-”表示删除一种权限,“=”表示只有指定的权限可用,其他所有的权限都被删除。
权限由字符“r”、“w”和“x”来指定。如下图

符号含义
u+x为文件所有者添加可执行权限
u-x删除文件所有者的可执行权限
+x为文件所有者、所属群组和其他所有用户添加可执行权限,等价于a+x
o-rw除了文件所有者和所属群组之外,删除其他所有用户的读写权限
go=rw除了文件所有者之外,设置所属群组和其他所有用户具有读写权限。如果所属群组和其他所有用户之前已经具有可执行权限,那么删除他们的可执行权限
u+x,go=rx为文件所有者添加可执行权限,同时设置所属群组和其他所有用户具有读权限和可执行权限。指定多种权限时,需用逗号分隔

2.2 umask设置默认权限

umask命令控制着创建文件时指定给文件的默认权限。它使用八进制表示法来表示从文件模式属性中删除一个位掩码。
在这里插入图片描述
首先,删除foo.txt文件存在的所有副本,以保证一切都是重新开始。下一步运行不带任何参数的umask命令,查看当前掩码值,得到的值是0022(0002是另一个常用的默认值),它是掩码的八进制表示形式。接着创建文件foo.txt的一个新实例,查看该文件的权限,可以发现,文件所有者获得读写权限,而组和其他所有用户则只获得读权限。组和其他所有用户没有写权限的原因在于掩码值。
在这里插入图片描述
在设置掩码为0000(实际上是关闭该功能)时,可以看到组和其他所有用户也拥有写权限了。为了理解它是如何实现的,再看看八进制数。
如果把该掩码展开成二进制形式,然后再与属性进行对比

名称形式
原始文件模式— rw- rw- rw-
掩码000 000 010 010
结果— rw- r-- r–

先忽略掉掩码中前面的0,观察掩码中出现1的地方,将会发现1的位置对应的属性被删除,这就是掩码的操作方式。掩码的二进制数值中每个出现1的位置,其对应的属性都被取消。

2.3 一些特殊权限

虽然通常看到的八进制权限掩码都是用三位数字表示的,但是,确切地说,从技术层面上来看,它是用四位数字来表示的。为什么呢?因为除了读取、写入和执行权限之外,还有一些其他的较少用到的权限设置。

2.3.1 setuid(八进制表示为4000)

当把它应用到一个可执行文件时,有效用户ID将从实际用户ID(实际运行该程序的用户)设置成该程序所有者的ID。大多数情况下,该权限设置通常应用于一些由超级用户所拥有的程序。当普通用户运行一个具有“setuid root”(已设置setuid位,由root用户所有)属性的程序时,该程序将以超级用户的权限来执行。这使得该程序可以访问一些普通用户通常禁止访问的文件和目录。很明显,这会带来安全方面的问题,因此允许设置setuid位的程序个数必须控制在绝对小的范围内。

2.3.2 setgid(八进制表示为2000)

类似于setuid位,它会把有效组ID从该用户的实际组ID更改为文件所有者的组ID。如果对一个目录设置setgid位,那么在该目录下新创建的文件将有该目录所在组所有,而不是由文件创建者所在组所有。当一个公共组下的成员需要访问共享目录下的所有文件时,设置setgid位将很有用,并不需要关注文件所有者所在的有效组。

2.3.3 sticky位(八进制表示为1000)

这是从传统UNIX中继承下来的,可以标记一个可执行文件为“不可交换的”。在Linux中,会忽略文件的sticky位,但是如果对一个目录设置sticky位,那么将能阻止用户删除或者重命名文件,除非用户是这个目录的所有者、文件所有者或者是超级用户。它常用来控制对共享目录(比如/tmp)的访问。

这里有一些使用chmod命令和符号表示法来设置这些特殊权限的实例。
首先,授予程序setuid权限:

chmod u+s 程序名

下一步,授予目录setgid权限:

chmod g+s 目录

最后,授予目录sticky权限:

chmod +t 目录 

使用ls命令可以查看这些特殊权限的设置结果。首先设置了setuid位的程序:

-rwsr-xr-x

具有setgid属性的目录:

drwxrwsr-x

设置了sticky位的目录:

drwxrwxrwt

3.更改身份

在很多时候,我们经常会需要变更身份来获取特权来执行管理任务,一般有三种方式:
1.注销系统并以其他用户的身份重新登录系统
2.使用su命令
3.使用sudo命令

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

su命令用来以另一个用户的身份来启动shell。该命令的一般形式如下:

su [-[l]] [user]

如果包含“-l”选项,那么得到的shell会话界面将是用于指定用户的登录shell(login shell)界面。这就意味着,该指定用户的运行环境将被加载,而且其工作目录也将更改为该指定用户的主目录。这样常常是我们想要得到的结果。如果没有指定用户,那么默认假定位超级用户。需要注意的是,-l可以缩写为-,而且这一形式经常被使用。
在这里插入图片描述
在输入su命令后,系统会提示输入超级用户的密码。如果密码正确,那么将会出现新的shell提示符,该提示符表示该shell将拥有超级用户的特权(提示符的末尾字符是#,而不是$),而且当前的工作目录现在也是用于超级用户的主目录(通常情况下为/root)。一旦进入了这个新的shell环境,我们就可以以超级用户的身份执行命令了。在使用结束时,输入exit,将返回到之前的shell环境。
我们也可以使用su命令执行单个命令,而不需要开启一个新的交互式命令界面

su -c 'command' [user] 
//user不写则默认为root用户环境

使用这种格式,单个命令行将被传递到一个新的shell环境下进行执行。这里需要用单引号把命令行引起来,这点很重要。因为该命令扩展并不希望在当前shell环境下执行,而是希望在新的shell环境下执行。

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

sudo命令在很多方面都类似于su命令,但是它另外还有一些重要的功能。管理者可以通过配置sudo命令,使系统以一种可控的方式,允许一个普通用户以一个不同的身份(通常是超级用户)执行命令。在特定情况下,用户可能被限制为只能执行一条或者几条特定的命令,而对其他命令没有执行权限。另一个重要的区别在于,使用sudo命令并不需要输入超级用户的密码。使用sudo命令时,用户只需要输入自己的密码来进行认证。比如说,配置sudo命令来允许普通用户运行一个虚构的备份程序(称为backup_script),这个程序需要超级用户的权限
在这里插入图片描述
在输入sudo命令后,系统将提示输入用户自己的密码(而不是超级用户密码),而且一旦认证通过,指定的命令就将被执行。su命令和sudo命令之间的一个重要的区别在于sudo命令并不需要启动一个新的shell环境,而且也不需要加载另一个用户的运行环境。这意味着,使用sudo命令的时候并不需要用单引号把命令引起来。需要注意的是,我们可以通过指定不同的选项来改变命令执行的效果。
要想知道sudo命令可以授予哪些权限,可以使用-l选项来查看。

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

chown命令用来更改文件或者目录的所有者和所属群组。使用这个命令需要超级用户的权限。chown命令的语法如下:

chown [ower][:[group]] file ...

chown命令更改的是文件所有者还是文件所属群组,或者对两者都更改,取决于该命令的第一个参数。

参数结果
bob把文件所有者从当前所有者更改为用户bob
bob:users把文件所有者从当前所有者更改为用户bob,并把文件所属群组更改为users组
:admins把文件所属群组更改为admins组,文件所有者不变
bob:吧文件所有者从当前所有者更改为用户bob,并把文件所属群组更改为用户bob登录系统是时所属的组

假设有两个用户,拥有超级用户权限的janet和没有该权限的tony。用户janet想要从她的主目录复制一个文件到用户tony的主目录中。因为用户janet希望tony能够编辑该文件,所以janet把该文件的所有者从janet更改为tony,具体操作如下
在这里插入图片描述
这里我们看到用户janet首先把文件从她的目录复制到用户tony的主目录中。接下来,janet把该文件的所有者从root(使用sudo命令的结果)更改为tony。通过在第一个参数末尾加上冒号,janet也把文件的所属群组更改成了tony登录系统是所属的组,该组名碰巧也叫tony。

3.4 chgrp:更改文件所属群组

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