我在 NFS 上有一个包含 200 多万个节点的文件列表。我必须运行相当多的文件权限更改、所有者更改等。当我运行诸如chmod
和chown
(甚至rm
或mv
)之类的命令时,这些进程需要相当长的时间才能完成,因为它们每个都必须访问文件系统中的每个节点。
由于我通过 NFS 共享访问权限,因此我希望实现某种形式的并行化。有没有办法拆分(分片?)文件列表,以便chown,chmod,rm,mv
在多台主机上运行 等可以更快地完成整个作业?想象一下 2 台主机从两端开始并在中间相遇。
答案1
见面parallel
(sudo apt install parallel
):
GNU
parallel
是一个 shell 工具,用于使用一台或多台计算机并行执行作业。作业可以是单个命令或小脚本,必须针对输入中的每一行运行该脚本。典型的输入是文件列表、主机列表、用户列表、URL 列表或表列表。作业也可以是从管道读取的命令。然后,GNU parallel 可以将输入拆分为块,并将块并行传输到每个命令中。
(…)
对于每行输入,GNUparallel
将command
使用该行作为参数执行。如果没有给出命令,则执行输入行。多条生产线将并行运行。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.txt
1000 行的数据块传递给这 3 个 worker。