权限这种东西太重要的,在系统地学习 linux 的过程中,发现文件和目录的权限虽然很基础,但是却有很多东西要记住,赶紧拿起我粉红色的小笔笔记起来。

# 权限与符号

我们都知道,一个文件大概有三种权限:

  • 读(read):一个用户能够读取当前文件的内容
  • 写(write):一个用户能够对当前文件写入新的内容
  • 执行(execute):一个用户能够执行当前的文件

linux 不像是 windows 会可以执行的文件用一个文件后缀名(.exe)标出来,一个文件能不能被执行,应该查看它是否拥有被执行的权限。

这三种权限在系统里面分别有着自己的符号和数字代号:

权限名称 英文单词 符号 数字代号
read r 4
write w 2
执行 execute x 1

数字代号用来干什么的呢?待会儿我们就知道了。

关键是数字代号怎么去记忆,我觉得只要记住了 r 是 4 就 ok了,因为 read 这个单词有四个字母。其余的两个就死记硬背吧?

# 查看文件权限

我们可以使用 ls -l 指令来查看当前目录下的文件列表及其权限,例如下图是查询了 /etc 目录下的文件列表及其权限:

etc部分目录

在最前面的部分我们看到形如 drwxr-xr-x 的字符串就是在说明这个文件的权限

其中 第一个字符 代表的是 文件目录类型

  • d 代表的是目录
  • - 代表的是文件
  • l 代表的是链接文件(link file)

而接下来的 9个字符 是三个三个一组的,拿 drwxr-xr-x 来举例:

  • 第一组 rwx 代表的是 文件拥有者 对于这个文件拥有的权限:读、写、执行
  • 第二组 r-x 代表的是某个 用户组内的用户 对于这个这个文件拥有的权限:读、执行
  • 第三组 r-x 代表的是 除了上面两者的其他人 对于这个文件拥有的权限:读、执行

不难理解,当一个用户对于这个文件不拥有某个权限时,会用 - 符号来代替。

还可以用 ll 命令来代替 ls -lll 是这小串指令的别名。

用户与用户组的概念在这里不作扩展

# 修改文件权限

chgrp (change group) 指令可以修改文件所属的用户组。

# 修改 /tmp/test1 的用户组为 root
chgrp root /tmp/test1

我们可以使用 chown (chang owner) 指令来修改文件的拥有者。

# 修改 /tmp/test1 的用户为 tricky
chown tricky /tmp/test1

# 同时修改拥有者为 tricky 和用户组为 root
chown tricky:root /tmp/test1

最重要的修改文件权限的指令是 chmod change mode

# 为 /tmp/test1 这个文件所属的用户组添加读和写的权限
chmod g+rw /tmp/test1

# 为 /tmp/test1 这个文件的所有者添加读和写的权限
chmod u+rw /tmp/test1

# 为 /tmp/test1 这个文件的其他访问者抹除读和写的权限
chmod o-rw /tmp/test1

# 一次性为所有用户(拥有者、用户组、其他人)添加读和写的权限
chmod a+rw /tmp/test1

从上面的命令中,不难总结出那个 加号和减号及其后面的权限符号 的作用就是添加或抹除相关权限。

augo 分别代表的是:

符号 英文 中文
a all 所有人
u user 拥有者
g group 用户组
o other 其他人(注意不是 owner!)

我们甚至可以显式地指定这些权限:

# 让拥有者拥有所有权限,让用户组和其他人拥有读写权限
chmod u=rwx go=rw /tmp/test1

还记得我们前文提及的权限代号吗?其实像 124 这串数字经常在各种编程规范或者常量里面出现。因为这三个数字互相求和的结果互不重叠,所以我们可以利用这三个数字的和来代表权限情况。

加法算式 结果 权限
1 1 --x
2 2 --w
1+2 3 -wx
4 4 r--
4+1 5 r-x
4+2 6 rw-
4+2+1 7 rwx

为什么没有 5+1 的算式?(啪啪)因为都说了,三个基本权限的数字代号里面有5吗?

那么,chmod 指令本身还可以这样用

# 为所有用户(拥有者、用户组、其他人)赋予读、写和执行的权限
chmod 777 /tmp/test1

三个数字自左往右分别代表 拥有者权限、用户组权限、其他人权限

# 只有拥有者有读写执行权限
chmod 700 /tmp/test1
# 所有用户都有读写执行权限,而其他人没有执行权限
chmod 775 /tmp/test1

# 目录的执行权限??

目录的 读取权限 意味着我们可以读取该目录底下的文件列表;写入权限 意味着我们可以在这个目录下:

  • 新建文件/目录
  • 删除文件/目录
  • 重命名文件/目录
  • 移动文件/目录

那么 执行权限 又是什么???

真是令人费解,我经常在书上看到,当你拥有目录的执行权限时,意味着你可以通过 cd 命令进入到该目录底下。

但是,让我抓狂的是,假设一个目录的权限是 drw-rw-rw-,这个目录拥有读取权限, 不拥有执行权限。

不能进入该目录的话,我还怎么去查看这个目录底下的文件列表??要这个写入的权限还有什么意义?

后来,我才发现我们可以使用 ls -l /tmp/somefolder 来查看一个目录的文件列表。

# 使用非root用户做个实验
# 先切换到 root 用户
su -
cd /tmp
mkdir test
chmod 776 test
# 在 test 目录里创建几个空文件
cd test
touch file1
touch file2
touch file3
# 回到非 root 的环境中
exit

cd /tmp
ls -dl test
cd test
ls -l test

实验结果

从上图的实验结果看来,如果我们对一个目录不拥有执行权限,确实是可以在不进入目录的情况下得知它的文件列表的。

所以有时候在进行文件复制(cp命令)时,如果想要让文件的权限设置不发生任何变动,应该使用 cp -a 进行复制。

# 用户文件默认创建权限

当我们使用 touch 创建空文件或 mkdir 创建空文件夹时,他们的默认权限又会是什么呢?

linux 有一个默认权限的规则:

  • 创建一个 文件 的默认规则应该是 -rw-rw-rw-,即没有执行权限
  • 创建一个 目录 的默认规则是 drwxrwxrwx

本文中称这套规则为 巴拉巴拉默认权限规则

而 linux 里面还有另一个概念,umask(user file creation mask,用户文件权限掩码)

在我的 centos 7 里面执行 umask,可以得到这样的结果:

umask

四个数字,其中第一位是特殊权限,太复杂了我们先不管,后面三位数字从左往右代表的依然是:拥有者、用户组、其他人。

而数字本身又和我们前文所说的权限数字代号一样。

上图中 0002 代表的是,要抹除掉 其他人的写权限 。 如果是 0047 那代表的就是,要抹除掉 用户组的读权限其他人的读、写和执行权限

这个 umask 的作用就是计算出一个用户创建空文件、目录时的权限会是怎样的,具体的规则就是由 巴拉巴拉默认权限规则 按照 umask 的定义抹除掉相关权限。

根据这个规则,假设 umask 是 0002, 我们创建的文件和目录的默认权限分别是:-rw-rw-r--drwxrwxr-x

注意,巴拉巴拉默认权限规则中文件的默认权限如果用数字写起来是 666,我们并不能简单的用 666-002=664 的方法来计算实际的默认权限。

举个合适的例子,假设 umask 是 003,那么意味着要拿掉用户的写和执行的权限,666-003=663,变成了其他人拥有写和执行的权限,这样是完全不对的!

我们也可以通过以下指令来修改这个用户文件权限掩码:

umask 0007

# 特殊权限

在上一个小节忽略掉的那个特殊权限,一共有三种:

权限名称 英文单词 符号 数字代号 情况
SUID set uid s 4 只能应用于文件
SGID set groupid s 2 可应用于文件、文件夹
SBIT sticky bit t 1 只能应用于文件夹

这三种权限会出现在 ls -l 的结果里,比如说 /tmp 目录的权限是 drwxrwxrwt。这其中的最后一个t原本应该是x,但是在这里,他代表的是一种特殊权限 SBIT

就拿 /tmp 目录来讲,拥有 SBIT 权限的目录, 如果一个用户对该目录具有 执行 的权限,那么这个用户在这个目录里面创建的文件或目录 只有他本人或root用户 才能删除。

如果我们想让一个目录拥有这个特殊权限,我们可以这样做:

chmod o+t /somefolder

关于 SUIDSGID 权限由于实际生活中对于我实在很少接触到,在学习的过程中就只能做一下简单的记录

SUID 只能设置在 二进制程序 身上,权限看起来像是这个样子:-rwsr-xr-x

程序的执行者 在执行这个二进制程序的过程中,会临时拥有这个程序的 拥有者 的所有权限。

例如所有的账号密码都是存放在 /etc/shadow 文件里面,这个文件只有 root 用户能修改,但是非 root 用户可以通过二进制程序 passwd 来修改账号密码,这个 passwd 的拥有者也是 root,意味着用户一旦执行了 passwd 就可以临时拥有修改 /etc/shadow 的权限了。

SGIDSUID 其实非常类似,SUID 是临时取得程序拥有者的权限,而 SGID 则是临时取得程序所在用户组的权限。

拥有 SGID 的文件、目录的权限看起来像这样:-rwx--s--x

只不过 SGID 还可以设置在目录身上,当一个用户进入到拥有 SGID 权限的 目录A 并在其中创建文件、目录时,这些文件、目录的用户组会自动设置成 目录A 的用户组本身。

# 总结

  1. 要记住各个权限及其数字代号的对应规则
  2. 目录权限 rx 并不冲突
  3. 用户创建的文件、目录的默认权限是根据 默认规则umask 计算出来的
  4. 为什么在某个共享文件夹下,同一个用户组下,用户组拥有rwx的权限可是我却删不掉其他用户上传的东西,大多数情况是因为 SBIT 这个特殊权限。