【问题标题】:Is it possible to create a script to save and restore permissions?是否可以创建脚本来保存和恢复权限?
【发布时间】:2011-03-27 21:18:03
【问题描述】:

我使用的是 linux 系统,需要对一组嵌套文件和目录进行一些权限试验。我想知道是否有某种方法可以保存文件和目录的权限,而不保存文件本身。

换句话说,我想保存权限,编辑一些文件,调整一些权限,然后将权限恢复到目录结构,保留更改的文件。

这有意义吗?

【问题讨论】:

    标签: linux permissions shell unix


    【解决方案1】:

    最简单的方法是使用 ACL 工具,即使您实际上不使用 ACL。只需调用getfacl -R . >saved-permissions 来备份目录树的权限,调用setfacl --restore=saved-permissions 来恢复它们。

    否则,备份权限的方法是使用find -printf。 (GNU find 是必需的,但这就是您在 Linux 上所拥有的。)

    find -depth -printf '%m:%u:%g:%p\0' >saved-permissions
    

    你得到一个文件,其中包含由空字符分隔的记录;每条记录包含一个文件的数字权限、用户名、组名和文件名。要恢复,循环记录并调用chmodchownfind-depth 选项是为了以防你想让某些目录不可写(你必须先处理它们的内容)。

    您可以使用此 bash sn-p 恢复权限,该 bash sn-p 源自 Daniel Alder 贡献的 sn-p:

    while IFS=: read -r -d '' mod user group file; do
      chown -- "$user:$group" "$file"
      chmod "$mod" "$file"
    done <saved-permissions
    

    您可以使用以下 awk 脚本将 find 输出转换为一些 shell 代码以恢复权限。

    find -depth -printf '%m:%u:%g:%p\0' |
    awk -v RS='\0' -F: '
    BEGIN {
        print "#!/bin/sh";
        print "set -e";
        q = "\047";
    }
    {
        gsub(q, q q "\\" q);
        f = $0;
        sub(/^[^:]*:[^:]*:[^:]*:/, "", f);
        print "chown --", q $2 ":" $3 q, q f q;
        print "chmod", $1, q f q;
    }' > restore-permissions.sh
    

    【讨论】:

    • 小修正getfacl命令应该是:getfacl -R。 >保存的权限
    • 这是解决方案的第二部分:恢复文件:while IFS=: read -r -d $'\0' mod user group file; do [ -e "$file" ] || continue;chmod -c "$mod" "$file";chown -Pc "$user" "$file";chgrp -Pc "$group" "$file";done &lt;saved-permissions
    • 最新的解决方案似乎坏了,因为它只是设法在此处处理.* 文件。我不打扰调试,因为基于 ACL 的方法工作得很好。只是标记....
    • @DanielAlder 我相信交换'chmod'和'chown'语句会更好,这样'chown'首先出现。这样,如果权限包括 SUID 和/或 SGID(例如,6755 而不仅仅是 755),则不会由 chown 重置。
    【解决方案2】:

    先安装ACL包:

    sudo apt-get install acl
    

    递归地存储权限和所有权到文件:

    getfacl -R yourDirectory > permissions.acl
    

    恢复(相对于当前路径):

    setfacl --restore=permissions.acl
    

    【讨论】:

      【解决方案3】:

      嗯。所以你需要 1)读取文件权限 2)以某种方式存储它们,与每个文件相关联 3)读取您存储的权限并将其设置回来

      不是一个完整的解决方案,而是一些想法:

      stat -c%a filename
      >644
      

      可能结合

      find -exec
      

      为了存储这些信息,this so question 有一些有趣的想法。基本上,您创建一个与实际文件匹配的临时文件结构,每个临时文件都包含文件权限

      重置您迭代临时文件、读取权限并将实际文件改回。

      【讨论】:

      • 我需要stat -f%p,FWIW
      【解决方案4】:

      还有一个特殊的工具叫做metastore

      metastore 是一种工具,用于将文件树中的文件/目录/链接的元数据存储到单独的文件中,然后比较存储的元数据并将其应用于所述文件树。我编写该工具作为 git 的补充,它不存储所有元数据,使其不适合例如将 /etc 存储在存储库中。如果您想创建文件树的 tarball 并确保“所有内容”(例如 xattrs、mtime、所有者、组)与文件一起存储,metastore 也可能会有所帮助。

      也可以使用Debian package

      【讨论】:

      【解决方案5】:

      保存: find . -type f |xargs ls -la| awk '{print "chmod "$1" "$NF}'&gt;./filesPermissions.sh

      恢复:sh ./filesPermissions.sh

      【讨论】:

      • 为什么这个答案不是最好的?
      【解决方案6】:

      我在https://github.com/robertknight/mandrawer/blob/master/save-file-attrs.py 有一个用于执行此操作的 Python 脚本

      save-file-attrs.py save

      将当前工作目录根目录树中文件的权限、模式和修改时间保存到本地文件(.saved-file-attrs),并且:

      save-file-attrs.py restore

      将从文件中恢复这些属性并显示更改。

      【讨论】:

        【解决方案7】:

        你可以通过

        获取文件的权限
        ls -l | awk '{print $1" "$NF}'
        

        这将返回文件名及其权限列表。 将其保存在某处,完成后 - 恢复 (chmod) 每个文件的权限。

        【讨论】:

          【解决方案8】:

          我发现 Dmytro L 的答案非常酷。但是,不幸的是,它不起作用,因为它会生成如下条目:

          chmod -rw-r--r-- ./.bashrc
          

          为了避免这种情况,我使用以下命令:

          find . -type f | xargs stat -c "%a %n" | awk '{print "chmod "$1" "$2}' > ./filesPermissions.sh
          

          基本上,它的作用相同,但会生成八进制条目,例如:

          chmod 644 ./.bashrc
          

          哪个有效。

          【讨论】:

          • 可能需要引用/转义文件名,否则会错误处理带有空格的名称
          【解决方案9】:

          这是一个使用单个文件轻松执行此操作的示例。不需要额外的工具、脚本、临时文件等。如果需要,您可以扩展此方法以处理更多文件。

          在此特定示例中,权限通过stat 命令保存在变量中。然后,该文件被暂时剥夺任何限制性权限。接下来,用它完成一些事情(由于之前的限制,这可能会失败)。终于恢复了原来的权限。

          file=$1
          saved_permissions=$(sudo stat -c %a $file)
          sudo chmod 777 $file
          # <DO SOMETHING HERE>
          sudo chmod $saved_permissions $file 
          

          【讨论】:

            【解决方案10】:

            我修改了 Anton 的命令以获取附加字符串 chown user:group /file_or_folder_path。现在您可以获得一个 bash 脚本,其中每个文件/文件夹包含两个字符串。

            命令:

            find . -type f | xargs stat -c "%a %U:%G %n" | awk '{print "chown "$2" "$3"\nchmod "$1" "$3}' > ./filesPermissions.sh
            

            输出示例:

            chown root:root /file_or_folder_path
            chmod 777 /file_or_folder_path
            

            【讨论】:

              【解决方案11】:
              #!/bin/bash
              
              if [ $# -ne 1 ]; then
                      echo "Enter directory";
                      exit 0;
              fi
              # dump acls
              cd $1
              >acl
              echo "#!/bin/bash">recovery_acl.sh
              echo "cd $1">>recovery_acl.sh
              f='./'
              # create acl file sorted by dir_level
              for i in `seq 0 15`;do
                find . -mindepth $i -maxdepth $i -type d -exec getfacl {} +|grep -E '*UTS|file:'>>acl
              done
              sed -i 's/default\:user/\-dm\ u/g' acl
              sed -i 's/default\:group/\-dm\ g/g' acl
              sed -i 's/user\:/\-m\ u\:/g' acl
              sed -i 's/group\:/\-m\ g\:/g' acl
              sed -i 's/\#\ file\:\ /\.\//g' acl
              sed -i '/^#/d' acl
              
              while IFS='' read -r line ; do
                # grep dir name
                if echo "$line" | grep -q "$f" ; then
                  dir="$line"
                  continue
                fi
                echo setfacl $line '"'$dir'"'>>recovery_acl.sh
                # grep non def acl (for files)
                if echo "$line" | grep -q '\-m' ; then
                  echo setfacl $line '"'$dir'"'/*>>recovery_acl.sh
                fi
              done < "acl"
              rm -f acl
              sed -i 's/134/\\/g' recovery_acl.sh
              sed -i 's/040/\ /g' recovery_acl.sh
              

              脚本执行后,将创建另一个“recovery_acl.sh”。 替换您域上的 UTS。 像“没有这样的文件或目录”这样的错误意味着目录是空的。

              【讨论】:

                【解决方案12】:

                我找到了最好的方法(对我来说)用 python 做到这一点!

                #!/usr/bin/env python3
                # -*- coding: utf-8 -*-
                import os
                import json
                import sys
                import re
                try:
                    import posix1e
                except ImportError:
                    print("No module named 'posix1e'")
                    print("You need do: apt install python3-pylibacl")
                    sys.exit()
                
                def dump_acl(dir):
                    acl_dict = {}
                    for root, dirs, files in os.walk(dir):
                        try:
                            path = root.split(os.sep)
                            root_acl = str(posix1e.ACL(file=root))
                            root_def_acl = str(posix1e.ACL(filedef=root))
                            #print(root_acl)
                            acl_dict[root] = root_acl
                            acl_dict["default_" + root] = root_def_acl
                            for file_name in files:
                                try:
                                    if 'acl.json' in file_name:
                                        continue
                                    file_path = root + "/" + file_name
                                    file_acl = str(posix1e.ACL(file=file_path))
                                    acl_dict[file_path] = file_acl
                                    #print(file_path)
                                except Exception as e:
                                    print(e)
                                    print(root, '/' + file_name)
                                    continue
                        except Exception as e:
                            print(e)
                            print(root, '/' + file_name)
                            continue
                
                    with open(dir + '/acl.json', 'bw') as f:
                        f.write(json.dumps(acl_dict, ensure_ascii=False).encode('utf8'))
                    return
                
                
                def recovery_acl(dir):
                    with open(dir + '/acl.json', 'r') as f:
                        acl_dict = json.load(f)
                    try:
                        for file_path, file_acl in acl_dict.items():
                            if file_path.startswith('default_'):
                                file_path = file_path.replace('default_', '', 1)
                                posix1e.ACL(text = file_acl).applyto(file_path, posix1e.ACL_TYPE_DEFAULT)
                                continue
                            if 'acl.json' in file_path:
                                continue
                            file_acl = file_acl.replace('\n', ',', file_acl.count('\n') -1)
                            file_acl = file_acl.replace('\134', u'\ ' [:-1])
                            file_acl = file_acl.replace('\040', u' ')
                            if 'effective' in file_acl:
                                file_acl = file_acl.replace('\t', '')
                                f_acl = re.sub('#effective:[r,w,x,-]{3}', '', file_acl)
                            posix1e.ACL(text = file_acl).applyto(file_path)
                    except Exception as e:
                        print(e, file_path, file_acl)
                    return
                
                def help_usage():
                    print("Usage:")
                    print("For dump acl:   ", sys.argv[0], "-d /path/to/dir")
                    print("For restore acl:", sys.argv[0], "-r /path/to/dir")
                    print("File with acls (acl.json) storing in the same dir")
                    sys.exit()
                
                
                if len(sys.argv) == 3 and os.path.isdir(sys.argv[2]):
                    if sys.argv[1] == '-d':
                        dump_acl(sys.argv[2])
                    elif sys.argv[1] == '-r':
                        if os.path.exists(sys.argv[2] + '/acl.json'):
                            recovery_acl(sys.argv[2])
                        else:
                            print("File not found:", sys.argv[2] + '/acl.json')
                else:
                    help_usage()
                

                备份acl:dump_acl.py -d /path/to/dir

                恢复acl:dump_acl.py -r /path/to/dir

                执行后,脚本在同一个目录下创建acl.json(witch backup/restore acls)

                【讨论】:

                  【解决方案13】:

                  我从roaima's post借用这个答案。
                  我认为这应该是最好的答案:
                  保存权限

                  find * -depth -exec stat --format '%a %u %g %n' {} + >/tmp/save-the-list
                  

                  恢复权限

                  while read PERMS OWNER GROUP FILE
                  do
                      chmod "$PERMS" "$FILE"
                      chown "${OWNER}:${GROUP}" "$FILE"
                  done </tmp/save-the-list
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-06-16
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多