Linux - 运行多个并行命令,打印顺序输出

时间:2014-08-12 05:16:42

标签: git bash

我对bash有点新,我需要并行运行几百次短命令,但顺序打印输出。该命令打印一个相当短的输出到stdout,这是我不想松动或使其与另一个线程的输出混淆/混淆。在Linux中是否有办法运行多个命令(例如,并行不超过N个线程),以便顺序打印所有命令输出(按任何顺序,只要它们不重叠)。

当前bash脚本(完整代码here

declare -a UPDATE_ERRORS
UPDATE_ERRORS=( )

function pull {
    git pull  # Assumes current dir is set
    if [[ $? -ne 0 ]]; then
      UPDATE_ERRORS+=("error message")
    fi

for f in extensions/*; do
  if [[ -d $f ]]; then
    ########## This code should run in parallel, but output of each thread
    ########## should be cached and printed sequentially one after another
    ########## pull function also updates a global var that will be used later
    pushd $f > /dev/null
    pull
    popd > /dev/null
  fi
done

if [[ ${#UPDATE_ERRORS[@]} -ne 0 ]]; then
  # print errors again
fi

3 个答案:

答案 0 :(得分:3)

您可以使用flock。我已经模仿了类似的情况进行测试。 do_the_things proc生成时间输出重叠。在for循环文本生成中同时调用多次。输出应该变得混乱,但输出被送到过程locked_print,它等待锁定被释放然后将收到的输入打印到stdout。从管道内部调用程序需要输出。

#!/bin/bash

do_the_things()
        {
        rand="$((RANDOM % 10))"
        sleep $rand
        for i in `seq 1 10`; do sleep 1; echo "${rand}-$i"; done
        }

locked_print()
        {
        echo Started
        flock -e testlock cat
        }

export -f do_the_things
export -f locked_print

for f in a b c d; do
        (do_the_things | locked_print) &
done
wait

答案 1 :(得分:1)

尝试这样的事情。我没有/使用git所以我在我的版本中做了一个虚拟命令来模拟它。

#!/bin/bash
declare -a ERRORS
ERRORS=( )

function pull {
    cd "$1"
    echo Starting pull in $1
    for i in {0..9}; do echo "$1 Output line $i";done
    sleep 5
    echo "GITERROR: Dummy error in directory $1"
}

export -f pull

for f in extensions/*; do
  if [[ -d $f ]]; then
    ########## This code should run in parallel, but output of each thread
    ########## should be cached and printed sequentially one after another
    ########## pull function also updates a global var that will be used later
    echo $f
  fi
done | parallel -k pull | tee errors.tmp

IFS=$'\n' ERRORS=($(grep "^GITERROR:" errors.tmp))
rm errors.tmp

for i in "${ERRORS[@]}"; do
   echo $i
done

你会看到,即使有4个目录要拉,整个脚本也只需要5秒 - 尽管执行了4批sleep 5

答案 2 :(得分:0)

通过添加/列出目录。并行产生一个shell,它与dir相关联。如果git pull失败,则会打印一个魔术字符串。所有输出也保存为out / 1 / *中的副本。完成所有拉动后,检查魔术字符串出现在哪些文件中,并打印出这些命令的STDOUT / STDERR。清理。

parallel --results out 'cd {} && (git pull || echo e_R_r_O_r)' :::  extensions/*/
grep -l e_R_r_O_r out/*/stdout | parallel 'grep -v e_R_r_O_r {//}/stdout; cat {//}/stderr >&2'
rm -r out