Linux
ACL 可以覆蓋 Linux 上的文件權限嗎?
我最近在 FreeBSD 上遇到了這個問題,但感謝上帝 ZFS 在那里為我解決了這個問題。但是我在 CentOS 中再次使用 ext4 並且不知道是否有一種簡單的方法(或任何方法)。我想要的是一個目錄,在這個目錄中,某個組中的任何使用者都保證了對文件的讀/寫訪問權限,而不管使用者的無能
umask
、糟糕的 FTP 客戶端上傳決定等。我認為這是不可能的,但我’想錯了。看起來不可能的原因是 ext4 ACL 不能覆蓋文件權限,只能與它們相交。例如:# mkdir bar # chmod 700 bar # getfacl bar # file: bar # owner: root # group: mygroup # flags: -s- user::rwx group::rwx #effective:--- group:mygroup:rwx #effective:--- mask::--- other::--- default:user::rwx default:group::rwx default:group:mygroup:rwx default:mask::rwx default:other::---
您可以看到預設的 ACL和遮罩都指定
rwx
為,mygroup
但文件權限勝過它並導致---
. 不幸的是,這意味著如果使用者的 FTP 客戶端(例如)將文件上傳為 640,組中的其他人將無法處理它。有沒有解決的辦法?
ACL 授予的權限是附加的,但也許您希望它們是遞歸的?(他們不是)
您幾乎可以使用 ACL 獲得所需的內容。您需要首先在樹中的每個文件和目錄上**遞歸地設置 ACL,就像上面一樣。**請務必
default:group:mygroup:rwx
在目錄中包含設置。現在,任何新目錄都將自動應用這些設置,並且這些目錄中的新文件也是如此。有兩次仍然失敗:
- 當有人從樹外移動文件或目錄時。由於 inode 已經存在,它不會獲得其上設置的預設值。
- 當有人使用覆蓋預設值的 ACL 感知程序從存檔中提取文件時。
除了編寫一個 cron 作業來定期執行之外,我不知道有什麼方法可以處理這兩個
chgrp -R mygroup DIRECTORY; chmod g+rwx -R DIRECTORY
。根據共享目錄中的文件數量,這可能可行,也可能不可行。這是我用來修復文件樹上的 ACL 的腳本的略微修改版本。它使用特定的讀寫組和只讀組列表完全覆蓋樹中任何內容上的任何 ACL。
#! /usr/bin/env perl use strict; use warnings; use String::ShellQuote; use Cwd 'abs_path'; # Usage: fix-permissions.pl DIRECTORY RW_GROUP1,RW_GROUP2... RO_GROUP1,RO_GROUP2... my $dir= $ARGV[0]; my @rw_groups= split ',', $ARGV[1] if $ARGV[1]; my @ro_groups= split ',', $ARGV[2] if $ARGV[2]; -d $dir or die "No such directory'$dir'\n"; $dir= abs_path($dir); $dir =~ m|/[^/]+/| or die "Cowardly refusing to run on a top-level directory: $dir\n"; # Give all files rw-r----- and all directories rwxr-x--- # then give each rw_group read/write access, then each ro_group # read-only access to the whole tree my $dir_perm= join(',', 'u::rwx', 'g::r-x', 'o::---', 'd:u::rwx', 'd:g::r-x', 'd:o::---', ( map { "g:$_:rwx" } @rw_groups ), ( map { "d:g:$_:rwx" } @rw_groups ), ( map { "g:$_:r-x" } @ro_groups ), ( map { "d:g:$_:r-x" } @ro_groups ) ); my $file_perm= join(',', 'u::rwx', 'g::r-x', 'o::---', ( map { "g:$_:rw-" } @rw_groups ), ( map { "g:$_:r--" } @ro_groups ) ); for ( "find ".shell_quote($dir)." -type d -print0 | xargs -0 -r setfacl --set ".shell_quote($dir_perm), "find ".shell_quote($dir)." ! -type d -print0 | xargs -0 -r setfacl --set ".shell_quote($file_perm) ) { 0 == system($_) or die "command failed: $_\n"; }