保留 xargs 并行执行的命令的输出顺序

UTF*_*F-8 5 xargs

当我运行一个xargs -n 1 -P 0用于并行执行的命令时,输出都是混乱的。有没有办法进行并行执行,但要确保在第二次执行的输出开始之前将第一次执行的全部输出写入stdout,在第三次执行的输出开始之前将第二次执行的全部输出写入stdout执行开始等?

例如,当想要散列包含大量数据的许多文件时,可以这样做:

printf "%s\0" * | xargs -r0 -n 1 -P 0 sha256sum
Run Code Online (Sandbox Code Playgroud)

我在少量数据 (9 GB) 上对此进行了测试,并在 5.7 秒内完成。使用散列相同的数据

sha256sum *
Run Code Online (Sandbox Code Playgroud)

耗时 34.1 秒。我经常需要散列大量数据(这可能需要几个小时),因此并行处理可以使事情完成得更快。

这里的问题是输出行的顺序是错误的。在这种情况下,它可以通过简单地按第二列对行进行排序来修复。但这并不总是那么容易。例如,当坚持上面的散列示例但想要按顺序散列编号文件时,这已经中断了:

printf "%s\0" {1..10000} | xargs -r0 -n 1 -P 0 sha256sum
Run Code Online (Sandbox Code Playgroud)

这需要更高级的排序。如果我们完全离开散列示例,事情会变得更加复杂。

在评论中,有人问我是否只是想防止输出交错。不是这种情况。我想要保持秩序。

Ole*_*nge 9

您可以使用 GNU Parallel ( ) 来实现--keep-order

printf "%s\0" {1..10000} | parallel --keep-order -r0 -n 1 -P 0 sha256sum
Run Code Online (Sandbox Code Playgroud)

--keep-order每个进程使用 4 个文件句柄,导致打印延迟。这通常不会造成任何延迟。

例如,如果您有 1000 个文件句柄,并且单个作业的耗时超过平均作业的 250 倍,则 GNU Parallel 将使用 996 个文件句柄执行其他作业。如果长时间运行的作业仍未完成,GNU Parallel 将耗尽文件句柄,因此将等待长时间运行的作业完成。它会警告:

parallel: Warning: No more file handles.
parallel: Warning: Try running 'parallel -j0 -N 100 --pipe parallel -j0'
parallel: Warning: or increasing 'ulimit -n' (try: ulimit -n `ulimit -Hn`)
parallel: Warning: or increasing 'nofile' in /etc/security/limits.conf
parallel: Warning: or increasing /proc/sys/fs/file-max
Run Code Online (Sandbox Code Playgroud)

然后将暂停,直到冗长的工作完成。不会有数据丢失。