Назад | Перейти на главную страницу

Как клонировать ACL ZFS из одного файла в другой?

Я хотел бы клонировать все 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 из исходного файла в целевой, используя эту технику, но в настоящее время я не могу найти исходный код. Если найду, добавлю к этому ответу.