本文讲述的是文件或目录的属性及权限,比如索引节点inode、文件类型、文件权限及属主;还对setuid、setgid及粘贴位进行了相关的讲解。其中,对ln、chmod、chown、chgrp、umask等命令的用法也进行了比较详细的说明和举例
Linux中的文件
文件属性概述
Linux系统中文件或目录的属性主要包括:文件或目录的索引节点(inode)、类型、权限属性、链接数、所归属的用户和用户组、最近修改时间等内容;
看一下执行ls -lhi命令的结果:
文字解释:
第一列:inode索引节点
第二列:文件类型及权限
第三列:硬链接个数
第四列:文件或目录所属的用户(属主)
第五列:文件或目录所属的用户所归属的组;
第六列:文件或目录的大小;
第七列、八、九列:文件或目录的修改时间
第十列:实际的文件名或目录名
文件属性举例说明
[root@localhost oldboy]# ls -lhi oldboy 810407 -rw-r--r-- 1 root root 12 May 1 05:05 oldboy
详细描述:
Inode索引节点编号:810407 文件类型:文件类型是-,表示这是一个普通文件; 文件权限:文件权限是rw-r--r--,表示文件属主可读可写;文件所属的用户组可读;其他用户可读; 硬链接个数:表示oldboy这个文件没有其他的硬链接;因为链接数是1,就是他本身; 文件属主:这个文件所属的用户,这里意思是oldboy文件被root拥有,是第一个root; 文件属组:这个文件所属的用户组,在这里是root用户组,是第二个root; 文件大小:文件大小是12个字节; 文件修改时间:这里的时间是该文件的最后被更新(包括文件创建、内容更新、文件名更新等),可用如下命令查看文件的修改,访问,创建的时间;
例子:
[root@localhost oldboy]# stat oldboy File: `oldboy' Size: 12 Blocks: 16 IO Block: 4096 regular file Device: 802h/2050d Inode: 810407 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2015-05-01 05:05:29.000000000 -0400 Modify: 2015-05-01 05:05:03.000000000 -0400 Change: 2015-05-01 05:05:03.000000000 -0400 提示:这个stat命令可以看到文件的很多信息,很好用。
索引节点inode
inode中文意思是索引节点,每个存储设备或存储设备的分区(存储设备可以是硬盘、U盘....)被格式化为文件系统后,都应该有两部分:一部分是inode,另一部分是Block。Block是用来存储数据用的。而inode就是用来存储这些数据信息的,这些信息包括文件大小、属主、归属的用户组、读写权限。
inode为每个文件进行信息索引,所以就有了inode的数值。操作系统根据指令,能通过inode值最快的找到相对应的文件。
打个比方,比如一本书,存储设备或分区就相当于这本书,Block相当于书中的每一页,inode就相当于这本书前面的目录,一本书有很多内容,如果想查找某部分的内容,可以先查目录,通过目录更快的找到我们想要看的内容。虽然不太恰当,但还是比较形象的。
当用ls查看某个目录或文件时,如果加上-i参数,就可以看到inode节点了;比如:
[root@localhost oldboy]# chmod 755 oldboy [root@localhost oldboy]# ls -li oldboy 818104070407 -rwxr-xr-x 1 root root 12 May 1 05:05 oldboy
第一列inode值是810407;查看一个文件或目录的inode,通过ls命令的-i参数即可。
inode值相同的文件是硬链接文件
在linux文件系统中,inode值相同的文件是硬链接文件。这也就是说,不同的文件名,inode的值可能是相同的,一个inode值可以对于多个文件。在Linux中,链接文件是通过ln命令来创建的。
硬链接的原理及示例
用ln创建文件硬链接的语法:
#ln 源文件 目标文件 #注意:目标文件不需要提前创建
下面举一个例子,在这个例子中,为oldboy创建其硬链接oldboy_hard_link,然后看一下oldboy和oldboy_hard_link的属性的变化;
[root@localhost oldboy]# echo 'I am oldboy'>>oldboy [root@localhost oldboy]# chmod 755 oldboy [root@localhost oldboy]# ls -li oldboy #查看你oldboy文件的inode情况 810403 -rwxr-xr-x 1 root root 12 May 1 07:42 oldboy [root@localhost oldboy]# ln oldboy oldboy_hard_link #通过ln来创建oldboy的硬链接文件 [root@localhost oldboy]# ls -li oldboy* #列下创建前后文件inode及链接数的情况 810403 -rwxr-xr-x 2 root root 12 May 1 07:42 oldboy 810403 -rwxr-xr-x 2 root root 12 May 1 07:42 oldboy_hard_link
可以看到oldboy在没有创建硬链接文件oldboy_hard_link的时候,其链接个数是1,创建了硬链接oldboy_hard_link后,这个值就变为2,也就是说,我们每次为oldboy创建一个新的硬链接文件后,其硬链接个数都会增加1.
inode值相同的文件,可以把他们的关系看作互为硬链接的关系。当我们修改其中一个文件的内容时,互为硬链接的文件的内容也会跟着变化。如果我们删除互为硬链接关系的某个文件时,另外的硬链接并不受影响,既文件数据还在(当文件硬链接个数为0时,数据占用空间才会被释放回收)。如我们把oldboy文件删除后,我们还是一样能看到oldboy_hard_link的内容,并且oldboy_hard_link仍是存在的。
可以这样理解,互为硬链接关系的文件,具有相同的inode值,也就是说,对应的实际数据是同一份;下面的例子我们把oldboy源文件删除,然后看一下啊oldboy_hard_link是不是能看到其内容。
[root@localhost oldboy]# echo 'i am oldboy!'>>oldboy [root@localhost oldboy]# ln oldboy oldboy_hard_link [root@localhost oldboy]# cat oldboy i am oldboy! [root@localhost oldboy]# cat oldboy_hard_link i am oldboy! [root@localhost oldboy]# rm -f oldboy [root@localhost oldboy]# ls -l oldboy* -rw-r--r-- 1 root root 13 May 1 08:15 oldboy_hard_link [root@localhost oldboy]# cat oldboy_hard_link
特别提示:目录不能创建硬链接,只有文件才能创建硬链接。
软链接的原理及示例:
创建软链接(也称为符号链接)的语法:
#ln -s 源文件或目录 目标文件或目录
软链接也叫符号链接,它和硬链接有所不同,软链接文件(包含到源文件的路径位置等信息)。当我们删除了源文件后,软链接就不能独立存在了。虽然仍然会保留文件名(失效后查看时会是红色闪烁状),但我们却不能查看软链接的内容了。
[root@localhost oldboy]# echo test >>etiantian.txt [root@localhost oldboy]# ls -li etiantian.txt 810404 -rw-r--r-- 1 root root 5 May 1 08:25 etiantian.txt [root@localhost oldboy]# ln -s etiantian.txt etiantian_soft_link.txt [root@localhost oldboy]# ls -li etiantian* 810405 lrwxrwxrwx 1 root root 13 May 1 08:25 etiantian_soft_link.txt -> etiantian.txt 810404 -rw-r--r-- 1 root root 5 May 1 08:25 etiantian.txt
在上面的例子中,我们首先查看下etiantian.txt的属性,比如文件的inode、所属文件类型、创建或修改时间等...,我们来对比一下:
1.对比一下节点:两个文件的inode节点值不同; 2.两个文件的文件类型不同etiantian.txt是-(表示普通文件),而etiantian_soft_link.txt 是l(字母l表示链接文件); 3.两个文件的读写权限不同etiantian.txt是-rw-r--r--,而etiantian_soft_link.txt的读写权限是rwxrwxrwx 4.两个文件的硬链接个数相同;都是1 5.两个文件的属主和所归属的用户组相同; 6.两个文件的创建或修改的时间列不同;
我们还注意带了etiantian.txt后面有一个标记”.>”,这表示etiantian_soft_link.txt是etiantian.txt的软链接文件。
特别提醒:
当我们修改链接文件的内容时,就意味着我们在修改源文件的内容。此时源文件的属性也会发生改变,但软链接文件的属性并不会发生变化。如我们把源文件删除后,则链接文件只会存在一个失效的文件名,因为失去了源文件,所以软链接也就不存在了。这一点和硬链接是不同的;
[root@localhost oldboy]# ls -li etiantian_soft_link.txt 810405 lrwxrwxrwx 1 root root 13 May 1 08:25 etiantian_soft_link.txt -> etiantian.txt
截图更清晰:
从上面的例子可以看出,如果一个链接文件失去了源文件,它就已经不存在了;虽然仍会保留文件名(失效后查看时会是红色闪烁状),也无法访问到文件了。
我们可以看到软链接文件其实相当于源文件的一个快捷方式,当源文件失去时,它也就不存在了。软链接文件只是占用了inode来存储软链接文件属性等信息,但文件内容存储是指向源文件的。
与硬链接不同的是,软链接对文件和目录都适用。无论是软链接还是硬链接,都相当于物件或目录,因此都可以用rm命令来删除。
Linux中文件的权限
文件权限概述
Linux中的文件或目录的权限和用户和用户组关联很大,要理解这部分内容,需要先理解一下Linux系统中用户管理方面的知识。
每个文件或目录都有一组共9个权限位,每三位为一组,他们分别是属主权限位(占三个字符)、用户组权限(占三位字符)、其它用户权限位(占三个字符)。
权限位说明
Linux文件或目录的权限位是9个权限位来控制,每三位为一组,他们分别是文件属主(Owner)的读写执行,用户组(group)的读写执行以及(Other)其他用户的读写执行;
文件属主:读r、写w、执行x
用户组:读r、写w、执行x
其他用户:读r、写w、执行x
如果权限位不可读,不可写,不可执行,则用-来表示。
Linux普通文件的读、写、执行权限说明:
可读r:表示具有读取阅读文件内容的权限
可写w:表示具有新增、修改文件内容的权限;(特别提醒:删除或修改、移动文件,这样的权限受父目录的权限控制)
可执行x:表示具有执行文件的权限
Linux目录的读、写、执行权限说明:
进入目录的权限:x
浏览目录的权限:r
修改目录内文件的权限:w
Linux文件与目录权限对比说明
r(read,读取权限): 对文件而言,表示具有读取阅读文件内容的权限; 对目录而言,表示具有浏览目录的权限(注意:与进入目录的权限不同) w(write,写入权限): 对文件而言,表示具有新增、修改文件内容的权限(注意:删除和移动文件和文件本身属性无关); 对目录而言,表示具有删除、一定目录内的权限 x(Execute,执行权限): 对文件而言,表示具有执行文件的权限; 对目录而言,表示具有进入目录的权限 -(无任何权限) 若对应位置权限为字符”-”,表示对应用户没有读、写、执行的任何权限。
特别注意:
当删除或移动一个文件或目录,仅与该文件与目录所在的上一层权限有关,与该文件本身属性无任何关系。
对于文件来说,写文件是修改文件,而不是删除文件,因此写文件是与该文件的本身属性有关系的。
普通文件的读、写、执行举例:
[root@localhost oldboy]# echo test >> oldboy [root@localhost oldboy]# chmod 755 oldboy [root@localhost oldboy]# ls -l oldboy -rwxr-xr-x 1 root root 5 May 1 09:57 oldboy
第一列-rwxr-xr-x 中的第一个字符是-,表示oldboy是一个普通文件;
Oldboy文件的权限是-rwxr-xr-x ,表示oldboy文件,文件的属主root,拥有rwx(可读、可写、可执行)权限,用户组root,拥有r-x(可读、可写)权限,其他用户拥有r-x(可读、可写)权限。这9个权限连在一起就是-rwxr-xr-x 。
提示:查看文件的属性用ls -l文件名或目录名;仅查看目录的属性是ls -ld目录。
改变权限属性命令chmod
chmod是用来改变文件或目录权限的命令,但只有文件的属主和超级用户root才有这种权限。通过chmod来改变文件或目录的权限有两种方法:一种是通过权限字母和操作符表达式的方法来设置权限;另一种是使用数字来设置权限。下面分别进行介绍。
[root@localhost oldboy]# touch ett.txt #创建ett.txt文件 [root@localhost oldboy]# touch oldboy.txt #创建oldboy.txt文件 [root@localhost oldboy]# ls -lh ett.txt oldboy.txt #查看ett.txt和oldboy.txt文件属性 -rw-r--r-- 1 root root 0 May 1 10:10 ett.txt -rw-r--r-- 1 root root 0 May 1 10:10 oldboy.txt [root@localhost oldboy]# chmod 755 ett.txt #通过数字来改变ett.txt的权限 [root@localhost oldboy]# chmod u+x,og+x oldboy.txt #通过字符式语法来改变文件的权限 [root@localhost oldboy]# ls -lh ett.txt oldboy.txt -rwxr-xr-x 1 root root 0 May 1 10:10 ett.txt -rwxr-xr-x 1 root root 0 May 1 10:10 oldboy.txt
上面是通过chmod的两种语法来改变权限的例子,虽然两种语法不同,但是都能达到同一目的。
这个过程是:
1.创建ett.txt和oldboy.txt两个文件; 2.查看两个文件的属性;它们的权限都是一样的,都是rw-r--r-- ,表示文件可读可写、文件所归属的用户组对文件可读、其他用户可读; 3.通过chmod的数字方法来改变ett.txt的权限;通过chmod的字符式语法来改变oldboy.txt的权限;
我们用两种方法来分别改变ett.txt 和oldboy.txt文件,通过chmod的两种不同的语法来让两个文件的权限达到一致;
在数字方法中,我们用了755,而在字符式语法中,我们用了u+x,og+x。虽然用了两种不同的语法,但达到了相同的目的。最后的结果,我们可以看到两个文件的权限,都是rwxr-xr-x。也就是说文件的属主对文件有可读、可写、可执行的权限,文件所归属的用户组有可读、可执行的权限,其他用户有可读、可执行的权限。
通过上面的例子,让我们理解了chmod的两种授权语法:chmod的数字方法,chmod的字符式语法;下面我们分别来叙述。
chmod数字权限方法
使用数字权限设置权限的命令格式如下:
chmod [数字组合] 文件名
Chmod的数字语法简单直观,在表4-1中列出了用数字表示权限的组合,该组合由3个八进制数来表示文件的3类用户的权限组合。
chmod的数字方法的说明;
r 4 w 2 x 1 - 0
属主的数字权限表示法:
属主的数字权限为三个权限位的数字加起来的总和。比如上面的例子ett.txt属主的权限是rwx,数字权限为4+2+1=7;
属组的数字权限表示法:
属组的数字权限同样为三个权限位的数字加起来的总和。比如上面的例子中的r-x,数字权限为4+0+1=5;
其他用户的数字权限表示法:
其他用户数字权限同样。上面上面例子中是r-x ,数字权限为4+0+1=5;
[root@localhost ~]# cd /test/oldboy/ [root@localhost oldboy]# ls ett.txt oldboy oldboy.txt [root@localhost oldboy]# ls -l oldboy -rwxr-xr-x 1 root root 5 May 1 09:57 oldboy [root@localhost oldboy]# chmod 644 oldboy [root@localhost oldboy]# ls -l oldboy -rw-r--r-- 1 root root 5 May 1 09:57 oldboy
每个三位的权限代码(分别是属主、数组,其他用户)组合,有8种可能;
提示:我们根据上面的数字列表来组合权限,比如我想让属主拥有rwx(所对应的数字是7),数组拥有-x(所对应的数字是1),其他用户拥有--(所对应的数字是0),这样我们把各组的权限组合就是rwx--x---(对于的数字是710)
[root@localhost oldboy]# ls -l oldboy -rw-r--r-- 1 root root 5 May 1 09:57 oldboy [root@localhost oldboy]# chmod 710 oldboy [root@localhost oldboy]# ls -l oldboy -rwx--x--- 1 root root 5 May 1 09:57 oldboy
如果我们想改变的仅仅是打开目录的权限,使用chmod命令时不用加任何参数。如果想把目录一下啊的所有文件或子目录也同时改变,需要使用-R参数;
[root@localhost oldboy]# mkdir etiantian [root@localhost oldboy]# touch ett_oldboy [root@localhost oldboy]# mv ett_oldboy etiantian/ [root@localhost oldboy]# ls -ld etiantian/ #我们查看到的etiantian目录的权限是rwxr-xr-x; drwxr-xr-x 2 root root 4096 May 1 21:35 etiantian/
我们仅仅改变etiantian的权限,让其拥有属主可读可写、属组可读、其他用户可读,也就是rw-r--r--,用数字权限表示为644.
[root@localhost oldboy]# chmod 644 etiantian/ [root@localhost oldboy]# ls -ld etiantian/ drw-r--r-- 2 root root 4096 May 1 21:35 etiantian/ #改变成功 [root@localhost oldboy]# ls -lr etiantian/ #我们查看一下etiantian目录下的子目录是否改变了? total 4 -rw-r--r-- 1 root root 0 May 1 21:34 ett_oldboy
尝试一下把etiantian及其子目录和文件权限都要改变为rw-r--r-- 权限。我们要用到-R参数;
oot@localhost oldboy]# chmod -R 644 etiantian/ #我们改变etiantian下所有的文件或子目录的权限都为rw-r--r-- ; [root@localhost oldboy]# ls -ld etiantian/ drw-r--r-- 2 root root 4096 May 1 21:35 etiantian/ [root@localhost oldboy]# ls -lr etiantian/ total 4 -rw-r--r-- 1 root root 0 May 1 21:34 ett_oldboy
值得注意的是:chmod改变一个目录下的所有file时,要小心操作。比如我们要改变etiantian下的所有file的权限为rwxr--r-- ,但我们不想改变etiantian目录的权限。下面的例子操作是错误的。
[root@localhost oldboy]# ls -ld etiantian/ drw-r--r-- 2 root root 4096 May 1 21:35 etiantian/ [root@localhost oldboy]# ls -lr etiantian/ total 4 -rw-r--r-- 1 root root 0 May 1 21:34 ett_oldboy [root@localhost oldboy]# chmod -R 755 etiantian/* #这样操作,会把etiantian目录的权限一并改为rwxr--r-- ; [root@localhost oldboy]# ls -ld etiantian/ drwxr-xr-x 2 root root 4096 May 1 21:35 etiantian/
所以当你想改变一个目录下的所有.file权限,并且想保留该目录的原有权限时,请不要用.*通配符。可用下面的匹配:
[root@localhost oldboy]# chmod -R 644 etiantian/[a-z]*
上面的例子chmod会匹配所有以a到z开头的文件
chmod字符式权限表示法
使用权限字符设置权限的命令格式以下:
chmod [用户类型] [+|-|=] [权限字符] 文件名
chmod的字符式语法相对简单,对文件或目录的改变时,是通过比较直观的字符的形式来完成;
在字符式语法中,相关字母的定义;
用户或用户组定义:
u:代表属主
g:代表属组
o:代表其他用户
a:代表属主、属组和其他用户,也就是上面三个用户(或组)的所有;
权限定义字母:
r 代表读权限
w 代表写权限
x 代表执行权限
权限增减字符
+:添加某个权限 -:取消某个权限 =: 赋予给定权限并取消其他所有权限
示例1:
[root@localhost oldboy]# ls -l ett.txt -rwxr-xr-x 1 root root 0 May 1 10:10 ett.txt [root@localhost oldboy]# chmod ugo-x ett.txt #把属主、用户组及其他用户的执行权限都减掉 [root@localhost oldboy]# ls -l ett.txt -rw-r--r-- 1 root root 0 May 1 10:10 ett.txt #我们看到对于权限的x位已经变成了-号
示例2:
[root@localhost oldboy]# ls -l ett.txt -rw-r--r-- 1 root root 0 May 1 10:10 ett.txt [root@localhost oldboy]# chmod u+x ett.txt #为文件的属主增加执行权限 [root@localhost oldboy]# ls -l ett.txt -rwxr--r-- 1 root root 0 May 1 10:10 ett.txt #我们看到x位已经变成了x号
示例3:
[root@localhost oldboy]# ls -l ett.txt -rwxr--r-- 1 root root 0 May 1 10:10 ett.txt [root@localhost oldboy]# chmod u-x,go+rw ett.txt #减去文件属主对文件的执行权,增加属组和其他用户对文件的可读写权; [root@localhost oldboy]# ls -l ett.txt -rw-rw-rw- 1 root root 0 May 1 10:10 ett.txt
用字符式语法比较灵活,组合起来方便;比如:
u=r+x 为文件属主添加读写权限 ug=rwx,0=r 为属主和属组添加读、写、执行权限,为其他用户设置读权限 a+x:为文件的属主、属组和其他用户添加执行权限 g=u:让文件的属组和属主和权限相同;
对于目录权限的设置,要用到-R参数:
和数字权限方法一样,如果我们会为一个目录及其下的子目录和文军具有相同的属性,就可以用-R参数;
[root@localhost oldboy]# chmod -R a+rwx etiantian/ [root@localhost oldboy]# ls -lr etiantian/ total 4 -rwxrwxrwx 1 root root 0 May 1 21:34 ett_oldboy
默认权限分配的命令umask
umask是通过八进制的数值来定义用户创建文件或目录的默认权限。umask表示的是禁止权限。具体的细节,文件和目录略有不同。
重要总结:
对于文件来说,umask的设置是在假定文件拥有八进制666权限上进行,文件的权限就是666减去umask的掩码数值;
对于目录来说,umask的设置是在假定文件拥有八进制777权限上进行,目录八进制权限777减去umask的掩码数值;
默认文件权限计算方法
666 ==>文件的起始权限值 022- ==>umask的值 ............. 644
默认目录权限计算方法
777 ==>目录的起始权限值 022- ==>umask的值 ............. 755
示例1:
[root@localhost oldboy]# umask 0022 #umask当前数值 [root@localhost oldboy]# umask 044 #更改为044 [root@localhost oldboy]# umask 0044 [root@localhost oldboy]# mkdir umask_test #建目录测试 [root@localhost oldboy]# ls -ld umask_test/ drwx-wx-wx 2 root root 4096 May 1 23:32 umask_test/ #对于数字权限为733,是不是服务上面的计算方法? [root@localhost oldboy]# touch umask_test.txt [root@localhost oldboy]# ls -l umask_test.txt -rw--w--w- 1 root root 0 May 1 23:32 umask_test.txt #对于数字权限为622,是不是服务上面的计算方法?
实例2:
Linux系统用户的加目录的权限是通过在配置文件中指定的,比如/etc/login.defs文件;
其中有这样一段:
# If useradd should create home directories for users by default # On RH systems, we do. This option is overridden with the -m flag on # useradd command line. # CREATE_HOME yes # The permission mask is initialized to this value. If not specified, # the permission mask will be initialized to 022. UMASK 077
表示的意思是,当我们创建用户时,他的家目录umask的数值是077。我们怎么理解这个077呢。
当添加用户时,系统自动在/home中创建用户的家目录,并且设置它的权限为777-077=700,也就是rwx------,我们看一下/home下的某个用户的家目录是不是这样的呢?
[root@localhost oldboy]# ls -ld /home/zgy/ drwx------ 3 zgy zgy 4096 Apr 30 21:40 /home/zgy/
Umask一般都是放在用户相关SHELL的配置文件中,比如用户家目录下的.bashrc或.profile,也可以放在全局性的用户配置文件中,比如/etc/login.defs,还可以放在SHELL全局配置文件中,比如/etc/bashrc或/etc/profile等;
umask放在相关的配置文件中,目的是当管理员创建用户时,系统会自动为用户创建文件或目录时配置默认的权限代码。
特别提示:在一般生产场景,umask的使用不多见,在此,大家了解下umask是怎么回事即可。
setid和setgid位
特别提醒:
本部分内容仅为了解内容,在一般的生产场景,运维人员使用色推动,setgid的情况不多见,也不推荐大家使用<setuid,setgid本身功能不错,但是会带来安全隐患>。在此,大家了解下setuid,setgid是怎么回事即可。
setuid和setgid介绍
setuid和setgid位是让普通用户可以让root用户的角色运行只有root账号才能运行的程序或命令。(注意和su及sudo的区别)
在Linux中,有时执行某个命令时,需要对另一个文件进行操作,而这个文件又不是普通用户有权限进行操作的。例如,修改用户密码的命令passwd,实际上最终更改的是/etc/passwd文件,该文件的所有者和组都是root,同组用户和其他用户具有执行权限,只有root权限的用户才能更改,但是普通用户也可使用该命令修改自己密码(这个不用验证了吧?)
[root@localhost oldboy]# ls -l /etc/passwd -rw-r--r-- 1 root root 1496 Apr 30 21:40 /etc/passwd
#所有者和组都是root,按照我们学过的知识,普通用户是无法更改这个文件的,但是setuid的功能可以让普通用户做到这个本没有权限的密码文件
按照我们学过的知识,如果普通用户通过修改/etc/passwd修改自己的口令肯定是不可完成的任务。平时我们也不这么做,作为普通用户可以通过passwd来修改自己的口令,既然没权限,为什么还能修改密码呢?在答案揭晓前,我们来看一下passwd命令的权限。
[root@localhost oldboy]# ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 23420 Aug 3 2010 /usr/bin/passwd
因为/usr/bin/passwd文件已经设置了setuid权限位(也就是r-s--x--x中的s),所以普通用户在执行/usr/bin/passwd命令时能够使用root用户的权限,间接的修改/etc/passwd,已达到修改自己口令的权限。
我们知道Linux的用户管理是极为严格的,不同的用户拥有不同的权限,为了完成只有root用户才能完成的工作,我们必须为普通用户提升权限,最常用的方法就是su或sudo。为了setuid和setgid也是让普通用户超越自身拥有的普通权限达到使用root权限的方法。但不推荐大家使用,因为它能为系统带来安全隐患!!
特别提醒:setuid和setgid会面临风险,所以尽可能的少用(尤其是使用不当),了解什么回事即可。
setuid和setgid实例应用
我们想让一个普通用户oldboy拥有root用户才拥有的rm删除权限,我么除了用su或sudo临时切换到root身份或以root的身份操作意外,还可以怎么做呢?
[root@localhost oldboy]# cd /home/ #进入/home目录 [root@localhost home]# touch zgytest.txt #创建一个测试文件 [root@localhost home]# ls -l zgytest.txt #查看文件属性 -rw--w--w- 1 root root 0 May 2 01:04 zgytest.txt #文件的属性 [root@localhost home]# su - zgy #切换普通用户 [zgy@localhost ~]$ cd /home/ [zgy@localhost home]$ rm -f zgytest.txt #以普通用户身份来删除zgytest.txt文件 rm: cannot remove `zgytest.txt': Permission denied #权限不够
那我们怎样才能让zgy这个普通用户也拥有root超级的rm删除功力呢?好,引出本节的主题setuid,setgid。
[root@localhost ~]# ls -l /bin/rm -rwxr-xr-x 1 root root 46480 Mar 14 2012 /bin/rm [root@localhost ~]# chmod 4755 /bin/rm #设置rm的权限为4755,这样就把setuid位设置好了 [root@localhost ~]# ls -l /bin/rm -rwsr-xr-x 1 root root 46480 Mar 14 2012 /bin/rm #属主位置增加了s [root@localhost ~]# cd /home/ [root@localhost home]# su - zgy #切换到普通用户zgy [zgy@localhost ~]$ cd /home/ [zgy@localhost home]$ ls -l zgytest.txt #查看文件属性 -rw--w--w- 1 root root 0 May 2 01:04 zgytest.txt #文件属性 [zgy@localhost home]$ rm -f zgytest.txt #轻松的删除了zgytest.txt文件
如上面内容所示,我们设置了rm的setuid位后,就让普通用户在rm指令上有了超级root才能享受的删除权力。
通过这个例子,我们应该能明白setuid和setgid位的应用了,如同前面所说,让普通用户超越本身的能力,让普通用户能执行只有root才能执行的命令。在这一点,我们要和su和sudo区分开来。
setuid和setgid设置说明
特殊权限位数字权限(八进制)方法
setuid位是用八进制的4000,setgid占用的是把您在的2000;比如我们前面所说的chmod 4755 /bin/rm就是设置的setuid位;
setuid设置方法:
其实就是在我们通过chmod设置文件或目录权限位的数字权限为的数字方法的前面多加一个数字4.比如:
[root@localhost ~]# chmod 4755 /bin/rm #设置rm的权限为4755,这样就把setuid位设置好了
setgid设置方法:
setgid位占用的是八进制的2000,其实就是在我们通过chmod设置文件或目录权限位的数字权限方法的前面多加一个数字2.我们下面举个例子:
[root@localhost ~]# cd /home/ [root@localhost home]# mkdir student_dir [root@localhost home]# ls -ld student_dir/ drwxr-xr-x 2 root root 4096 May 2 05:25 student_dir/ [root@localhost home]# chmod 2755 student_dir/ [root@localhost home]# ls -ld student_dir/ drwxr-sr-x 2 root root 4096 May 2 05:25 student_dir
我们看到student_dir这个目录,经过改变权限后的目录所归属用户组的那三个权限位r-s。
特别提醒:如果我们见到的是小写的s,表明文件所归属的用户组位有执行权限x。因为我们用了2755,意思是说文件属主拥有可读可写可执行,所归属的用户组拥有可读可执行权限,并且设置了setuid,所以这时本来文件所归属的用户组拥有r-x,现在加了setgid位,就把其中的x换成了s。如果文件所归属的用户组没有执行权限,这个权限应该是S。同理setuid位中的大写S和小写的s,也是这个原理。
见下面的例子:如果本来在该位上有x,则这些特殊标志显示为小写字母(s,s,t)。否则,显示为大写字母(S,S,T)。
[root@localhost home]# chmod 2740 student_dir/ [root@localhost home]# ls -ld student_dir/ drwxr-S--- 2 root root 4096 May 2 05:25 student_dir/
这个例子是因为目录student_dir所归属的组没有执行权限,这时本来在执行权限位上显示-,由于有了setuid,所以显示为S。
如果我们为一个文件ett.txt的设置权限拥有属主可读、可写、可执行权限,所归属的组拥有可读、可执行权限,其他用户可读、可执行权限,并且同时设置setuid和setgid位,我们应该怎么运行命令呢?
[root@localhost oldboy]# touch ett.txt [root@localhost oldboy]# ls -l ett.txt -rw-r--r-- 1 root root 0 May 2 06:49 ett.txt [root@localhost oldboy]# chmod 6755 ett.txt #同时设置setuid,setgid的命令办法为6755,6相当于4+2 [root@localhost oldboy]# ls -l ett.txt -rwsr-sr-x 1 root root 0 May 2 06:49 ett.txt
所以,同时设置setuid和setgid,就是把setuid和setgid两个八进位的值相加(4000+2000=6000),然后加上文件或目录的权限位的三个数值(上面的例子是755),然后通过chmod运行就行了,然后上面例子中用了6755.
特殊权限位字符式语法方法
还是用chmod的字符式语法,通过u+s或u-s来增减setuid位,同理,我们可以通过g+s来增减setgid位;
[root@localhost oldboy]# touch comment.txt [root@localhost oldboy]# ls -l comment.txt -rw-r--r-- 1 root root 0 May 2 06:59 comment.txt [root@localhost oldboy]# chmod u+s comment.txt [root@localhost oldboy]# ls -l comment.txt -rwSr--r-- 1 root root 0 May 2 06:59 comment.txt
我们也可以用file命令来查看setuid和setgid位,当然也能用file来查看文件的类型;
比如:
[root@localhost oldboy]# file /usr/bin/passwd /usr/bin/passwd: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), stripped
黏贴位及设置方法
黏贴位的理解,我们还是先看一个例子
[root@localhost oldboy]# ls -ld /tmp/ drwxrwxrwt 17 root root 4096 May 2 06:34 /tmp/
我们看到/tmp权限位最后的一个字母是t。这就是设置了黏贴位。
黏贴位的设置,用八进制的1000位来表示。比如
[root@localhost oldboy]# mkdir zgy_dir [root@localhost oldboy]# ls -ld zgy_dir/ drwxr-xr-x 2 root root 4096 May 2 07:04 zgy_dir/ [root@localhost oldboy]# chmod 1755 zgy_dir/ #设置黏贴位的数字权限方法 [root@localhost oldboy]# ls -ld zgy_dir/ drwxr-xr-t 2 root root 4096 May 2 07:04 zgy_dir/
也可以用chmod的字符式语法来设置。用o+t表示设置黏贴位,用o-t表示取消黏贴位;
[root@localhost oldboy]# ls -ld zgy_dir/ drwxr-xr-x 2 root root 4096 May 2 07:04 zgy_dir/ [root@localhost oldboy]# chmod o+t zgy_dir/ [root@localhost oldboy]# ls -ld zgy_dir/ drwxr-xr-t 2 root root 4096 May 2 07:04 zgy_dir/ #是不是有了黏贴位的设置,字母t就是。
黏贴位的功能限制也很少用了,不过对于像/tmp目录这样的,是整个系统临时文件存放地,还是有点意义。一个目录即使它的所有权限都开放rwxrwxrwx,如果是设置了黏贴位,除非目录的属主和root用户有权限删除它,除此之外其他用户不能删除这个目录。用途一般是把一个文件夹的权限都打开,然后来共享文件,像/tmp目录一样,方便带来的安全隐患,生产环境我们一般不这样使用!
文件或目录的归属关系
文件或目录的归属关系主要定义文件或归属哪个用户所有及归于哪个用户组所有。
[root@localhost oldboy]# ls -l oldboy -rw-r--r-- 1 root root 5 May 1 09:57 oldboy
上面的例子表示,oldboy这个文件,其属主是root,归
属的组是root用户组,而root用户所拥有的权限是rw-,root用户组拥有的权限是r--。
有时我们可能不理解,为什么Linux要设置文件的属主、属组,为什么还要为属主、属组和其他用户都要设置权限呢?我们在以前的文档说过,Linux是多用户的操作系统,文件的安全性对Linux是极为重要的,Linux的安全性主要表示在用户管理和权限(用户的权限及文件的权限)管理上。
改变文件所属关系命令chown
当我们要改变一个文件的属组。我们所使用的用户必须是该文件的属主而且同时是目标属组成员,或超级用户。只有超级用户才能改变文件的属主。
chown 语法
chown [选项]... [所有者][:[组]] 文件...
举例:将oldboy文件的属主改为oldboy用户
[root@localhost oldboy]# ls -l oldboy -rw-r--r-- 1 root root 5 May 1 09:57 oldboy [root@localhost ~]# chown oldboy:root oldboy #这里冒号也可以换成点(.) [root@localhost oldboy]# ls -l oldboy -rw-r--r-- 1 oldboy root 5 May 1 09:57 oldboy
说明:chown 所接的新的属主和新的属组之间应该以.或:连接,属主和属组任意之一可以为空。如果属主为空,应该是:属组;如果属组为空,就不必需要.或:了。
root@localhost ~]# mkdir -p /test/oldboy [root@localhost ~]# cd /test/oldboy/ [root@localhost oldboy]# touch oldboy.txt [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 root root 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# chown zgy oldboy.txt #把oldboy.txt的属主改为zgy [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 zgy root 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# chown :zgy oldboy.txt [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 zgy zgy 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# chown root:etiantian oldboy.txt #把oldboy.txt的属主改为root,把属组改成etiantian用户组 [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 root etiantian 0 May 3 08:09 oldboy.txt 特别提示:要修改的用户和组鄙视是系统中已经存在的。
chown也提供了-R参数,这个参数对目录改变属主和属组极为有用,我们可以通过加-R参数来改变某个目录下的所有文件到新的属主或属组;
[root@localhost oldboy]# mkdir zgy_dir [root@localhost oldboy]# ls -ld zgy_dir/ drwxr-xr-x 2 root root 4096 May 3 08:26 zgy_dir/ [root@localhost oldboy]# mkdir zgy_dir [root@localhost oldboy]# ls -ld zgy_dir/ drwxr-xr-x 2 root root 4096 May 3 08:26 zgy_dir/
改变文件的数组命令chgrp
语法:
chgrp [参数选项]... 组 文件
它的用户和chown类似,只不过它仅是用来改变文件或目录的属组的;-R参数用于目录及目录下所有文件改变属组的。这和chown也是一样的,可以把chgrp看作是chown的子集。一般会用chown即可。我们来两个例子简单阐述下chgrp的用法
例子1:
[root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 root root 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# chgrp zgy oldboy.txt [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 root zgy 0 May 3 08:09 oldboy.txt
文件属主和属组的特殊情况
[root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 root zgy 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# chown ett oldboy.txt [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 ett zgy 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# userdel ett [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 502 zgy 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# useradd ett Creating mailbox file: File exists useradd: warning: the home directory already exists. Not copying any file from skel directory into it. [root@localhost oldboy]# chown ett:ett oldboy.txt [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 ett ett 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# userdel ett [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 504 504 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# useradd oldboy123 [root@localhost oldboy]# chown oldboy123:oldboy123 oldboy.txt [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 oldboy123 oldboy123 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# userdel oldboy123 [root@localhost oldboy]# cd /home/oldboy123/ [root@localhost oldboy123]# ls -l oldboy.txt ls: oldboy.txt: No such file or directory [root@localhost oldboy123]# cd - /test/oldboy [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 504 504 0 May 3 08:09 oldboy.txt
上面的例子是不是有点奇怪?因为它的属主和数字都是一个数值;这是为什么呢?出现这种情况的原因是系统中不存放与之对应的用户,所有只能以数字形式显示了。也就是说一旦删除了用户,而文件原来文件的的属主或属组是这个用户,那么该文件的属主或属组就会变成数字形式。
文件被修改或被访问的时间
我们通过查看文件的属性时,会发现它的时间标记。这个时间并不代表文件被创建的时候,他是代表文件被访问或被修改的时间。文件被修改的时间比较好理解,比如我们可以用编辑器来修改文本文件,然后保存一下,这样文件的时间就变了。
当然也有其他的工具不修改文件的内容,只修改文件的时间,这时可以被称为访问时间,比如touch工具能达到能达到这个目的。
[root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 zgy zgy 0 May 3 08:09 oldboy.txt [root@localhost oldboy]# touch oldboy.txt #更改文件的访问时间为当前系统时间 [root@localhost oldboy]# ls -l oldboy.txt -rw-r--r-- 1 zgy zgy 0 May 3 09:30 oldboy.txt
关于touch的用法,更多的请参见:man touch 或touch --help
文件属性和文件系统属性的关系
文件系统的特性决定着文件属性的定义和修改,比如我们chattr来锁定一个文件为不可修改或不可删除时,要用到chattr的+i参数;这在ext2和ext3文件系统是有效的,但在reiserfs文件系统是没有任何效果的;
[root@localhost oldboy]# chattr +i oldboy.txt [root@localhost oldboy]# lsattr oldboy.txt ----i-------- oldboy.txt [root@localhost oldboy]# rm -f oldboy.txt rm: cannot remove `oldboy.txt': Operation not permitted 注:如果把oldboy.txt 变成可修改可删除,应该用-i参数;