文章目录
关于权限
在谈 Linux 中权限的概念之前,先简单粗略地理解一下广泛的权限是什么。
首先,权限是指为了保证职责的有效履行,任职者必须具备的,对某事项进行决策的范围和程度。而现实生活中,法律是最基本的规定每个公民的权限的。
那么,对于权限的管理就有两部分,一是人,而是某事项或某事物。规定某个人对某事项或某事物具有什么什么的执行权力,这就是权限管理。
而在 Linux 中,权限管理同样是两部分,用户和文件(夹)。
Linux 中的权限管理就是让用户对某个文件(夹)具有执行或不能执行某操作的行为。
而一个文件(夹)具有被读、被写和被执行的属性,
所以用户能对文件(夹)进行的操作也无非就是读、写、执行。
那用户有普通用户和超级用户 root ,他们对某个属于或不属于他们的文件呢?
我怎么知道我对某个文件能执行什么操作呢?
Linux 下又是怎么管理和表示这种权限的呢?
下面一一进行解读。
我是谁
对于一个文件,无论我是普通用户还是超级用户 root,都有一个这个文件属不属于我的问题。
Linux 是怎么区分文件所属的呢?
这里着重关注两列。
第一列代表的是文件(夹)的所属者(u - User),
第二列代表的是该文件(夹)的所属组(g - Group),
这里我用的是 lch 用户,很显然前四个文件都是属于我的,所以我既是它们的所属者,也是他们的所属组。
而最后一个文件的所属者和所属组是 root ,
那么我对这个文件(夹)来说就是其他人(o - Other)。
这是第一个需要明确的问题。
我能对某个文件(夹)进行什么操作
首先对普通文件的读写执行很好理解,就是字面意思的读写执行。
如果是目录文件呢,对目录文件进行写入或删除,访问目录文件,这又是对应什么权限呢?
下面一一进行探讨。
普通文件的事物属性
对于一个文件(夹),他能被读、被写和被执行,
这是它作为文件(夹)的事物属性。
这些操作在 Linux 下对应的表示分别为 r/w/x。
这里重点关注标注的三列。
它们三三为一组,顺序依次为读(r)写(w)执行(x)。
其中 - 代表的是没有对应的操作权限。
第一列对应的是文件**所属者(u - User)**的操作权限,
第二列对应的是文件**所属组(g - Group)**的操作权限,
第三列对应的是**其他人(o - Other)**的操作权限。
以 a.out 文件为例,它的所属者和所属组都是 root ,
所以我当前对它来说就是其他人的身份,
此时三个操作对应的权限都是 “—” ,
所以当前用户 lch 对该文件并没有执行权限,
虽然它是一个可执行文件:
上面我是以普通用户的身份,还受到权限的制约,
如果我是超级用户 root 呢?
此时 a.out 的所属者和所属组都成了普通用户 lch,
那么 root 就成了 Other,而 Other 的读写执行权限都没有,
而 root 却仍能执行。
所以直接抛出结论,超级用户root不受权限的制约,权限是用来制约普通用户的。
目录文件的事物属性
下面解释一下目录文件的权限。
类似于Windows,
Linux 下也有各种各样类型的文件,
简单的比如目录文件、文本文件、源文件、可执行文件…
像文本文件的权限很好理解,
一般只有可读和可写,可执行可以有但没意义。
可执行文件的权限也好理解,执行就是了。
那目录文件的权限有什么作用呢?
以下面的homework目录为例:
此时我是该目录的所属者,并且拥有可读可写可执行的权限。
那对目录的可读可写可执行分别代表着什么呢?
此时对该目录的所有操作都是OK的:
ls 可以读到该目录下的文件,
touch 也可以向该目录中写入文件(没有报错),
cd 也可以访问到该目录中。
如果咔掉读权限呢:
此时 ls 已经 permission denied 了,但 touch 和 cd 都还能正常执行。
如果咔掉写权限呢:
此时 ll 还可以正常访问,cd 也可以正常进入,
而 touch 则不能在该目录下创建文件,rm 也不能在该目录下删除文件。
如果咔掉执行权限呢:
发现此时好多操作都做不了了。
ll 只看到了文件名,但其他信息都看不到;
虽然可写,但 touch 并不能在外面向里写文件;
cd 也进不去了。
实际上,在 Windows 下我们用鼠标双击可执行程序就是运行它,对一个文件夹双击就是进入,所以进入文件夹何尝不是执行目录文件。
而在 ll 和 touch 的过程中,要访问到目录才能进行读写操作,而访问目录就是相当于执行,自然而然就 Permission denied 了。
其实上面还有一个隐藏的问题,就是在目录下面,只要我有权限,就可以对目录下的任意文件进行删除,而不管我有没有对应文件的任何权限。
又或者说,现在有一个对所有人完全公开的目录,大家都在这个目录下写文件,既然这个目录文件的所有权限都是公开的,那么所有人都可以对这个目录文件进行读写删除等操作。经过上面分析知道只要我有对这个目录的 w 和 x 权限,我就可以删除这个目录下的文件,不管我对这个文件有没有对应操作权限。那这不就乱套了吗。
这实际上是不太合理的,假如我辛辛苦苦写了一个代码,结果被别人删掉了,找谁说理去。
我们想要的是大家可以在目录下一起写文件,而不能随意删除别人的文件,为了解决这个问题,Linux 引入了粘滞位的概念。
粘滞位其实就是修改目录文件的 **x权限 **为 t权限:chmod o+t [filename]
此时就是下面这样:
此时我(也就是 Other)的执行权限变成了 t ,而且可读可写。
那么自然而然地我就可以在目录下面创建我自己的文件:
但此时我如果再想删除其他人的文件:
就不被允许了。
所以稍微总结一下粘滞位,就是让目录文件变得可读写,但不完全可读写。
而且给目录设置粘滞位一般是用来限制目录的Other的,这样一来只有目录的所有者或者是root才有随意删除的权限了。
实际上,我们的系统中就有一个设有粘滞位的目录
/tmp
:因为一个系统可能有很多人一起使用,而使用过程中难免会有很多临时文件,这些临时文件都可以存放到根目录下的一个 tmp 目录中,但是自己的文件存在的同时也有别人的文件,而为了限制用户对其他人的文件进行非法操作,也就有了粘滞位。
对目录的权限进行总结一下,如果目录没有 x 权限,则无法对目录执行任何命令,虽然可以读到目录中的文件,但这也是很矛盾的一种妥协。在有 x 权限的前提下,可以 cd 访问到目录,那么只要有读写权限就可以对目录进行相应的操作了。
怎么管理文件(夹)的权限
管理文件(夹)的权限有两个对象可以操作,
一是管理文件(夹)本身的事物属性,
就是对所有者、所属组、其他人所允许和禁止的操作;
二是管理文件夹的(所属)关系,
就是改变文件的所属人或所属组。
修改文件(夹)的事物属性
其中文件(夹)的事物属性可以通过 chmod 指令修改。
例如想要对所属者修改权限,可以输入指令chmod u±rwx
。
其中 u 就是 User,就是文件所属者的意思,
**+和-**分别代表添加或删除某项操作权限,
r/w/x 分别代表读/写/执行三种权限。
想要管理所属组的权限,可以输入指令chmod g±rwx
;
想要管理其他人的权限,可以输入指令chmod o±rwx
;
如果想一次性管理所有人的权限,则可以输入指令chmod a±rwx
。
当然也可以用chmod u±rwx,g±rwx,o±rwx
避免重复输入指令。
上面只是说了怎么修改文件(夹)的事物属性,但没有说谁能修改。
实际上,只有文件的拥有者和root才可以改变文件的权限。
还有一点就是,如果我不仅想改变某个目录的事物属性,我还想改变目录下所有文件(包括该目录下的目录…)的事物属性,此时可以加上 -R 选项进行递归修改。
但这么做有前提。
如果我是普通用户,那么我一定要是该目录下所有文件的所有者,否则只能通过 sudo 选项进行短暂的权限提升;
而如果我是超级用户root,那就没有这个烦恼了。
修改文件的所属关系
现在我会改文件对各种人开放的权限了,那我如果想改变文件的所属者或者所属组呢?
修改所属者用到的指令是 chown [username] [filename]
,
修改所属组用到的指令是chgrp [groupname] [filename]
,
当然,如果想一次性同时修改文件的所属者和所属组则还有这样的用法:
chown [username:groupname] [filename]
。
上述指令都还有 -R 选项,意为递归调用。
但问题来了,我可以随意把我写的文件转给别人吗?
就好比我有一个定时炸弹,就直接随便扔给别人?
所以想要修改文件的所属关系也不是随便能修改的,
也是要经过别人同意的。
而如果真像转,可以切成 root 身份来操作或使用 sudo 命令。
文件(夹)权限的其他表示方式
前面已经提到了,文件(夹)对用户开放三种权限,
分别是读®、写(w)、执行(x)。
将这三种权限顺序固定,有对应权限为1,无对应权限为0,
那么就可以用三个二进制数,或一个八进制数来表示一种用户的权限了。
例如一个文件的权限为
rwx/r-x/r--
,转成二进制就是
111/101/100
,对应的八进制表示就是
7/5/4
。那么该文件对应的权限是不是还可以表示成754呢?
看一个简单的例子:
所以如上面所讲的,八进制也可以表示文件权限,此外还有其他形式,这里就不细讲了。
同时,我们也看到,chmod 也支持用八进制的形式来修改文件权限。
文件(夹)的默认权限和权限掩码
不知道大家有没有思考过一个问题,
为什么我创建的文件(夹)初始权限都是一样的:
实际上,Linux 下的新建文件的默认权限为666,新建目录的默认权限为777,这个在最后会进行验证。
但上面新建文件的权限默认权限转换为八进制却是664,
新建目录的默认权限转换为八进制是775,
这又是因为什么呢?
这就要提到另一个概念——权限掩码。
权限掩码权限掩码,就是给权限打掩护的,那它是怎么掩护的呢?
首先我们可以通过 umask
指令查看一下当前的权限掩码:
此时作为普通用户,我的默认权限掩码是0002。
解释一下。
这里 0002 中的第一个数字在这里可以理解为表示这是一个八进制数,就好比十六进制数是以 0x 开头的。
其余三个数字则是分别对应 User/Group/Other 。
前面说了,文件的初始权限是 666 ,上面文件的实际权限是 664;
文件夹的初始权限是 777 ,上面文件夹的实际权限是 775,
如果不考虑进位,三个位分开来算,权限掩码比初始权限对应的值要大时,实际权限就是0,权限掩码比初始权限对应的值要小时,实际权限就是二者之差。
如果以二进制数表示呢?
默认权限掩码的二进制表示为 000/000/010 ;
文件的默认权限二进制表示为 110/110/110 ,实际权限为 110/110/100 ;
目录的默认权限二进制表示为 111/111/111,实际权限为 111/111/101 。
同样,如果不考虑进位,我们仍可以像上面那样做,但二进制还有丰富的位运算,所以还有一种更简洁明了的运算方式:实际权限 = 默认权限 ^ 权限掩码。这里就不给验证了。
普通用户的默认权限掩码是 0002,而 root 用户的默认权限掩码是 0022 。
实际上,权限掩码也是可以修改的:umask 0xxx
:
但值得注意的是,这样修改权限掩码在下次重新进入系统时就失效了,如果想永久修改,则需要一些特殊手段了,当然这里不提供也不建议这种刺激的玩法。
至于此前提到的默认权限 666 和 777 ,我们就可以通过将权限掩码归零来验证一下: