【问题标题】:Is there a way to force xargs to send multiple lines at once?有没有办法强制 xargs 一次发送多行?
【发布时间】:2018-03-21 06:02:09
【问题描述】:

我有一个从 \n 分隔的流中读取数据并将信息发送到 xargs 以一次处理 1 行的作业。问题是,这还不够高效,但我知道如果我更改程序,使 xargs 执行的命令被发送多行而不是一次只发送一行,它可以大大提高我的脚本的性能。

有没有办法做到这一点?我对-L-n 的各种组合没有任何运气。不幸的是,我认为我也坚持使用-I 来参数化输入,因为如果我不使用-I,我的命令似乎不想采用标准输入。

基本思想是我正在尝试使用 xargs 模拟小批量处理。

从概念上讲,这与我目前所写的内容相似

contiguous-stream | xargs -d '\n' -n 10 -L 10 -I {} bash -c 'process_line {}'

^ 在上面,process_line 很容易更改,以便一次处理多行,而这个功能现在是瓶颈。强调一下,上面的-n 10-L 10 似乎没有做任何事情,我的线路仍在一次处理一个。

【问题讨论】:

  • xargs -I {} bash -c 'something with {}' 很危险。如果您的信息流中的某一行包含$(rm -rf ~),该怎么办?
  • 为什么要调用bash来执行process_line?如果它是一个独立的可执行文件,您可以直接调用它以避免安全问题和一些开销。如果它是一个 shell 函数或别名,您可以创建一个包装 shell 可执行文件来调用而不是 bash -c ...
  • @pabouk, ...同意直接调用可执行文件是首选,但如果被调用的代码是本机 shell,我不确定包装器是否购买了 bash -c特别是 如果您有一个要尝试调用的导出函数。你能扩展吗?
  • @CharlesDuffy 你是对的。这只是如何避免由 shell 评估参数引起的上述安全问题的一种替代方法。

标签: bash concurrency batch-processing xargs


【解决方案1】:

每次 Shell 调用多行

不要在这里使用-I。它可以防止一次传递多个参数,并且在用于将值替换为作为代码传递的字符串时是彻底的重大安全错误危险。

contiguous-stream | xargs -d $'\n' -n 10 \
  bash -c 'for line in "$@"; do process_line "$line"; done' _

在这里,我们将 xargs 添加的参数从代码带外传递到从 $1 和更高版本填充的位置,然后使用 "$@" 对其进行迭代。

请注意,这会减少开销,因为它将多个参数传递给每个 shell(因此您支付 shell 启动成本的次数更少),但它并不实际上同时处理所有这些参数。为此,你想要...

多条平行线

假设 GNU xargs,您可以使用 -P 指定并行处理级别:

contiguous-stream | xargs -d $'\n' -n 10 -P 8 \
  bash -c 'for line in "$@"; do process_line "$line"; done' _

在这里,我们向每个 shell 传递 10 个参数,一次运行 8 个 shell。调整你的参数以适应口味:-n 的更高值花费更少的时间来启动新的 shell,但最终会增加浪费量(如果一个进程还有 8 个进程要完成,而其他所有进程都完成了,那么你的操作就不是最理想的了) .

【讨论】:

  • -I 实际上并没有阻止一次传递超过 1 个参数,但没有关于安全漏洞的参数。
  • @JoeyColeman, ...我当然没有在 the POSIX xargs spec 中看到任何明确的规范,说明当 -I 隐含的 -L 1 被覆盖时它应该如何表现。因此,看起来任何没有它的工作能力都是一种扩展。诚然,我正在利用 -d,另一个扩展,但我会争辩一个不那么模棱两可的扩展。 :)
  • @JoeyColeman,似乎 -I 阻止了参数的“批处理”。我删除了我的答案,因为 Charles' 更好,但尝试 for i in {1..100};回声 $i;完成 | tr '\n' '\0' | xargs -0 -n10 然后尝试使用 -I {} echo {} 你会发现 -I 肯定会影响 xargs 参数处理。
  • 另一个让我更清楚的技巧是使用 tr '\n' '\0' 将输入流中的 \n 替换为 \0,然后使用 xargs -0。
  • 在 GNU xargs 中,如果你在 -I {} 之后指定 -L x-n x,那么 -I 的效果会被完全取消。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
  • 1970-01-01
  • 2012-11-05
相关资源
最近更新 更多