如何将 ZFS ACL 从一个文件克隆到另一个文件?

如何将 ZFS ACL 从一个文件克隆到另一个文件?

我想将所有 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

我遇到了同样的问题。我的代码在这里:

https://gist.github.com/1021032

对我来说非常有效。希望如果有人遇到这个问题,它能派上用场。

答案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 类型;这就是系统命令喜欢mvcp使用的。

我曾经写过一个命令,使用这种技术将 acl 从源复制到目标文件,但目前找不到源代码。如果我找到它,我会将其附加到这个答案中。

相关内容