すべての ZFS ACL を 1 つのファイルから別のファイルに複製したいと思います。
getfacl
POSIX ACL では、の出力を にパイプすることでこれを実行できますsetfacl
。
ZFS の NFSv4 スタイルの ACL を使用して、これを簡単かつ迅速に実行する方法はありますか? の出力を読み取ってls -lV
、それを の一部として入力できることchmod
はわかっていますが、ACL をコピーする POSIX の方法と機能的に同等なものが見つからないようです。
答え1
を使用する代わりに、スクリプトに入力してACL を複製する一連のコマンドに変換することがls -lV
できます。ls -lv
chmod
たとえば、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
最近、上記のようなスクリプトが役に立つ状況に遭遇したので、ZFS ACL をあるファイルから別のファイルにコピーするために必要な chmod コマンドのリストを出力する、私が作成した小さな Bash スクリプト (シェルにソースして関数として実行することもできます) を以下に示します。
#!/bin/bash acl_as_chmods() { # ACL エントリを '$1' から '$2' にコピーする chmod コマンドのリストを出力します [[ -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#*:}" || \ echo -n "$ACL_entry" 終わり } } ## スクリプトとして実行するか、シェルに関数をソースしますか? __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: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 ~$ ソース acl_as_chmods.sh ~$ acl_as_chmods ファイル1 chmod A=owner@::deny $TARGET chmod A1+owner@:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:allow $TARGET chmod A2+group@:read_data/write_data/append_data:deny $TARGET chmod A3+group@:execute:allow $TARGET chmod A4+everyone@:read_data/write_data/append_data/write_xattr/write_attributes/write_acl/write_owner:deny $TARGET chmod A5+everyone@:read_xattr/execute/read_attributes/read_acl/synchronize:allow $TARGET
両方のファイルがこのホスト上でアクセス可能で、ACLをコピーしたい場合は、これらのchmodを直接評価することもできます。ファイル1にファイル2すぐに:
~$ ls -Vd ファイル* #BEFORE -rwx--x--x 1 ユーザー ユーザー 0 6月19日 04:12 ファイル1 所有者@:--------------:------:拒否 所有者@:rwxp---AW-Co-:------:allow グループ@:rw-p----------:------:拒否 グループ@:--x-----------:------:許可 みんな@:rw-p---AW-Co-:------:拒否 みんな@:--x---aRc--s:------:許可 ---x------+ 1 ユーザー ユーザー 0 6月19日 04:12 ファイル2 所有者@:--x-----------:------:許可 ~$ eval "$(acl_as_chmods ファイル1 ファイル2)" ~$ ls -Vd ファイル* #後 -rwx--x--x 1 ユーザー ユーザー 0 6月19日 04:12 ファイル1 所有者@:--------------:------:拒否 所有者@:rwxp---AW-Co-:------:allow グループ@:rw-p----------:------:拒否 グループ@:--x-----------:------:許可 みんな@:rw-p---AW-Co-:------:拒否 みんな@:--x---aRc--s:------:許可 -rwx--x--x 1 ユーザー ユーザー 0 6月19日 04:12 ファイル2 所有者@:--------------:------:拒否 所有者@:rwxp---AW-Co-:------:allow グループ@:rw-p----------:------:拒否 グループ@:--x-----------:------:許可 みんな@:rw-p---AW-Co-:------:拒否 みんな@:--x---aRc--s:------:許可
答え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: $?";
}
system(@out) 行のコメントを解除する前に試してください。
答え4
残念なことに、これはシェル レベルでは適切に公開されていないようです。C には、あるファイルから ACL を取得して別のファイルに適用するために使用できる関数とがありますacl_get(3SEC)
(acl_set(3SEC)
もちろん、他のオプションもあります)。また、便利なことに、これらの関数は ACL を POSIX ドラフトから NFSv4 タイプに変換します。これは、システム コマンドが好んmv
でcp
使用するものです。
かつて、この手法を使用して、ソース ファイルから宛先ファイルに ACL をコピーするコマンドを作成しましたが、現在ソース コードが見つかりません。見つかったら、この回答に追加します。