chmod 对数千个文件的递归权限

chmod 对数千个文件的递归权限

这是关于递归“chmoding”的更普遍的问题。

我有这个脚本,在某些时候需要在包含数十万个文件的文件夹中递归地更改权限。该文件夹中每天都会添加新文件,但已有的文件已设置权限并且不会更改。

我的问题是...当我打电话时

chmod 775 。 -R

它是否尝试为已设置正确权限的文件设置权限,或者仅为没有正确权限的新文件设置权限?

尽管“新”文件只有几千个并且它应该相当快地执行其权限,但似乎总是需要很长时间才能在脚本中通过此命令。

我查看了 chmod 的手册页,但似乎没有提及有关此情况的任何内容。

如果 chmod 没有事先检查权限,我是否应该开始考虑将“find”与“chmod”结合起来?

答案1

查找/chmod优化

两者都find必须chmod阅读

  1. 所有目录条目
  2. 所有这些条目的索引节点

通过首先读取所有条目,然后读取所有索引节点(在旋转磁盘上),您可能会获得性能改进,因为这样磁盘头不会在目录和索引节点之间移动。作为chmod 愚蠢的(正如其他答案之一所解释的)它应该find只被调用。但即便如此,在第一个索引节点写入之前读取所有索引节点可能会有所帮助(假设您有足够的可用 RAM 用于磁盘缓存)。我建议这样:

find . -printf "" # reading the file names only
find . ! -perm 775 -printf "" # reading all the inodes (file names are cached)
find . ! -perm 775 -exec chmod 775 + # writing to the cache without reading from disk

好的解决方案:ACL

好的解决方案可能完全不同:如果文件是在此目录中创建的(并且不是从其他位置移动的),那么 ACL 可以即时完成这项工作。您只需在父目录上设置默认 ACL。

通过文件系统优化可以实现进一步的改进。如果是ext3/ext4那么你可能会e2fsck -D时不时地运行一下。也许将此目录放在单独的卷上会有所帮助。您可以尝试不同的文件系统或文件系统设置(例如不同的索引节点大小)。

答案2

假设使用chmod来自GNU coreutils 包在 Ubuntu 12.10 上。

chmod 775 . -R对其找到的每个文件执行fchmodat系统调用,无论权限是否需要更改。我通过检查代码并使用strace chmod 775 . -R(下面的片段)列出实际行为来确认这一点。

newfstatat(4, "d", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "d", 0775)                  = 0
newfstatat(4, "c", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "c", 0775)                  = 0
newfstatat(4, "a", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "a", 0775)                  = 0
newfstatat(4, "b", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "b", 0775)                  = 0

fchmodat在每个文件上运行有几个缺点

  • 如果更改大量文件,额外的系统调用可能会变得很重要。find//通过仅xargs更改chmod需要更改的文件,其他人提到的方法可能会更快。
  • 调用fchmodat改变每个文件的文件状态修改(ctime)。这将导致每个文件/索引节点每次都会更改,并且可能会导致过多的磁盘写入。可以使用挂载选项来停止这些多余的写入。

一个简单的实验显示了直接发生的 ctime 变化chmod

auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 d
auser@duncow:/tmp/blah.test$ chmod 775 . -R
auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 d

但这并没有改变find//几分钟后xargschmod

auser@duncow:/tmp/blah.test$ date
Tue Jun 18 18:27:27 BST 2013
auser@duncow:/tmp/blah.test$ find . ! -perm 775 -print0 | xargs -0 -I {} chmod 775 {}
auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 d

我总是倾向于使用find//版本xargschmod因为 find 可以更好地控制选择内容。

答案3

chmod可能会或可能不会更改已设置为您想要的文件的权限,但如果没有,仍然需要检查它们以查看其当前权限是什么[0]。对于数十万个文件,我认为这两种方式都不重要;时间很可能花在工具stat检查每个文件上。

您可以尝试使用find检查比上次运行更新的文件或需要chmod运行的文件,但我认为您不会获得太大的速度提升。

如果您的脚本可能的话,您也许可以首先将新文件放入一个单独的目录中,作为“保留”区域。然后你可以chmod在那个目录(只有新文件)中,将mv它们与其余的文件放在一起。这应该会快得多,但不幸的是并不适用于每个应用程序。

[0] 即使它确实尝试设置不需要任何更改的文件的权限,底层文件系统可能不会对该请求执行任何操作,因为这是不必要的。

答案4

您是否考虑过更改创建文件的进程以使用 0775 模式创建文件?查看环境中的 umask 值 - 0002 可能会有所帮助。

相关内容