在 Linux 中,文件权限分为所有者、群组、其他人三种身份。
- 所有者:指拥有该文件/目录的用户,默认是创建该文件/目录的用户。
- 群组:指该文件/目录所属的群组,默认是创建该文件/目录的用户所在主要群组。群组是多个用户的集合,通过给群组赋予权限,从而使群组中的用户都拥有相应的权限。
- 其他人:如果一个用户既不是文件/目录的所有者,也不属于文件/目录所属的群组,那么该用户就是其他人。
在下面的例子中,可以看到当前用户是 her-cat
,通过 ll 查看 /var/run/docker.sock
的文件属性。其中,第三列表示文件的所有者是 root
;第四列表示文件所属的群组是的 docker
;用户 her-cat
既不是所有者 root
,又不在 docker
群组中,所以用户 her-cat
的对该文件来说身份是其他人。
[her-cat@centos her-cat]$ ll /var/run/docker.sock
srw-rw---- 1 root docker 0 9月 10 22:51 /var/run/docker.sock
上面的第一列 srw-rw----
表示该文件的类型和权限,一共由 10 个字符组成。其中,第一个字符用来表示文件的类型,有以下几种类型:
d
:表示为目录。-
:表示为普通文件。l
:表示为链接文件。b
:表示为设备文件中可供储存的设备。c
:表示为设备文件中的序列埠设备,例如键盘、鼠标。s
:表示为套接字文件。p
:表示为用于管道通信的文件。
在上面的例子中,第一个字符是 s
, 所以该文件是一个套接字文件。
剩余 9 个字符 rw-rw----
用来表示文件的权限,将其拆分成三个字符为一组,一共三组,即 rw-
、rw-
、---
,分别表示所有者、群组、其他人的权限。其中,每一组中的 3 个字符分别表示可读(r)、可写(w)、可执行(x),当拥有某项权限时,就会在相应的位置展示该权限对应的占位符(r/w/x),否则就会用 -
表示没有该项权限。
第一组的 rw-
表示所有者的权限,第一个字符 r
和第二个字符用 w
表示所有者拥有可读和可写权限,第三个字符是 -
而不是 x
,表示所有者没有可执行权限。
第二组的 rw-
表示群组的权限,它与第一组相同,表示群组中的用户都拥有可读、可写权限,同样也没有可执行权限。
第三组的 ---
表示其他人的权限,与前两组不同,第三组的可读、可写、可执行都是 -
,这意味着其他人没有可读、可写、可执行权限,也就是说除了所有者和群组中的用户以外,其他人不能对该文件进行任何操作。
在前面有提到,当前登录的用户是 her-cat
,对应的是其他人的权限,所以我们不能对该文件执行任何操作,如果尝试读取该文件的内容,那么就会提示你没有权限读取该文件。
[her-cat@centos her-cat]$ cat /var/run/docker.sock
cat: /var/run/docker.sock: Permission denied
思考:为什么我们没有该文件的任何权限,却能看到这个文件呢?🤔
那么,作为当前用户要怎样才能拥有对该文件的操作权限呢?
我们可以从三种不同的身份下手,相应的就有以下四种方法。
- 第一种:修改文件的所有者。
我们可以使用 chown
命令来修改文件的所有者,当我们是文件的所有者时,我们也就拥有了所有者所拥有的权限(可读、可写)。该命令的用法如下:
chown = change owner
chown [-R] 用户名 文件或目录
-R 表示递归修改目录下所有文件及目录的所有者。
使用示例:
sudo chown her-cat /var/run/docker.sock
再次查看文件属性,可以看到所有者已经是 her-cat
了。
[her-cat@centos her-cat]$ ll /var/run/docker.sock
srw-rw---- 1 her-cat docker 0 9月 10 22:51 /var/run/docker.sock
当然,由于这种方法比较「邪恶」,相当于本来是别人的东西,你直接开了「金手指」给抢过来,所以非必要情况,不建议使用该方法。
- 第二种:修改文件所属的群组。
既然当前用户并不在该文件所属的群组 docker
中,那么我们将该文件所属的群组改成当前用户在的群组即可。
使用 groups
命令查看当前用户所属的群组。
[her-cat@centos her-cat]$ groups
her-cat adm wheel video
选择其中的一个为目标群组,例如 wheel
,然后使用命令修改文件所属的群组,可以修改文件所属群组的命令有以下两个。
第一个命令就是上面提到的 chown
,该命令除了可以修改文件的所有者以外,还可以用来修改文件所属的群组,用法如下:
chown [-R] :群组名 文件或目录
chown [-R] 用户名:群组名 文件或目录
两种用法并没有太大差异,只不过第二种可以同时修改所有者和群组。
使用示例:
sudo chown root:wheel /var/run/docker.sock
再次查看文件属性,可以看到所属群组已经是 wheel
了。
[her-cat@centos her-cat]$ ll /var/run/docker.sock
srw-rw---- 1 root wheel 0 9月 10 22:51 /var/run/docker.sock
第二个命令是专门用来修改群组的 chgrp
,用法如下:
chgrp [-R] 用户组 文件或目录
使用示例:
sudo chgrp wheel /var/run/docker.sock
当然,修改群组的这种方法与修改所有者有「异曲同工」的感觉,所以,同样也是非必要不建议使用。
- 第三种:修改其他人的权限。
前两种方法都有些太过于「粗暴」了,其操作的影响范围都很大,既然当前用户属于「其他人」,那我们只需要修改该文件对于「其他人」的权限即可。
我们可以使用 chmod
命令来修改文件的权限,该命令有两种符号和数字两种用法。
先来看第一种用法,使用符号来表示身份和权限,这种用法更适合我们人类进行阅读和理解,并且可操作性更强,它支持新增、修改、删除权限,下面我们来看一下如何使用。
在 chmod
命令中,分别使用 u、g、o 三个符号表示所有者、群组和其他人三种身份,还有一个特殊的 a
表示所有身份。我们可以对这些身份执行 +(新增)、-(删除)、=(修改)三个操作,相应的可读、可写和可执行权限就分别由 r、w 和 x 表示。
例如,我们现在要给所有者加上可执行权限,删除群组的可写权限,给其他人加上可读可写权限。
sudo chmod u+x,g-w,o+rw /var/run/docker.sock
查看文件属性:
[her-cat@centos her-cat]$ ll /var/run/docker.sock
srwxr--rw- 1 root docker 0 9月 10 22:51 /var/run/docker.sock
可以看到,所有者的权限由 rw-
变成了 rwx
,群组的权限由 rw-
变成了 r--
,其他人的权限由 ---
变成了 rw-
,说明权限按照我们的预期修改成功了。
如果想要给所有身份都加上可写权限,那么只需要像下面这样即可:
sudo chmod a+w /var/run/docker.sock
第二种用法则是使用数字来表示身份和权限。
在这种用法中,分别使用 4、2、1、0 来表示 r(可读)、 w(可写)、x(可执行)和 -(没有权限),将每个身份的权限对应的数字加起来,最后得到的三个数字就是权限值。
例如当权限为 rwxr--rw-
,所有者的权限 rwx
转换为数字是 421
,将三个数字相加得到数字 7
,那么 7
就表示所有者的权限;接下来是群组的权限 r--
,转换为数字是 400
,相加后为 4
;最后是其他人的权限 rw-
,转换为数字是 420
,相加后得到 6
;最后将每个身份的数字拼在一起就得到了权限值 746
。
所以,当我们使用 746
作为 chmod
的参数时,就可以将文件的权限设置为 rwxr--rw-
。
sudo chmod 746 /var/run/docker.sock
文件属性:
[her-cat@centos her-cat]$ ll /var/run/docker.sock
srwxr--rw- 1 root docker 0 9月 10 22:51 /var/run/docker.sock
如果想要给群组加上可写权限,可写权限 w
对应的数字是 2
,在原来 4
基础上加 2
就得到了群组修改后的权限对应的数值 6
,最后与所有者和其他人的数字拼在一起就得到了权限值 766
。执行 chmod
命令时使用该权限值就可以将群组的权限修改为 rw-
。
由于每个身份的权限的数字不会重复,所以我们可以快速的知道数字所表示的权限。例如 7 就是 4 + 2 + 1,表示拥有所有权限(可读、可写、可执行),6 就是 4 + 2,表示拥有读写权限,不可能会是 2 + 2 + 2 这样的组合,因为可写权限只能出现一次。
虽然修改其他人权限相比前两种方法更「友好」,但是该方法依然存在一些弊端。
第一,在一些情况下该方法的作用是临时的。例如上面举例使用的 /var/run/docker.sock
文件,当机器重启后该文件会被清理,再次启动 Docker,你会发现该文件依然是原来的权限。所以我们每次重启机器后,都必须重新进行授权。
第二,存在安全风险。当我们给该文件的其他人增加了读写权限后,那么就意味着系统中所有的其他用户(不是所有者并且不在所属群组中的用户)都拥有了对该文件的读写权限,而不仅仅是给当前用户。
- 第四种:加入文件所属的群组。
如果我们仅仅想让当前用户拥有权限,那么只需要将当前用户加入到文件所属的群组即可,这样就可以不修改文件本身的属性来达到获得权限的目的。
我们可以使用 usermod
命令将当前登录用户添加到 docker
群组中。
sudo usermod -aG docker her-cat
-G 表示将用户添加到指定的 docker 组中。 -a 表示在组中追加用户,而不是覆盖现有的用户。
查看当前用户所属的群组。
[her-cat@centos her-cat]$ groups
her-cat adm wheel video docker
可以看到已经添加成功了,但需要重新登录才能使其生效,如果在虚拟机中运行 Linux,则可能需要重新启动虚拟机才能使更改生效。
但是,我们也可以使用 newgrp
命令切换当前用户所属的群组,使其立即生效。用户可以同时属于多个群组,但在某一时刻只能以一个主群组的身份进行工作。
需要注意的是,
newgrp
命令只会在当前会话中起作用,一旦退出当前会话,将恢复到在系统中定义的默认主群组。
newgrp docker
这时读取 /var/run/docker.sock
文件就不会提示无权限了。
以上就是文件权限相关的内容,接着来看下前面提到的问题:为什么我们没有该文件的任何权限,却能看到这个文件呢?
这是因为能否看到某个目录下的文件,与文件本身的权限无关,而是与文件所在的目录的权限有关。
目录权限与文件权限都是使用 r/w/x 进行表示,但是它们代表的含义不一样,下面是目录权限的 r/w/x 所代表的含义。
- r:表示拥有读取该目录下的文件列表的权限。
- w:表示拥有创建、删除、移动、重命名该目录下的文件的权限。
- x:表示拥有进入目录作为工作目录的权限。
工作目录就是指当前所在的目录,使用
cd
命令进入某个目录的时候,就是将该目录作为工作目录。
从上面可以看出文件权限与目录权限的区别,文件权限针对的是对于文件内容的操作,而目录权限则针对的是文件本身,比如对移动文件、重命名文件等等,这些都是不会涉及文件内容的操作。
注意:本文中使用 /var/run/docker.sock 文件作为为例子,讲述了 Linux 文件权限相关概念及操作。建议在实际中不要使用该文件练习本文中的操作,以免出现问题。