Я хотел бы клонировать все ACL ZFS из одного файла в другой.
С помощью списков ACL POSIX это можно сделать, связав вывод getfacl
к setfacl
.
Есть ли простой и быстрый способ сделать это с помощью ACL в стиле NFSv4 в ZFS? Я знаю, что могу прочитать вывод ls -lV
а затем введите его как часть chmod
, но я не могу найти функциональный эквивалент POSIX-способу копирования списков ACL.
Вместо того, чтобы использовать 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, который я сделал (также можно передать в оболочку и запустить как функцию), чтобы распечатать список необходимых команд chmod чтобы скопировать ACL ZFS из одного файла в другой:
#!/bin/bash acl_as_chmods () { # print list of chmod commands to copy the ACL entries from '$1' to '$2' [[ -a "$1" ]] 2>/dev/null || { echo "Valid reference file required." >&2 return 1 } ls -vd "$1" | { read # first line is not ACL information; bypass read ACL_entry echo -n "chmod A=${ACL_entry#*:}" # if no target file was specified as '$2', use 'TARGET' variable at runtime while read ACL_entry || { echo " ${2-\$TARGET}"; false; } do [[ "$ACL_entry" == [0-9]*:* ]] && \ echo -en " ${2-\$TARGET}\nchmod A${ACL_entry%%:*}+${ACL_entry#*:}" || \ echo -n "$ACL_entry" done } } ## run as script or source function to shell? __acl_as_chmods () { [[ "${FUNCNAME[1]}" == "source" ]] || acl_as_chmods "$@" } __acl_as_chmods "$@"
Вот пара примеров использования и их вывод для file1 сверху:
~$ ./acl_as_chmods.sh file1 file2 chmod A=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 ~$ source acl_as_chmods.sh ~$ acl_as_chmods file1 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
При желании мы даже можем оценить эти chmods напрямую, если оба файла доступны на этом хосте и мы хотим скопировать ACL из file1 к файл2 немедленно:
~$ ls -Vd file* #BEFORE -rwx--x--x 1 user user 0 Jun 19 04:12 file1 owner@:--------------:------:deny owner@:rwxp---A-W-Co-:------:allow group@:rw-p----------:------:deny group@:--x-----------:------:allow everyone@:rw-p---A-W-Co-:------:deny everyone@:--x---a-R-c--s:------:allow ---x------+ 1 user user 0 Jun 19 04:12 file2 owner@:--x-----------:------:allow ~$ eval "$(acl_as_chmods file1 file2)" ~$ ls -Vd file* #AFTER -rwx--x--x 1 user user 0 Jun 19 04:12 file1 owner@:--------------:------:deny owner@:rwxp---A-W-Co-:------:allow group@:rw-p----------:------:deny group@:--x-----------:------:allow everyone@:rw-p---A-W-Co-:------:deny everyone@:--x---a-R-c--s:------:allow -rwx--x--x 1 user user 0 Jun 19 04:12 file2 owner@:--------------:------:deny owner@:rwxp---A-W-Co-:------:allow group@:rw-p----------:------:deny group@:--x-----------:------:allow everyone@:rw-p---A-W-Co-:------:deny everyone@:--x---a-R-c--s:------:allow
Я столкнулся с этой же проблемой. Мой код здесь:
https://gist.github.com/1021032
Для меня работает как оберег. Надеюсь, это удобно, если кто-нибудь еще когда-нибудь столкнется с этой проблемой.
Принимая что Мартин предлагает и применив немного 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) строки.
Досадно, что это не отображается должным образом на уровне оболочки. В C есть функции acl_get(3SEC)
и acl_set(3SEC)
который можно использовать, чтобы взять ACL из одного файла и применить его к другому (очевидно, среди других опций). Кроме того, они будут, с пользой, переводить ACL из проекта POSIX в тип NFSv4; это то, что любят системные команды mv
и cp
использовать.
Одно время я написал команду для копирования ACL из исходного файла в целевой, используя эту технику, но в настоящее время я не могу найти исходный код. Если найду, добавлю к этому ответу.