【发布时间】:2020-03-24 10:43:38
【问题描述】:
xargs 如果您有一个通过命令行参数接受其输入的命令,那就太好了,但如果您有一个通过 stdin 接受其输入的命令,它就没有那么有用了。
我所看到的类似情况的建议是使用tee 将行复制到多个下游进程,如下所示:
producer | tee >(consumer0 >out0) >(consumer1 >out1) >(consumer2 >out2) | consumer3 >out3;
cat out* | next-stage-of-pipeline
这有一个缺点,即所有消费者都会收到所有生产的行,并且假设似乎consumer{0..3} 是不同的进程。如果我需要每个消费者都相同,并处理部分输入(例如,并行化一个顺序消费者),那么它就不起作用了。
我正在寻找的是类似xargs 的东西,它允许在同一消费者的多个实例之间拆分工作,然后组合输入并继续处理。输出组合的方式应该模仿xargs,所以不能保证行的顺序,但是两行不会拼接在一起(例如:“Hello Fred”和“Hello George”可能以任何顺序出现,但是你不会看到“HHello GeoFregedello”)。
这样的事情的主要用途是处理大量数据,如果为输入的每一行都启动一个,消费者的启动延迟会很明显。如果consumer 的启动成本很低,我只需将它包装在一个小的shell 脚本中,将它的参数通过管道传递到consumer 并使用xargs 调用它。
至少对于我想到的用例,生产者会从内部服务中获取一堆数据,之后消费者需要转换这些数据并进行一些 API 调用。所以生产者和消费者都将是长时间运行的进程,并行运行 API 调用确实会加快速度。
这样的东西会是理想的,但我一直找不到这样做的东西:
producer | ??? -P20 consumer | next-stage-of-pipeline
是否有提供此功能的命令行工具?
【问题讨论】:
-
你建议如何分割输入?逐行循环?第一个 1/20 到 consumer0,下一个 1/20 到 consumer1,...?输出如何组合?
-
理想情况下它是可配置的,实际上循环是最容易实现的,如果存在这样的工具,我期望的可能会可用(我认为这就是 xargs 将输入拆分为论据)。为了在存在大量输入的情况下以合理的方式表现,我希望输出在作为工具标准输出(基本上xargs 的行为方式)
-
我不明白。你就不能
xargs -P20 bash -c 'consumer <<<"$1"' --吗? -
@KamilCuk 如果
consumer快速启动就可以使用,但如果您正在使用像 Java 这样的语言编写的东西,它既有启动成本,又倾向于运行时间越长越快。 -
@Morgen 为避免额外的混淆,您能否澄清“生产者”是否“昂贵”(时间、内存、启动缓慢等),以及预期产生的数据量。让消费者/生产者并行运行重要吗?
标签: shell parallel-processing xargs