将输出通过管道传输到另一个延迟命令时如何挂起主命令

How to suspend the main command when piping the output to another delay command

我有两个自定义脚本来实现它们自己的任务,一个用于输出一些 URLs(假装下面的 cat 命令),另一个用于接收 URL 来解析它通过网络请求(伪装成下面的 sleep 命令)。

这是原型:

案例一:

cat urls.txt | xargs -I{} sleep 1 && echo "END: {}"

输出是 END: {} 并且 sleep 有效。

案例二:

cat urls.txt | xargs -I{} echo "BEGIN: {}" && sleep 1 && echo "END: {}"

输出为

BEGIN: https://www.example.com/1
BEGIN: https://www.example.com/2
BEGIN: https://www.example.com/3
END: {}

不过好像只有sleep1秒。

Q1:我有点疑惑,为什么会有这些输出?

问题 2:是否有任何解决方案可以为每个 cat 行输出执行完整的流水线 xargs 延迟命令?

您可以将命令放入单独的脚本中:

worker.sh

#!/bin/bash
echo "BEGIN: $*" && sleep 1 && echo "END: $*"

设置执行权限:

chmod +x worker.sh

并用 xargs:

调用它
cat urls.txt | xargs -I{} ./worker.sh {}

输出

BEGIN: https://www.example.com/1
END: https://www.example.com/1
BEGIN: https://www.example.com/2
END: https://www.example.com/2
BEGIN: https://www.example.com/3
END: https://www.example.com/3

在 BEGIN 和 END 之间脚本休眠一秒钟。

感谢shellter和UtLox的提醒,我发现xargs是关键。

这是我的发现,shell/zsh 解释器将 sleep 5echo END: {} 拆分为另一个命令序列,因此 xargs 没有收到我预期的两个 && 内联命令作为一个实用命令,并将 {} 替换为 END 表达式中的值。这可以通过 xargs -t.

来证明
cat urls.txt | xargs -I{} -t echo "BEGIN: {}" && sleep 1 && echo "END: {}"

受到UtLox答案的启发,我发现我可以在xargs中加入我对sh -c的期望。

cat urls.txt | xargs -I{} -P 5 sh -c 'echo "BEGIN: {}" && sleep 1 && echo "END: {}"'

对于-P 5,它使实用程序命令运行在并行模式下具有最大指定的子进程,以利用大部分带宽资源。

完成!