转:https://blog.csdn.net/pi9nc/article/details/14139465
本篇文章讨论的是Linux/Unix的权限问题,包括文件的访问权限、可执行文件的权限以及修改这些权限的命令chmod。
Linux权限模式介绍
用ls -l命令列出文件的详细信息,关于ls -l参见这里。
1 2 3 4 5 6 | $ ll # alias ll='ls -lh' total 20K -rwxr-xr-x 1 dutor dutor 7.1K 2010-08-08 12:45 a.out -rw-r--r-- 1 dutor dutor 540 2010-08-08 12:29 main.c -rw-r--r-- 1 dutor dutor 472 2010-07-17 23:18 main.cpp -rw-r--r-- 1 dutor dutor 53 2010-04-26 12:24 Makefile |
ls -l输出内容包括七个域,其中第一个域包括10个字符。第一个字符指明了文件类型,可能是以下字符:
- -: 普通文件;
- d: directory,目录文件;
- l: link,符号链接;
- s: socket文件;
- b: block,块设备;
- c: charactor,字符设备;
- p: FIFO pipe,管道文件。
接下来的9个字符指明了文件的访问权限:每三位指明一类用户的权限,分别是文件属主(user)、同组用户(group)、其它用户(other),权限分为读(r)、写(w)、执行(x),相应位若为-,表示此类用户不具有相应权限。
另外,x对应的位置(执行位)还可能是其它字符。比如,user或group的执行位若为s,表示该文件的set-user-id或者set-group-id(这两种id下文会着重介绍)和执行权限x被同时置位;若为S,则表示set-user-id或set-group-id被置位,而执行权限x不被置位。other的执行为如果为t,表示该文件的粘滞位(sticky bit)和x均被置位;若为T,则表示只有粘滞位被置位。粘滞位如果被置位,而且该文件为可执行文件,则当文件被执行时,其文本段(.text段,即代码段)会被加载到swap中,程序结束时仍然保留在swap,当下次执行该文件时,将直接从swap中加载,由于swap在磁盘中为连续的block,因此加载速度会提高。另外,如果目录文件的粘滞位被置位,也具有特殊含义,此处从略 。
需要特别说明的是目录的权限。Linux/Unix中,目录是一种“特殊”的文件,这个文件包括该目录下所有文件(包括子目录)的文件名和索引节点,i-node号。读一个目录是指列出该目录下所有的文件和子目录,如ls。写一个目录是指增加、删除或者重命名该目录下的文件或目录,如rm,mv等,值得一提的是,你可能无法读写和执行一个文件,但却可能删除这个文件,只要你对其所在目录具有写权限。一个目录的执行权限是指,该目录可以是一个(搜索)路径的一部分,即你必须对你要访问的文件的路径中的任何一个目录都具有执行权限,形象地你可以把目录的执行权限当作是过境的绿卡。
chmod命令介绍
下面介绍如何使用chmod命令来设定和修改文件的权限位。
首先,chmod命令本身的执行也有限制,普通用户只能修改自己的文件的权限位,超级用户可以使用chmod修改任意用户任意文件的权限。使用chmod的方法为chmod [option] mode file. 常用的选项就是-R,用来对整个目录及其子目录中的文件进行模式(权限)修改。mode可以由两种方式指定,一种是由字母表达式表示的相对修改方式,一种是以4位8进制表示的绝对方式。
第一种方式:chmod [ugoa][+-=][rwxst] file. u指代user,g指代group,o指代other,a指代all。+-=分别执行指代增加、减少、设定相应权限(由后面的参数指定)。rwxst分别指代读、写、执行、set-user-id/set-group-id、sticky-bit粘滞位。整体上理解,就是对哪类用户(ugoa,为a时可省略)执行哪些权限(rwxst)的什么修改(+-=)。示例:
1 2 3 4 5 6 7 8 9 10 11 12 | $ chmod u-x a.out $ ll a.out -rw-r-xr-x 1 dutor dutor 7.1K 2010-08-08 13:33 a.out $ chmod +t a.out $ ll a.out -rw-r-xr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out $ chmod g=rs a.out $ ll a.out -rw-r-Sr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out $ chmod a+x a.out $ ll a.out -rwxr-sr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out |
第二种方式:chmod xxxx file. 其中x为一个八进制的数字,即0~7,由三个代表权限权值的数字相加或者按位或形成。各权限位的权值分别为:r:4, w:2, x:1; set-user-id:4, set-group-id:2, t:1. 其中,set-user-id, set-group-id和t组成第一个8进制数,其它三个八进制数分别代表user、group和other的权限,由rwx组成。另外,你可以指定少于4个的8进制数字,这样,前面未指定的数字就为0。示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $ ll a.out -rwxr-xr-x 1 dutor dutor 7.1K 2010-08-08 13:54 a.out $ chmod 0755 a.out $ ll a.out -rwxr-xr-x 1 dutor dutor 7.1K 2010-08-08 13:54 a.out $ chmod 0777 a.out $ ll a.out -rwxrwxrwx 1 dutor dutor 7.1K 2010-08-08 13:54 a.out $ chmod 1700 a.out $ ll a.out -rwx-----T 1 dutor dutor 7.1K 2010-08-08 13:54 a.out $ chmod 6760 a.out $ ll a.out -rwsrwS--- 1 dutor dutor 7.1K 2010-08-08 13:54 a.out |
user-id和group-id
一个用户,有两个id:user-id和group-id。user-id对于一个用户唯一的,但一个用户可以隶属于多个不同的group,但默认的组只有一个,这里的默认是指这个用户创建的文件默认隶属的组。这里说的group-id即为默认组id。
相对于下面要介绍的effective-user-id和effective-group-id,上面的user-id和group-id确切地说是real-user-id和real-group-id。这两个id被保存在/etc/passwd文件中,创建用户时被写入,每当用户登录时由登录程序来读取该文件,并设定相应用户的id,OS以用户的用户id和组来判断你是否具有相应的权限来执行特定的操作。
effective-user-id和effective-group-id,是针对可执行文件来说的,通常一个被执行的程序(进程)的effective-user-id和effective-group-id与real-user-id和real-group-id是相同的,都等于执行该程序的用户的user-id和group-id,不管该程序文件本身属于哪个用户。但当该程序文件的set-user-id或者set-group-id被置位时,该程序进程的effective-user-id或effective-group-id就是该程序文件属主的user-id或group-id,而不是该进程的real-user-id或real-group-id。
那么,effective-user-id和effective-group-id有什么作用呢?
在一个进程试图去访问一种资源时,比如读、写某个文件,OS(内核)会判断此进程对该文件是否具有相应的权限,判断的依据就是上面介绍的文件的权限访问位。那么,OS是拿进程的real*id,即执行该程序的用户的id来判断呢,还是拿进程的可执行文件的属主的id来判断呢?答案是,拿进程的effective-user-id和effective-group-id来判断,而effective-user-id和effective-group-id与set-user-id和set-group-id有关。这样,问题就明了了。
举例来说,/etc/passwd文件保存了系统中用户的基本信息(早期的Unix中,甚至直接将用户密码保存在该文件中),它的属主是root用户,普通用户对该文件只有读权限。但系统又需要允许用户修改自己的信息,这样就提供了相应的命令,例如passwd命令。这个命令的可执行文件的属主为root用户,为了普通用户也能够通过passwd命令修改密码,这个命令的set-user-id就被置位了。而普通用户的身份认证就转移到了passwd程序内部了,例如不允许普通用户修改其它用户的密码。上面所说的你可以自己验证:
1 2 | $ ll `which passwd` -rwsr-xr-x 1 root root 37K 2010-01-27 01:09 /usr/bin/passwd # set-user-id被置位 |
注意,由于现在用户密码已经不再直接保存在/etc/passwd中了,因此passwd命令可能不再修改该文件,而该文件肯定也是不允许root之外的用户(准确说是不具有超级权限的用户)修改的。事实上,真正保存密码的文件是/etc/shadow,而这个文件的权限位为0640。