xargs输出缓冲-P并行

时间:2017-06-15 14:00:53

标签: bash shell awk sed

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

 echo ${list} | xargs -n 1 -P 24 -I@ bash -l -c 'myAwesomeShellFunction @'

一切正常但输出因为显而易见的原因而混乱(没有缓冲)

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

 echo ${list} | xargs -n 1 -P 24 -I@ bash -l -c 'myAwesomeShellFunction @ | sed -u ""'

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

 echo ${list} | xargs -n 1 -P 24 -I@ stdbuf -i0 -oL -eL bash -l -c 'myAwesomeShellFunction @'

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

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

1 个答案:

答案 0 :(得分:4)

如果您的输出长于页面(通常为4kb),则这不是完全原子,但对于大多数情况,它会执行:

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

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

请注意,我们不需要-n 1(如果你正在处理大量的参数 - 对于一小部分它可能会改进并行化),因为我们正在迭代尽可能多的参数您的24个并行bash个实例的传递。

如果你想让它真正成为原子,你可以用一个锁文件来做到这一点:

# 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
' _