ACL是Linux里面常見的概念但並不是Linux特有的。很多產品包括硬件都有ACL的概念,比如思科交換機路由器也有ACL。無論在什么地方看到ACL,它的名稱既然叫訪問控制列表那就是要實現控制功能的,確切的說ACL就是用來實現靈活的權限控制的。#####
ACL的常用參數及使用格式##
- getfacl file |directory #查看ACL屬性
- setfacl -m u:uname:rwx file|directory #指定用戶ACL權限
- setfacl -M file.acl file|directory #通過調用文件的方式授予ACL權限
- setfacl -m g:group:rw file| directory #指定組ACL權限
- setfacl -m d:u:uname:rx directory #默認權限,此目錄新建文件默認有ACL
- setfacl -x u:uname file |directory #刪除用戶ACL權限
- setfacl -X file.acl directory #通過調用文件刪除ACL
- setfacl -k dir #刪除默認ACL權限
- setfacl –b file1 #清除所有ACL權限
- getfacl file1 | setfacl --set-file=- file2 #復制file1的acl權限給file2
- --set #set選項會把原有的ACL項都刪除,用新的替代,需要注意的是一定要包含
UGO的設置,不能象-m一樣只是添加ACL就可以
示例:
setfacl --set u::rw,u:wang:rw,g::r,o::- file1
有的人說既然傳統的屬主(owner)、屬組(group)、其他(other)讀寫執行管理已經實現了權限管理那這個ACL有什么意義呢?那是因為我們傳統的權限控制還不夠強大,功能還有很大所欠缺。為什么這樣說呢?那我們新建一個文件testfile它的默認屬性如下:
[13:58:54root@localhost data]#touch /data/testfile
[13:59:13root@localhost data]#ll testfile
-rw-r--r--. 1 root root 0 Mar 17 13:59 testfile
比方說我們現在有這么一個需求,我就希望屬於other的“u1”用戶對這個文件沒有訪問權限而不影響其他other成員的正常訪問,如果直接把other權限給改了,那other的其他成員也無法訪問該文件,影響范圍太廣了,結果很顯然,系統默認的權限管理無法實現這個需求。
為什么系統默認的無法實現這功能呢?因為傳統的權限設的太簡陋了,它只有兩個屬性:第一所有者、第二所屬組;根據這兩個屬性把訪問文件的人只能分為簡單的三類人:第一是文件所有者、第二是組的成員、第三是其他人,而上面的用戶“u1”不屬於這三類人屬於第四類人。萬一再來了個需求我不僅希望“u1”不能訪問這個文件,還要“u2"能讀寫,還要“u3”只能讀和執行...默認權限管理區分不出這么多人,所有它只能實現簡單的權限分配。因為這種場景所以就引入了ACL。
ACL除了文件的所有者,所屬組和其他人,可以對更多的用戶,甚至可以支持不同的組來設置權限,可以設置你任意指定的某個人或組還設置權限。
那在傳統權限管理無法滿足的條件下,我們就以ACL來實現上面的需求,我們希望在不影響傳統權限的情況下“u1”不能訪問testfile:
首先確認下用戶是否已創建
[15:40:46root@localhost data]#cat /etc/passwd|tail -1
u1:x:1009:1011::/home/u1:/bin/bash
查看文件原來的屬性
[16:27:33root@localhost data]#ll testfile
-rw-r--r--. 1 root root 0 Mar 17 13:59 testfile
設置“u1”對此文件權限為0(以八進制表示也可以用-表示)
[16:29:31root@localhost data]#setfacl -m u:u1:0 testfile
注意看賦予acl權限后和文件原本屬性變化,other位后面多了個+號
[16:31:49root@localhost data]#ll testfile
-rw-r--r--+ 1 root root 0 Mar 17 13:59 testfile
切換到屬於other的“u1”查看是否具有相應的other權限,結果顯然以ACL的權限優先,other權限已經沒有了
[16:31:54root@localhost data]#su u1
[16:43:51u1@localhost data]$cat testfile
cat: testfile: Permission denied
使用getfacl命令列出該文件的訪問控制列表
[17:25:54u3@localhost data]$getfacl testfile
# file: testfile
# owner: root #該文件所有者
# group: root #該文件所屬組
user::rw- #文件默認的權限屬性
user:u1:--- #ACL指定u1用戶的權限
group::r-- #文件默認所屬組權限
mask::rwx #顧名思義 掩碼起到遮掩作用 權限的線高位待會詳細描述
other::r-- #文件默認other權限
ACL使用是不是非常靈活,想針對誰就針對誰,甚至還可以針對組設置,比如我們希望g1組的人對testfile具有讀和寫權限,只需要把用戶附加組設給g1即可。
新建g1組並指定該組對testfile指定讀寫權限,新建用戶u2並指定所屬組為g1
[17:36:42root@localhost data]#groupadd g1
[17:36:54root@localhost data]#setfacl -m g:g1:rw testfile
[17:37:44root@localhost data]#useradd -G g1 u2
[17:47:06root@localhost data]#id u2
uid=1012(u2) gid=1015(u2) groups=1015(u2),1014(g1)
[17:47:12root@localhost data]#su u2
[17:47:23u2@localhost data]$cat testfile
asdf
[17:47:34u2@localhost data]$exit
exit
ACL優先級
ACL的優先級順序是所有者>ACL自定義用戶>ACL自定義組>其他人,當一個用戶去訪問某個文件的時候,它會判斷訪問此文件的人是不是所有者,如果是權限立即生效,后面不會再繼續往后判斷,如果不是那它繼續判斷訪問者是否ACL指定的用戶,如果是那ACL里面設置那用戶的權限生效了,它就不往后看了,下面做個驗證:把前面已經指定權限為0的u1放進g1組,看看u1是保留原來的0權限還是獲得了g1組的rw-權限
先看看控制列表
[17:47:43root@localhost data]#getfacl testfile
# file: testfile
# owner: root
# group: root
user::rw-
user:u1:--- #u1
group::r--
group:g1:rw- #g1
mask::rw-
other::r--
結果:u1加入了g1組后對testfile還是無訪問權限,他沒有得到g1組的rw-權限。
[17:48:35root@localhost data]#gpasswd -a u1 g1
Adding user u1 to group g1
[22:35:44root@localhost data]#id u1
uid=1009(u1) gid=1011(u1) groups=1011(u1),1014(g1)
[22:36:03root@localhost data]#su u1
[22:36:25u1@localhost data]$cat testfile
cat: testfile: Permission denied
想要用戶u1獲得g1的讀寫權限只有把原來用ACL指定的0權限刪除了,使用-x參數刪除:
[22:44:47root@localhost data]#setfacl -x u:u1 testfile
[22:45:15root@localhost data]#su u1
[22:46:13u1@localhost data]$cat testfile
asdf
[22:46:20u1@localhost data]$echo m9l >>testfile
mask
注意看testfile文件原來的group位,它已經不是我們一開始創建此文件時候的group用的了,看看是不是和下面的訪問控制列表的mask權限一樣?是的沒錯,原來ll列出來的group位已經被mask取代了。
[23:02:45root@localhost data]#ll testfile
-rw-rw-r--+ 1 root root 9 Mar 17 22:47 testfile
[23:02:59root@localhost data]#getfacl testfile
# file: testfile
# owner: root
# group: root
user::rw-
user:u2:rw-
group::r--
group:g1:rw-
mask::rw-
other::r--
mask權限用來做權限的限高的,所有自定義的用戶和組都只能比它低而不能比它高,這有什么用呢?我們可能會遇到這樣一種場景,我們針對了很多用戶設置了ACL權限,讀寫執行各不相同難以管理。某天覺得這些用戶的權限稍大了,要把他們的權限設小一點,如果用傳統的方法一個個的手動設置太麻煩了十幾個呢,那這時候mask的作用就體現出來了,我們只需要把mask設置小一點,因為所有人的權限只能比它低,就全降級了,那我們先來試試吧,真能起到這樣的效果嗎?
為了實驗就先再多造兩用戶吧
[23:30:55root@localhost data]#cat /etc/passwd | tail -4
u1:x:1009:1011::/home/u1:/bin/bash
u2:x:1010:1012::/home/u2:/bin/bash
u3:x:1011:1015::/home/u3:/bin/bash
u4:x:1012:1016::/home/u4:/bin/bash
然后指定大點的權限
[23:32:38root@localhost data]#setfacl -m u:u3:7 testfile
[23:33:05root@localhost data]#setfacl -m u:u4:6 testfile
好了,先看看表,注意看mask權限是不是變大了,因為人為的設定的權限比mask的大了,它也隨之往上加了
[23:33:25root@localhost data]#getfacl testfile
# file: testfile
# owner: root
# group: root
user::rw-
user:u2:rw-
user:u3:rwx
user:u4:rw-
group::r--
group:g1:rw-
mask::rwx
other::r--
因為mask權限現在就是文件原所屬組的權限,直接改了所屬組也就改了mask
[23:33:38root@localhost data]# ll testfile
-rw-rwxr--+ 1 root root 9 Mar 17 22:47 testfile
不過我們還是通過改ACL的mask來吧,還是用-m,設置所有用戶權限為只讀r,看到被限的用戶的小尾巴沒有?表面上給的權限再高的用戶因為有了限高桿都超不過去,有效的只能是r--,所有用戶的權限都降下來了,所以剛剛說的那個場景十幾個用戶我就不用一個個去設了,設置mask輕松解決了。
[23:41:37root@localhost data]#setfacl -m mask::r testfile
[23:46:57root@localhost data]#getfacl testfile
# file: testfile
# owner: root
# group: root
user::rw-
user:u2:rw- #effective:r--
user:u3:rwx #effective:r--
user:u4:rw- #effective:r--
group::r--
group:g1:rw- #effective:r--
mask::r--
other::r--
當然這樣設完以后本旨上它改動的就是group位的權限
[23:47:02root@localhost data]# ll testfile
-rw-r--r--+ 1 root root 9 Mar 17 22:47 testfile
批量設置文件做還原備用
ACL大家在某些場景下用還是非常靈活的,至少比傳統權限要方便,功能更加豐富而且還有一個問題,我們在某些場景下,比方說有一個目錄里面有很多文件權限各不相同,有些應用需要把這目錄的文件臨時更改為777權限,這些文件被批量修改權限后需要撤銷回歸到原來的權限,傳統的文件管理的話我們得把每個權限記下來而且還要一個一個改回去,下面模擬這樣一個場景:
[00:37:42root@localhost data]#mkdir /data/dir
[00:37:50root@localhost data]#touch dir/f{1..10}
假設每個文件的權限各不一樣,懶得一個個改了= =
[00:38:23root@localhost data]#ll dir
total 0
-rw-r--r--. 1 root root 0 Mar 18 00:38 f1
-rw-r--r--. 1 root root 0 Mar 18 00:38 f10
-rw-r--r--. 1 root root 0 Mar 18 00:38 f2
-rw-r--r--. 1 root root 0 Mar 18 00:38 f3
-rw-r--r--. 1 root root 0 Mar 18 00:38 f4
-rw-r--r--. 1 root root 0 Mar 18 00:38 f5
-rw-r--r--. 1 root root 0 Mar 18 00:38 f6
-rw-r--r--. 1 root root 0 Mar 18 00:38 f7
-rw-r--r--. 1 root root 0 Mar 18 00:38 f8
-rw-r--r--. 1 root root 0 Mar 18 00:38 f9
如果一個應用需要把這些權限各不一樣的文件臨時的改為777,我們用chmod遞歸把該目錄的文件批量改的話后面要恢復就很麻煩,這時候ACL就用得着了,因為ACL也能用-R批量修改方式來設置權限,假設有個叫bin的服務賬號
[01:00:51root@localhost data]#setfacl -R -m u:bin:rwx dir
這樣設完以后bin這個服務就對這個目錄有了完全的控制權限
[01:01:13root@localhost data]#getfacl dir
# file: dir
# owner: root
# group: root
user::rwx
user:bin:rwx
group::r-x
mask::rwx
other::r-x
包括該目錄下的所有文件
[01:01:55root@localhost data]#getfacl dir/f1
# file: dir/f1
# owner: root
# group: root
user::rw-
user:bin:rwx
group::r--
mask::rwx
other::r--
當做完實驗或者做完配置了bin這個服務不用了,我們可以把可以把ACL屬性清除批量還原原來的文件屬性。
有+號代表有ACL屬性
[01:02:12root@localhost data]#ll dir/f1
-rw-rwxr--+ 1 root root 0 Mar 18 00:38 dir/f1
雖然可以使用-x參數刪除bin的權限,但是它的ACL屬性還存在。
[01:14:49root@localhost data]#setfacl -x u:bin dir/f1
[01:14:58root@localhost data]#getfacl dir/f1
# file: dir/f1
# owner: root
# group: root
user::rw-
group::r--
mask::r--
other::r--
注意它的加號還有,說明這種刪除它沒能完全清除上面的ACL屬性只是清除了特定的權限而已
[01:15:22root@localhost data]#ll dir/f1
-rw-r--r--+ 1 root root 0 Mar 18 00:38 dir/f1
徹底刪除上面的ACL屬性要使用-b選項,+消失了
[01:16:18root@localhost data]#setfacl -b dir/f1
[01:27:21root@localhost data]#ll dir/f1
-rw-r--r--. 1 root root 0 Mar 18 00:38 dir/f1
那有了這個-b我們就省事了,那我做完所有的操作了我想把這個權限回歸
[01:29:45root@localhost data]#setfacl -R -b dir/
[01:29:57root@localhost data]#ll dir/
total 0
-rw-r--r--. 1 root root 0 Mar 18 00:38 f1
-rw-r--r--. 1 root root 0 Mar 18 00:38 f10
-rw-r--r--. 1 root root 0 Mar 18 00:38 f2
-rw-r--r--. 1 root root 0 Mar 18 00:38 f3
-rw-r--r--. 1 root root 0 Mar 18 00:38 f4
-rw-r--r--. 1 root root 0 Mar 18 00:38 f5
-rw-r--r--. 1 root root 0 Mar 18 00:38 f6
-rw-r--r--. 1 root root 0 Mar 18 00:38 f7
-rw-r--r--. 1 root root 0 Mar 18 00:38 f8
-rw-r--r--. 1 root root 0 Mar 18 00:38 f9
備份和恢復ACL
主要的文件操作命令cp和mv都支持ACL,只是cp命令需要加上-p 參數。但是
tar等常見的備份工具是不會保留目錄和文件的ACL信息
- getfacl -R /tmp/dir1 > acl.txt
- setfacl -R -b /tmp/dir1
- setfacl -R --set-file=acl.txt /tmp/dir1
- setfacl --restore acl.txt
- getfacl -R /tmp/dir1