Linux 权限非常的重要,正常情况下一个文件或目录有三种角色,分别为:目录或文件拥有者(User)、所属群组(Group)、其他用户(Other),每个角色对应:读、写、可执行(rwx)。这也是我们最常见的权限,#ls -l所看到第一列内容。第一位是文件类型,如:d 是目录、-是普通文件、l是链接文件、c是字符文件、b是块文件等。 剩下9位即是文件对应三种角色的权限。如下图: 

还会有其它一些特殊权限,如:SUID、SGID、 Sticky bit,还有一些需要通过命令lsattr来查看和chattr来设置的隐藏权限。

然而这些权限并没有办法单纯的针对某一用户或群组来设定特定的权限需求。这时候ACL可以帮助我们解决这个问题。
1.什么是ACL?

ACL(Access Control List)即访问控制列表。主要是针对单一用户,单一文件或目录进行rwx权限的细部设定。可以针对用户(User)、群组(Group)、默认属性掩码(mask)进行设置。

2.设置ACL前的准备工作
ACL 是Linux系统权限额外支持的一项功能,需要文件系统的支持,例如:ReiserFS , EXT2 , EXT3 , EXT4 , JFS , XFS等都支持ACL功能。如果你的文件系统支持ACL,接下来查看你的ACL功能是否启用。在RHEL6中查看文件系统是否启用ACL。
(1)使用#mount命令查看ACL

可以看到sda7的ACL已经启用。

注意:

如果是用tune2fs命令启用分区的ACL功能,用mount命令是看不到的,要使用tune2fs -l <分区>,查看“Default mount options:”的信息

(2) 永久 启用ACL

方法一:

如果你想永久在某个partition上启用ACL功能,可以修改 /etc/fstab 。 在rhel6的fstab文件中是用UUID来挂载,所以可以先来确定sda7的UUID号,如下图:

事实上由mount这条命令,你可以知道sda7是挂载在 /data目录。所以在fstab文件中找到挂载在该目录下partition就是一定是sda7了。当然也可以用更加可靠的做法,就是确定这个partition的UUID值。用blkid这条命令查到UUID,再和fstab中比对。
在sda7上启用ACL功能,只需在defaults后加上acl,如下图:

修改完成,保存退出后。重新用mount 命令挂载这个分区。命令如下:

#mount -o remount /dev/sda7

之后再用mount 查看所有已挂载设备,应该能够看 (rw,acl) 字样。

方法二:

还可以使用tune2fs命令设置分区永久启用ACL

tune2fs -o acl <分区>    #设置分区永久启用ACL

tune2fs  -l <分区>    #查看分区详细信息

可以看到“Default mount options:    acl”的信息,说明这个分区的ACL已经启用了。
 
3.ACL 相关设置命令
有以下三条命令:

getfacl取得文件或目录的ACL设置信息。 

setfac设置文件或目录的ACL设置信息。

chaclsetfacl,也是用来设定ACL设置信息。用法类似于chmod。不常用。

这里主要介绍getfacl和setfacl命令。 下图是三条命令的man page:

命令常用参数:

(1) getfacl [-aceEsRLPtpndvh] file...

-a , --access显示文件或目录的访问控制列表。

-d , --default显示文件或目录的默认(缺省)的访问控制列表。

-e , --all-effective列出有效权限。

 -c , --omit-header:不显示默认的访问控制列表。

-R , --recursive:操作递归到子目录。

-t , --tabular:使用列表输格式出ACL设置信息。

-n , --numeric:显示ACL信息中的用户和组的UIDGID

(2) setfacl  [-bkndRLP]  { -m|-M|-x|-X ... }  file ...

-m, --modify=acl更改文件或目录的ACL规则。

-x, --remove=acl删除文件或目录指定的ACL规则。

-b, --remove-all删除文件或目录所有的ACL规则。

-k, --remove-default删除文件或目录默认的ACL规则。

-d, --default设置目录默认的ACL规则(只对目录有效)。

-M, --modify-file=file:从一个文件读入ACL设置信息并以此为模版修改当前文件或目录的ACL规则。

-X, --remove-file=file:从一个文件读入ACL设置信息并以此为模版删除当前文件或目录的ACL规则。

--set=acl:设置当前文件的ACL规则

--set-file=file:从文件读入ACL规则来设置当前文件或目录的ACL规则

--mask:重新计算有效权限,即使ACL mask被明确指定。

--restore=file:从文件恢复备份的ACL规则(这些文件可由getfacl -R产生<---针对目录)。通过这种机制可以恢复整个目录树的acl设置信息。此参数不能和除--test以外的任何参数一同执行。

-n, --no-mask:不要重新计算有效权限。setfacl默认会重新计算ACL mask,除非mask被明确的制定。

--test:测试模式,不会改变任何文件或目录的ACL规则,操作后的ACL规格将被显示。

-R --recursive:递归处理,将指定目录下的所有文件及子目录一并处理。 

指定ACL规则的4种情况:

(1)[d:]u:<UID|用户>:<权限> #指定用户的ACL[d:]表示配置用户对文件或目录的默认的ACL,权限可以使用字符或数字。

(2)[d:]g:<GID|用户组>:<权限> #指定用户的ACL[d:]表示配置用户对文件或目录的默认的ACL,权限可以使用字符或数字。

(3)[d:]o:<权限> #相关于普通权限中其他用户的权限,[d:]表示配置用户对文件或目录的默认的ACL,权限可以使用字符或数字。

(4)[d:] m:<权限> #指定有效权限,[d:]表示配置的默认的权限,权限可以使用字符或数字。

3.实例
由于我的sda7这个partition经过上面的动作,已经启用了ACL功能,挂载在 /data目录下。下面所有的动作都是在这个目录下完成。
(1)默认的ACL设置信息
用root在 /data 目录下创建一个acl_test目录。

有没有发现在缺省设置里没有mask这一项,这是因为这个目录还没有设置扩展有ACL设置信息。
注意:

使设置信息能正常执行,需要满足以下条件:
 ★ 三个基本设置不能被删除。
 ★ 任何一条包含指定的用户名或群组名的设置信息必须包含有效的权限组合(即rwx的权限组合)。
 ★ 缺省设置信息必须存在。

由基本设置信息,我们可以知道文件名为 acl_test/ 的拥有者是root用户,所属群组是root组。
由缺省设置信息可知这个目录的权限是755,即只有root用户可读可写,root组和其他用户只有读的权限。
如果我想让 scan这个用户也具有可读可写,怎么办?
(2)针对目录的ACL设置
让scan这个用户对acl_test/ 这个目录可读可写。
设置规范:

setfacl -m u:[用户列表][rwx]   #针对用户的权限规范。

setfacl -m g:[群组列表][rwx]   #针对群组的权限规范。

至于其它人的设置没有意义。
针对scan用户的ACL设置如下图:

可以看到多了一条扩展的ACL设置信息。

注意:多了一个mask:rwx。这是一个权限掩码。用来控制你所设置的扩展ACL权限。你所设置的权限必须存于mask规定的范围内才会生效。也就是所谓的“有效权限(effective permission)”。你可以用getfacl -e命令查看,如下图:

注意:在这里说一下目录的x权限,这个权限必须要有,否则你即使有写的权限,也没有办法进入这个目录。这个权限决定了你是否可以进目录。非常重要!
注意:设置了ACL的目录或文件,在属性的最后一位会出现一个“+”号,如下图:

上面我们知道acl_test/ 这个目录只root用户可读可写,在设置了针对scan用户的ACL信息后,现在我们切换到scan用户看看可不可以进行写操作。如下图:

成功创建一个目录和一个文件。
(3)针对文件的ACL设置
如果是针对一个文件呢?下面我们用root用户在acl_test/目录下创建一个 acl_vim文件。这时候scan用户应该没有写入的权限。如下图:

切换到scan用户试试看。如下图:

没有写入权限。写入的动作被禁止。
下面我们要让scan用户对这个文件有写入的权限,所以我们来针对scan用户设置acl_vim文件的acl信息,如下图:

我们通过ACL设置信息,让scan这个用户具有对acl_vim文件读和写的权限。现在我们来切换到scan用户验证一下,如下图:

验证成功。也可以发现在文件属性的权限最后一位也有一个“+”号。
(4)针对有效权限mask的设定
设定规范:

setfacl -m m:[rwx]

setfacl -m m::[rwx]

设定acl_test/ 目录的有效权限为mask:r。如下图:

我们可以看到scan用户的有效权限变为r。包括group。
那么这时候scan用户对acl_test/ 这个目录还有没有写入权限。下面验证一下,如下图:

由于scan用户在这个目录上没有x权限,所以连这个目录都不能进入,尽管我们已经赋予scan用户rwx的ACL设置信息。最终权限由mask控制,你所设置的权限必须在mask内,否则相对mask多出来的权限也是无效的。
下面把mask改为原来的rwx。如下图:

这个时候scan用户就可以对这个目录写入了。上面的写入操作都可以实现了。

注意:如果setfacl命令不指定操作用户,那么就是对默认属主用户权限的操作(例如acl_test/目录,owner:root,group:root),这时候的setfacl命令功能上和传统的chmod相同。例如setfacl u::rwx,g::rwx,o::rwx acl_test/ 等价于chmod 777 acl_test/ 。就是把缺省设置信息全部设置为rwx的权限了。

注意:

文件和目录设置了ACL规则后,通过“ls -l”或“ll”命令查看文件或目录所属群组权限时,所看到的权限不再是该文件或目录所属群组权限,而是ACLmask的权限,不再显示群组的权限;mask有可能是最大权限(rwx),也可能不是(如:r或rw);所以要查看文件或目录所属群组的准确权限应该使用getfacl命令。

(5)针对预设权限的设定
我在设置了acl_test/ 目录的ACL后,在这个目录下再创建目录和文件时,并没有继承上层目录acl_test/ 的ACL设置信息。如下图:

之前我们在acl_test/ 目录下创建了scan/ 目录和scan_test文件用于验证acl_test/ 这个目录scan用户的ACL设置信息。所以可以看到它们的用户和组都为scan。而acl_vim是在上面步骤中用于验证文件上的ACL设置信息的设定。
可以看到目录scan/ 和文件scan_test 并没有继承上层acl_test/ 目录的ACL设置信息。
 
设置规范:

可以使用以下三种中的任意一种规范。

1setfacl -d -m [ug]:列表:[rwx] <目录> (注意:-d参数必须放在最前面。)

2setfacl -d --set [ug]:列表:[rwx] <目录> (注意:-d参数必须放在最前面。)

3setfacl -m d:[ug]:列表:[rwx] <目录>

让acl_test/ 这个目录下的所有文件和目录继承acl_test/ 目录的ACL设置信息。如下图:

下面我们切换到scan用户验证一下在acl_test/目录下创建目录和文件能不能继承acl_test/这个目录的ACL设置信息。如下图:

可以看到目录scan_1/和文件scan_test_1已经继承了上层acl_test/目录的ACL设置信息。在权限的最后一位都有个“+”号。
注意:当然文件和目录的继承又会有一些差异。因为文件不像目录,目录的下层可再创建文件和目录,所以目录在继承上层目录的ACL设置信息时,会保证在它下层的目录和文件仍可以继承它的ACL设置信息。所以它要完全继承上层目录的ACL设置信息。而文件不需要继承这些设置信息。所以对于文件来说仅会继承scan用户这条ACL设置信息即可,而LINUX系统中的文件默认是不允许有x权限的。所以尽管scan用户有rwx的权限,但是mask为rw,所以有scan用户对该文件的有效权限仅有rw的权限。
(6)setfacl其它一些操作

 

setfacl -x [ug]:用户或组 <文件或目录>删除特定用户或组在相关文件或目录上的ACL规则。

setfacl -b <文件或目录>删除文件或目录上所有的ACL规则。

注意:加上-R参数可以对目录递归处理。

注意:

cpmv命令对于ACL的支持,mv命令保持ACL设置信息,cp命令在使用-p-a参数时保留ACL设置信息。但是如果从一个支持ACL的文件系统向一个不支持ACL的文件系统移动或带ACL属性的拷贝,则会得到类似下面这样的错误提示,cp: preserving permissions for `filename: Operation not supported

 删除acl_test目录下acl_vim文件的ACL设置信息,如下图:

删除acl_test/目录下scan_1/目录的ACL设置信息,如下图:

 
备份和恢复ACL设置信息
备份和恢复scan_test_1文件的ACL设置信息,如下图:

在恢复的时候,不需要跟对应的文件名。可以看到恢复后的ACL信息和之前的一样。
到这里,ACL可以告一段落了。其中还有其它一些操作。