Linux ext4 在错误备份/恢复后恢复文件和目录访问权限

Linux ext4 在错误备份/恢复后恢复文件和目录访问权限

我搞砸了我的个人目录的备份rsync(可能是因为我在 NTFS 文件系统上备份):所有文件都在这里,但所有文件和目录的访问权限都是 777。我想知道是否有魔法会递归改变的实用程序:

  • 从 777 到 755 的目录。
  • 常规文件从 777 到 644。我家里没有很多可执行文件,所以我可以稍后手动管理。
  • 保持其他文件(链接,其他任何东西?)不变。

在 shell 中执行此操作很容易,但需要花费几个小时......

rsync辅助问题:有没有什么建议可以在 NTFS(或其他)上正确备份 Linux 目录层次结构。

答案1

标准推荐的解决方案很简单:

find . -type d -exec chmod 0755 "{}" \+
find . -type f -exec chmod 0644 "{}" \+

这会将尽可能多的文件名作为参数附加到单个命令,直至达到系统的最大命令行长度。如果命令行超出此长度,则将多次调用该命令。

如果您想要对每个文件调用一次命令,您可以这样做:

find . -type d -exec chmod 0755 "{}" \;
find . -type f -exec chmod 0644 "{}" \;

答案2

chmod -R a=,u+rwX,go+rX $DIR似乎运行良好,而且很可能是最快的,无论你怎么看它。

(我检查过strace,它只 fchmodat()每个文件/目录的系统调用 - 对于文件为 644 和目录为 755)。

诀窍在于X记录中的权限man chmod,其作用类似于x仅针对目录 - 这正是您想要的区别。

什么是不是记录显示我猜测它们会按照指定的顺序应用,而不是按照随机顺序,但对几种变体进行的重复测试使我相信它们确实按照给定的顺序运行,所以我很确定它会一直像这样工作。

我应该提到这是在 Linux 上,尽管粗略阅读 BSD 手册页的 chmod 表明它应该也在那里工作。

答案3

我进行了基准测试sitam 的回答Peter Cordes 的评论Fanatique 的回答, 和harrymc 的回答, 但这个答案有最快的方法

平均值:

  • Deltik 的回答* – 7.480 秒
    * 归功于彼得·科德斯为了暗示平行
  • sitaram 的答案 – 12.962 秒(比最佳答案慢 73.275%)
  • Peter Cordes 的评论 – 14.414 秒(比最佳成绩慢 92.685%)
  • Fanatique 的答案——14.570 秒(比最佳答案慢 94.772%)
  • harrymc 的更新答案 – 14.791 秒(比最佳答案慢 97.730%)
  • harrymc 的原始答案 – 1061.926 秒(比最佳答案慢 14096.113%)

完整统计摘要:

Author              N      min     q1      median  q3      max     mean    stddev
------------------  --     ------- ------- ------- ------- ------- ------- --------
Deltik              10     7.121   7.3585  7.4615  7.558   8.005   7.4804  0.248965
sitaram             10     12.651  12.803  12.943  13.0685 13.586  12.9617 0.276589
Peter Cordes        10     14.096  14.2875 14.375  14.4495 15.101  14.4136 0.269732
Fanatique           10     14.219  14.512  14.5615 14.6525 14.892  14.5697 0.211788
harrymc (updated)   10     14.38   14.677  14.8595 14.9025 15.119  14.791  0.21817
harrymc (original)  1      1061.93 1061.93 1061.93 1061.93 1061.93 1061.93 N/A

Deltik 的命令(采用基准格式):

查找“$(pwd)”-type d-print0|xargs-0-P4 chmod 755&\
找到“$(pwd)”-type f -print0 | xargs -0 -P4 chmod 644并等待

sitam 的命令,采用基准格式:

chmod -R a=,u+rwX,go+rX "$(pwd)"

Peter Cordes 的命令(采用基准格式):

找到“$(pwd)” \(-type d -exec chmod 755 {} + \)\
           -o \(-type f-exec chmod 644 {} + \)

Fanatique 的命令(采用基准格式):

查找“$(pwd)”-type d -print0 | xargs -0 chmod 755 ; \
查找“$(pwd)”-type f -print0 | xargs -0 chmod 644

harrymc 的更新命令,采用基准格式:

查找“$(pwd)”-type d-exec chmod 755 {} + ; \
查找“$(pwd)”-type f-exec chmod 644 {} +

harrymc 的原始命令,采用基准格式:

找到“$(pwd)”-type d-exec chmod 755 {} \; ; \
找到“$(pwd)”-type f-exec chmod 644 {} \;

由于chmod每个文件类型有四个并行进程,我的命令是最快的。这允许多个 CPU 核心运行chmod,从而将瓶颈转移到内核 I/O 线程或磁盘。

sitaram 的命令位居第二,因为所有操作都在chmod命令中完成。与其他答案相比,这大大减少了开销,因为:

  • 这些文件只需扫描一次(类似于只扫描一次find而不是两次),并且
  • 不需要创建子进程。

但是,这个命令是最不灵活的,因为它依赖于涉及常规文件和目录之间可执行位的不同含义的技巧。

Peter Cordes 的评论使用一个find命令来防止目录条目的重复查找。文件越多,这种改进就越明显。它仍然有创建子进程的开销,这就是为什么它比-only 解决方案chmod慢很多的原因。chmod

在 Fanatique 的命令和 harrymc 的更新命令之间,find通过管道传输到xargs( find | xargs) 的速度更快,因为结果流是异步处理的。找到的结果被发送到 进行并发处理,而不是find暂停其查找行为。 (空字节分隔符 ( ) 似乎不影响运行时间。)-execxargs
find -print0 | xargs -0

harrymc 的原始命令太慢,因为chmod每个文件和文件夹都需要一个新命令,并且每个命令都按顺序执行。


在测试设置中,1001 个目录中包含 1000002 个常规文件:

root@demo:~# echo {0..999} | xargs mkdir -p
root@demo:~# find -type d -exec bash -c "cd {}; echo {0..999} | xargs touch" \;
root@demo:~# find | wc -l
1001003
root@demo:~# find -type d | wc -l
1001
root@demo:~# find -type f | wc -l
1000002

我将所有文件和文件夹设置为具有777权限,就像问题的初始条件一样。

777然后,我对这些命令进行了十次基准测试,每次都在chmod -R 0777 "$(pwd)"运行测试之前将权限恢复为。

通过OUTPUT表示包含每个基准测试命令输出的文件,我使用以下方法计算平均时间:

bc <<< "scale=3; ($(grep real OUTPUT | grep -Po '(?<=m).*(?=s)' | xargs | sed 's/ /+/g'))/10"

Deltik 答案的基准测试结果

root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; 时间 { find "$(pwd)" -type d -print0 | xargs -0 -P4 chmod 755 & find "$(pwd)" -type f -print0 | xargs -0 -P4 chmod 644 & 等待 ; } ; 完成
[1] 9791
[2] 9793
[1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755
[2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644

实际 0分7.634秒
用户 0分2.536秒
系统 0分23.384秒
[1] 9906
[2] 9908
[1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755
[2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644

实际 0分7.443秒
用户 0分2.636秒
系统 0分23.106秒
[1] 10021
[2] 10023
[1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755
[2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644

实际 0分8.005秒
用户 0分2.672秒
系统 0m24.557s
[1] 10136
[2] 10138
[1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755
[2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644

实际 0 分 7.480 秒
用户 0分2.541秒
系统 0分23.699秒
[1] 10251
[2] 10253
[1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755
[2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644

实际 0分7.397秒
用户 0分2.558秒
系统 0分23.583秒
[1] 10366
[2] 10368
[1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755
[2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644

实际 0分7.482秒
用户 0分2.601秒
系统 0m23.728s
[1] 10481
[2] 10483
[1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755
[2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644

实际 0分7.679秒
用户 0分2.749秒
系统 0分23.395秒
[1] 10596
[2] 10598
[1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755
[2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644

实际 0分7.243秒
用户 0分2.583秒
系统 0 分 23.400 秒
[1] 10729
[2] 10731
[1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755
[2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644

实际 0 分 7.320 秒
用户 0分2.640秒
系统 0分23.403秒
[1] 10844
[2] 10847
[1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755
[2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644

实际 0 分 7.121 秒
用户 0分2.490秒
系统 0分22.943秒

平均时间:7.480秒

sitam 答案的基准测试结果

root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time chmod -R a=,u+rwX,go+rX "$(pwd)" ; done

真实 0分12.860秒
用户 0分0.940秒
系统 0分11.725秒

实际 0分13.059秒
用户 0分0.896秒
系统 0分11.937秒

实际 0分12.819秒
用户 0分0.945秒
系统 0分11.706秒

实际 0分13.078秒
用户 0分0.855秒
系统 0 分 12.000 秒

实际 0分12.653秒
用户 0分0.856秒
系统 0分11.667秒

实际 0分12.787秒
用户 0分0.820秒
系统 0分11.834秒

实际 0分12.651秒
用户 0分0.916秒
系统 0分11.578秒

实际 0分13.098秒
用户 0分0.939秒
系统 0分12.004秒

实际 0分13.586秒
用户 0分1.024秒
系统 0分12.372秒

实际 0分13.026秒
用户 0分0.976秒
系统 0 分 11.910 秒

平均时间:12.962秒

Peter Cordes 评论的基准测试结果

root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; 时间查找 "$(pwd)" \( -type d -exec chmod 755 {} + \) -o \( -type f -exec chmod 644 {} + \) ; 完成

实际 0分14.096秒
用户 0分1.455秒
系统 0分12.456秒

实际 0分14.492秒
用户 0分1.398秒
系统 0分12.897秒

实际 0分14.309秒
用户 0分1.518秒
系统 0分12.576秒

实际 0分14.451秒
用户 0分1.477秒
系统 0分12.776秒

实际 0分15.101秒
用户 0分1.554秒
系统 0分13.378秒

实际 0分14.223秒
用户 0分1.470秒
系统 0 分 12.560 秒

实际 0分14.266秒
用户 0分1.459秒
系统 0 分 12.609 秒

实际 0分14.357秒
用户 0分1.415秒
系统 0 分 12.733 秒

实际 0分14.393秒
用户 0分1.404秒
系统 0 分 12.830 秒

实际 0分14.448秒
用户 0分1.492秒
系统 0分12.717秒

平均时间:14.414秒

Fanatique 答案的基准测试结果

root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; 时间 { find "$(pwd)" -type d -print0 | xargs -0 chmod 755 ; find "$(pwd)" -type f -print0 | xargs -0 chmod 644 ; } ; 完成

实际 0分14.561秒
用户 0分1.991秒
系统 0分13.343秒

实际 0分14.521秒
用户 0分1.958秒
系统 0分13.352秒

实际 0分14.696秒
用户 0分1.967秒
系统 0分13.463秒

实际 0分14.562秒
用户 0分1.875秒
系统 0 分 13.400 秒

实际 0分14.609秒
用户 0分1.841秒
系统 0分13.533秒

实际 0分14.892秒
用户 0分2.050秒
系统 0 分 13.630 秒

实际 0分14.291秒
用户 0分1.885秒
系统 0分13.182秒

实际 0分14.843秒
用户 0分2.066秒
系统 0分13.578秒

实际 0分14.219秒
用户 0分1.837秒
系统 0分13.145秒

实际 0分14.503秒
用户 0分1.803秒
系统 0分13.419秒

平均时间:14.570秒

harrymc 更新答案的基准测试结果

root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; 时间 { find "$(pwd)" -type d -exec chmod 755 {} + ; find "$(pwd)" -type f -exec chmod 644 {} + ; } ; 完成

实际 0分14.975秒
用户 0分1.728秒
系统 0 分 13.050 秒

实际 0分14.710秒
用户 0分1.586秒
系统 0分12.979秒

实际 0分14.644秒
用户 0分1.641秒
系统 0分12.872秒

实际 0分14.927秒
用户 0分1.706秒
系统 0分13.036秒

实际 0分14.867秒
用户 0分1.597秒
系统 0分13.086秒

实际 0分15.119秒
用户 0分1.666秒
系统 0分13.259秒

实际 0分14.878秒
用户 0分1.590秒
系统 0分13.098秒

实际 0分14.852秒
用户 0分1.681秒
系统 0分13.045秒

实际 0分14.380秒
用户 0分1.603秒
系统 0分12.663秒

实际 0分14.558秒
用户 0分1.514秒
系统 0分12.899秒

平均时间:14.791秒

harrymc 原始答案的基准测试结果

由于这个命令很慢,我只运行了一次基准测试。

root@demo:~# for i in {0..0} ; do chmod -R 0777 "$(pwd)" ; 时间 { find "$(pwd)" -type d -exec chmod 755 {} \; ; find "$(pwd)" -type f -exec chmod 644 {} \; ; } ; 完成
 
实际 17m41.926s
用户 12分26.896秒
系统 4分58.332秒

耗时:1061.926 秒

答案4

如果目录太大且包含太多文件,@harrymc 向您展示的原始方法将会失败。

如果文件太多,则需要使用管道find传输:xargschmod

find /base/dir -type d -print0 | xargs -0 chmod 755 
find /base/dir -type f -print0 | xargs -0 chmod 644

相关内容