如何將 ZFS ACL 從一個檔案克隆到另一個檔案?

如何將 ZFS ACL 從一個檔案克隆到另一個檔案?

我想將所有 ZFS ACL 從一個檔案克隆到另一個檔案。

對於 POSIX ACL,這可以透過管道輸出getfaclto來完成setfacl

是否有一種簡單快速的方法可以使用 ZFS 中的 NFSv4 樣式 ACL 來執行此操作?我知道我可以讀取 的輸出ls -lV,然後將其作為 a 的一部分輸入chmod,但我似乎找不到與複製 ACL 的 POSIX 方式等效的功能。

答案1

ls -lV您可以使用which來代替使用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 並作為函數運行)來打印必要的 chmod 命令列表將ZFS ACL從一個文件複製到另一個文件:

#!/bin/bash

acl_as_chmods () {
# 列印 chmod 指令列表,將 ACL 條目從“$1”複製到“$2”
 [[ -a "$1" ]] 2>/dev/null || {
   echo“需要有效的參考文件。” >&2
   返回1
 }
 ls -vd“$1”| {
   read #第一行不是ACL訊息;旁路
   讀取 ACL_entry
     echo -n "chmod A=${ACL_entry#*:}"
   # 如果沒有將目標檔案指定為“$2”,則在執行時使用“TARGET”變量
   讀取 ACL_entry || 時{ echo " ${2-\$TARGET}";錯誤的; }
     [[ "$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=所有者@::拒絕檔案2
chmod A1+owner@: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:拒絕 file2
chmod A3+group@:執行:允許檔案2
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:允許 file2

~$ 源 acl_as_chmods.sh
~$ acl_as_chmods file1
chmod A=所有者@::拒絕$TARGET
chmod A1+owner@:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:允許$TARGET
chmod A2+group@:read_data/write_data/append_data:拒絕$TARGET
chmod A3+group@:執行:允許$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 Jun 19 04:12 file1
            所有者@:--------------:------:拒絕
            所有者@:rwxp---AW-Co-:------:允許
            組@:rw-p----------:------:拒絕
            組@:--x----------:------:允許
         大家@:rw-p---AW-Co-:-------:否認
         大家@:--x---aRc--s:------:允許
---x------+ 1 用戶 用戶 0 六月 19 04:12 file2
            所有者@:--x----------:------:允許

~$ eval "$(acl_as_chmods file1 file2)"

~$ ls -Vd 檔案* #之後
-rwx--x--x 1 個使用者 user 0 Jun 19 04:12 file1
            所有者@:--------------:------:拒絕
            所有者@:rwxp---AW-Co-:------:允許
            組@:rw-p----------:------:拒絕
            組@:--x----------:------:允許
         大家@:rw-p---AW-Co-:-------:否認
         大家@:--x---aRc--s:------:允許
-rwx--x--x 1 個使用者 user 0 Jun 19 04:12 file2
            所有者@:--------------:------:拒絕
            所有者@:rwxp---AW-Co-:------:允許
            組@:rw-p----------:------:拒絕
            組@:--x----------:------:允許
         大家@:rw-p---AW-Co-:-------:否認
         大家@:--x---aRc--s:------:允許

答案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: $?";
}

在取消註解 system(@out) 行之前嘗試一下。

答案4

令人煩惱的是,這似乎沒有在 shell 層級正確暴露。在 C 中,有一些函數acl_get(3SEC)acl_set(3SEC)可用於從一個檔案中取得 ACL 並將其套用到另一個檔案(顯然還有其他選項)。他們也可以有效地將 ACL 從 POSIX 草稿轉換為 NFSv4 類型;這就是系統指令喜歡mvcp使用的。

我曾經編寫過一個命令,使用這種技術將 acl 從原始文件複製到目標文件,但我目前找不到原始程式碼。如果我找到它,我會將其附加到這個答案中。

相關內容