我想将所有 ZFS ACL 从一个文件克隆到另一个文件。
getfacl
使用 POSIX ACL 可以通过将的输出通过管道传输到 来实现setfacl
。
有没有一种简单快捷的方法可以使用 ZFS 中的 NFSv4 样式 ACL 来执行此操作?我知道我可以读取的输出ls -lV
,然后将其作为 的一部分输入chmod
,但我似乎找不到与 POSIX 复制 ACL 的方式功能等效的方法。
答案1
除了使用之外,ls -lV
您还可以使用ls -lv
可以输入到脚本中的chmod
命令序列来复制 ACL。
例如,如果 ACl 如下所示:
$ ls -lv file1
0:owner@::deny
1:owner@:read_data/write_data/append_data/write_xattr/execute
/write_attributes/write_acl/write_owner:allow
2:group@:read_data/write_data/append_data:deny
3:group@:execute:allow
4:everyone@:read_data/write_data/append_data/write_xattr
/write_attributes/write_acl/write_owner:deny
5:everyone@:read_xattr/execute/read_attributes/read_acl/synchronize:allow
它应该转换为以下chmod
命令序列:
chmod A0=owner@::deny file2
chmod A1=owner@:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:allow file2
chmod A2=group@:read_data/write_data/append_data:deny file2
chmod A3=group@:execute:allow file2
chmod A4=everyone@:read_data/write_data/append_data/write_xattr/write_attributes/write_acl/write_owner:deny file2
chmod A5=everyone@:read_xattr/execute/read_attributes/read_acl/synchronize:allow file2
我最近发现自己处于一种需要使用上述脚本的情况,因此我制作了一个小型 Bash 脚本(也可以将其作为源放到 shell 中并作为函数运行)来打印将 ZFS ACL 从一个文件复制到另一个文件所需的 chmod 命令列表:
/bin/bash #!/bin/bash acl_as_chmods(){ # 打印 chmod 命令列表以将 ACL 条目从“$1”复制到“$2” [[ -a "$1" ]] 2>/dev/null || { echo "需要有效的参考文件。" >&2 返回 1 } ls -vd“$1”| { 读取#第一行不是ACL信息;绕过 读取 ACL_entry echo -n "chmod A=${ACL_entry#*:}" # 如果没有将目标文件指定为“$2”,则在运行时使用“TARGET”变量 当读取 ACL_entry || { echo " ${2-\$TARGET}"; false; } 做 [[ "$ACL_entry" == [0-9]*:* ]] && \ echo -en“ ${2-\$TARGET}\nchmod A${ACL_entry%%:*}+${ACL_entry#*:}”|| \ 回显-n“$ACL_entry” 完毕 } } ## 作为脚本或源函数运行到 shell 中? __acl_as_chmods(){ [[ "${FUNCNAME[1]}" == "源" ]] || acl_as_chmods "$@" } __acl_as_chmods“$@”
以下是几个示例用法及其输出文件1从上面:
~$ ./acl_as_chmods.sh 文件1 文件2 chmod A=owner@::deny file2 chmod A1 + 所有者 @:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:允许文件 2 chmod A2 + group @:read_data / write_data / append_data:拒绝文件2 chmod A3 + group @:execute:allow file2 chmod A4 + everyone @:read_data / write_data / append_data / write_xattr / write_attributes / write_acl / write_owner:拒绝文件2 chmod A5 + everyone @:read_xattr / execute / read_attributes / read_acl / synchronize:allow file2 ~$ 源 acl_as_chmods.sh ~$ acl_as_chmods 文件1 chmod A=owner@::deny $TARGET chmod A1 + 所有者 @:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:允许 $TARGET chmod A2 + group @:读取数据/写入数据/附加数据:拒绝$ TARGET chmod A3 + group @:execute:允许$TARGET chmod A4 + everyone @:read_data / write_data / append_data / write_xattr / write_attributes / write_acl / write_owner:拒绝$ TARGET chmod A5 + everyone @:read_xattr / execute / read_attributes / read_acl / synchronize:允许$ TARGET
如果我们愿意,我们甚至可以直接评估这些 chmod,如果这两个文件都可以在此主机上访问,并且我们希望从中复制 ACL文件1到文件2立即地:
~$ ls -Vd 文件* #之前 -rwx--x--x 1 用户 user 0 6月 19 04:12 file1 所有者@:--------------:------:deny 所有者@:rwxp---AW-Co-:------:allow 组@:rw-p----------:------:deny 组@:--x-----------:------:允许 每个人@:rw-p---AW-Co-:------:deny 每个人@:--x---aRc--s:------:allow ---x------+ 1 用户 user 0 6月 19 04:12 file2 所有者@:--x-----------:------:allow ~$ eval "$(acl_as_chmods 文件1 文件2)" ~$ ls -Vd 文件* #之后 -rwx--x--x 1 用户 user 0 6月 19 04:12 file1 所有者@:--------------:------:deny 所有者@:rwxp---AW-Co-:------:allow 组@:rw-p----------:------:deny 组@:--x-----------:------:允许 每个人@:rw-p---AW-Co-:------:deny 每个人@:--x---aRc--s:------:allow -rwx--x--x 1 用户 user 0 6月 19 04:12 file2 所有者@:--------------:------:deny 所有者@:rwxp---AW-Co-:------:allow 组@:rw-p----------:------:deny 组@:--x-----------:------:允许 每个人@:rw-p---AW-Co-:------:deny 每个人@:--x---aRc--s:------:allow
答案2
答案3
服用什么马丁建议并应用一点 perl 你可能会得到类似的东西:
#!/usr/bin/perl
use warnings;
use strict;
my $state = 0;
if ($#ARGV < 1 || $#ARGV > 2) {
print "\n\tUsage: $0 srcFile destFile\n";
}
my $acl=`ls -lv "${ARGV[0]}"`;
my @out="chmod", "arg", $ARGV[1];
foreach my $line ($acl) {
chomp $line;
if ($line =~ m/^\s+(\d+):(.*)$/) {
if ($state > 0) {
print join(" ",@out)."\n";
#system(@out) or die "system @args failed: $?";
}
$state = 1;
$out[1] = "A$1=$2";
} else {
$line =~ m/^\s+(.*)$/;
$state = 2;
$out[1] .= $1;
}
}
if ($state > 0) {
print join(" ",@out)."\n";
#system(@out) or die "system @args failed: $?";
}
在取消注释系统(@out)行之前尝试一下。
答案4
令人恼火的是,这似乎没有在 shell 级别正确公开。在 C 中,有函数acl_get(3SEC)
和acl_set(3SEC)
可用于从一个文件中获取 ACL 并将其应用于另一个文件(显然还有其他选项)。它们还可以将 ACL 从 POSIX 草案转换为 NFSv4 类型;这就是系统命令喜欢mv
和cp
使用的。
我曾经写过一个命令,使用这种技术将 acl 从源复制到目标文件,但目前找不到源代码。如果我找到它,我会将其附加到这个答案中。