是否可以创建脚本来保存和恢复权限?
Posted
技术标签:
【中文标题】是否可以创建脚本来保存和恢复权限?【英文标题】:Is it possible to create a script to save and restore permissions? 【发布时间】:2011-03-27 21:18:03 【问题描述】:我使用的是 linux 系统,需要对一组嵌套文件和目录进行一些权限试验。我想知道是否有某种方法可以保存文件和目录的权限,而不保存文件本身。
换句话说,我想保存权限,编辑一些文件,调整一些权限,然后将权限恢复到目录结构,保留更改的文件。
这有意义吗?
【问题讨论】:
【参考方案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
你得到一个文件,其中包含由空字符分隔的记录;每条记录包含一个文件的数字权限、用户名、组名和文件名。要恢复,循环记录并调用chmod
和chown
。 find
的 -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 <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。
【讨论】:
metastore 已失效的 Git 存储库已镜像到 GitHub 上 github.com/przemoc/metastore【参考方案5】:保存: find . -type f |xargs ls -la| awk 'print "chmod "$1" "$NF'>./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
【讨论】:
以上是关于是否可以创建脚本来保存和恢复权限?的主要内容,如果未能解决你的问题,请参考以下文章