从非常长的文件列表的两端进行 chown

从非常长的文件列表的两端进行 chown

我在 NFS 上有一个包含 200 多万个节点的文件列表。我必须运行相当多的文件权限更改、所有者更改等。当我运行诸如chmodchown(甚至rmmv)之类的命令时,这些进程需要相当长的时间才能完成,因为它们每个都必须访问文件系统中的每个节点。

由于我通过 NFS 共享访问权限,因此我希望实现某种形式的并行化。有没有办法拆分(分片?)文件列表,以便chown,chmod,rm,mv在多台主机上运行 等可以更快地完成整个作业?想象一下 2 台主机从两端开始并在中间相遇。

答案1

见面parallelsudo apt install parallel):

GNUparallel是一个 shell 工具,用于使用一台或多台计算机并行执行作业。作业可以是单个命令或小脚本,必须针对输入中的每一行运行该脚本。典型的输入是文件列表、主机列表、用户列表、URL 列表或表列表。作业也可以是从管道读取的命令。然后,GNU parallel 可以将输入拆分为块,并将块并行传输到每个命令中。
(…)
对于每行输入,GNUparallelcommand使用该行作为参数执行。如果没有给出命令,则执行输入行。多条生产线将并行运行。GNU parallel 通常可以用作xargs或 的替代品cat | bash

例子

find . -type f -print0 | parallel -0 chmod +w

这将递归地查找当前目录中的每个文件并chmod +w在其上运行,同时执行多个进程 - 默认情况下每个 CPU 核心一个进程。

更多详情请参阅man parallel,尤其是解释示例的精彩列表。还有一个带有示例视频的播放列表在YouTube上。

答案2

如果限制因素不是服务器,我会感到惊讶。因此,我认为 dessert 的解决方案是合理的 - 可能添加-j200-X在本地主机上运行更多并行作业,并在每行插入多个参数。

但假设你有懒惰的客户那么这可能是一种方法:

doit() {
  chmod +w "$1"
  # do other stuff
}
export -f doit
cat 2millionfilelist.txt |
  parallel --env doit -S nfsclient1,nfsclient2,nfsclient3 doit

这定义了一个函数(根据您的需要进行调整)。然后,将此函数复制到 3 个 nfsclient 中的每一个,并使用来自 2millionfilelist.txt 的单个参数运行。此操作是并行完成的,默认情况下,在 3 个客户端中的每一个上每个 cpucore 运行 1 个作业。

现在 GNU Parallel 将使用 连接到每个文件的 nfsclient ssh。因此,上述方法可能效率极低。但我们可以做得更好。

doitwrap() {
  doit() {
    chmod +w "$1"
    # do other stuff
  }
  export -f doit
  parallel doit
}
export -f doitwrap
cat 2millionfilelist.txt | parallel --env doitwrap -S nfsclient1,nfsclient2,nfsclient3 --pipe -N1000 doitwrap

doit与之前的操作相同,但现在我们有一个包装器,它从标准输入读取并doit在本地机器上运行。所以现在我们只需要将其2millionfilelist.txt均匀地分配给三个客户端。

GNU Parallel 也能做到这一点。我们将 doitwrap 传输给三个 worker,然后在那里运行。然后我们将2millionfilelist.txt1000 行的数据块传递给这 3 个 worker。

相关内容