我最近在 FreeBSD 上遇到了这个问题,但感谢上帝 ZFS 帮我解决了这个问题。然而,我在带有 ext4 的 CentOS 中再次遇到了它,不知道是否有一个简单的方法可以绕过它(或任何绕过它的方法)。我想要的是一个目录,其中某个组中的任何用户都可以保证对文件的读/写访问权限,无论用户无能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和mask 都指定rwx
formygroup
但文件权限胜过它并导致---
.不幸的是,这意味着如果用户的 FTP 客户端(例如)将文件上传为 640,组中的其他人将无法干扰它。有没有解决的办法?
答案1
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";
}