xargs输出缓冲-P并行

rek*_*nuc 8 bash shell awk sed

我有一个bash函数,我使用xargs -P并行调用

 echo ${list} | xargs -n 1 -P 24 -I@ bash -l -c 'myAwesomeShellFunction @'
Run Code Online (Sandbox Code Playgroud)

一切正常,但输出因为显而易见的原因搞砸了(没有缓冲)

试图找出一种有效缓冲输出的方法.我以为我可以使用awk,但我不够好写这样的脚本,我在谷歌上找不到任何有价值的东西?有人可以帮我在sed或awk中写这个"输出缓冲区"吗?没什么好看的,只是累积输出并在过程终止后吐出.我不关心shell函数执行的顺序,只需要它们的输出缓冲...类似于:

 echo ${list} | xargs -n 1 -P 24 -I@ bash -l -c 'myAwesomeShellFunction @ | sed -u ""'
Run Code Online (Sandbox Code Playgroud)

我按照https://unix.stackexchange.com/questions/25372/turn-off-buffering-in-pipe尝试使用stdbuf, 但是没有用,我在o和e上指定了缓冲但输出仍然没有缓冲:

 echo ${list} | xargs -n 1 -P 24 -I@ stdbuf -i0 -oL -eL bash -l -c 'myAwesomeShellFunction @'
Run Code Online (Sandbox Code Playgroud)

这是我的第一次尝试,这只捕获第一行输出:

 $ bash -c "echo stuff;sleep 3; echo more stuff" | awk '{while (( getline line) > 0 )print "got ",$line;}'
 $ got  stuff
Run Code Online (Sandbox Code Playgroud)

Cha*_*ffy 5

如果您的输出超过一页(通常为4kb),这不是原子,但是在大多数情况下,它将做到:

xargs -P 24 bash -c 'for arg; do printf "%s\n" "$(myAwesomeShellFunction "$arg")"; done' _
Run Code Online (Sandbox Code Playgroud)

这里$(...)的妙处是命令替换:创建一个子shell(shell的fork()ed-off副本),...在其中运行代码,然后读取该内容以替换为外部脚本中的相关位置。

请注意,我们不需要-n 1(如果您要处理大量的参数,如果数量很少,则可以改善并行化),因为我们要遍历bash传递的24个并行实例中的每个参数那么多的参数。


如果要使其真正成为原子,可以使用锁文件来实现:

# generate a lockfile, arrange for it to be deleted when this shell exits
lockfile=$(mktemp -t lock.XXXXXX); export lockfile
trap 'rm -f "$lockfile"' 0

xargs -P 24 bash -c '
  for arg; do
    {
      output=$(myAwesomeShellFunction "$arg")
      flock -x 99
      printf "%s\n" "$output"
    } 99>"$lockfile"
  done
' _
Run Code Online (Sandbox Code Playgroud)