我有一个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
答案 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
' _