Bash xargs输出缓冲-P并行

Bash xargs输出缓冲-P并行,bash,shell,awk,sed,Bash,Shell,Awk,Sed,我有一个bash函数,我使用xargs-p并行调用它,如下所示 echo ${list} | xargs -n 1 -P 24 -I@ bash -l -c 'myAwesomeShellFunction @' 一切正常,但由于明显的原因(无缓冲),输出混乱 试图找出一种有效缓冲输出的方法。我在想我可以用awk,但我不够好,写不出这样一个脚本,我在谷歌上找不到任何有价值的东西?有人能帮我用sed或awk写这个“输出缓冲区”吗?并没有什么奇怪的,只是累积输出,并在进程终止后将其吐出。我不在乎s

我有一个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 ""'
另外,我试着使用stdbuf 但不起作用,我在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
如果您的输出长度超过一页(通常为4kb),这并不是非常原子化的,但在大多数情况下,它可以:

xargs -P 24 bash -c 'for arg; do printf "%s\n" "$(myAwesomeShellFunction "$arg")"; done' _
这里的神奇之处在于命令替换:
$(…)
创建一个子shell(一个
fork()
ed脱离shell副本),运行其中的代码
,然后将要替换的代码读入外部脚本中的相关位置

请注意,我们不需要
-n1
(如果您处理大量参数——对于少量参数,它可能会改进并行化),因为我们迭代的参数数量与传递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
' _

不要告诉我使用GNU parallel,我没有安装它,安装它是有问题的,因为我在RHEL6上运行,为什么不将输出重定向到一个文件,使用
-I@
为每个任务生成一个唯一的文件名?然后可以
cat
所有文件。您甚至可以使用
mktemp
不要乱动文件顺便说一句,
-I@
被替换成
bash-c
是有问题的,如果您不信任您的数据。如果列表中的一个条目包含
$(/tmp/evil-prog)
,则您刚刚插入了代码。从代码带外传递数据要安全得多。@BenjaminW.,打开行缓冲告诉单个实例不要尝试执行短于一行的写操作(假设没有一行超过缓冲区大小),但这不会阻止行在多个实例之间交错。即使是大于行的缓冲区也不能防止缓冲区边界(以及写入边界)处于不希望的截止点。这真是聪明,没有意识到命令替换就是这样做的。输出只能占用1页?我的几乎保证小于4kb,除非真的发生了不寻常的事情。参数的数量通常是这样的:它可以占用多个页面,但在这种情况下更有可能被拆分为多个写入,因此,如果多个进程同时完成(彼此之间的间隔不超过几毫秒?),并结合多页面输出,那么您可能会失去原子性。