并行运行bash命令,跟踪结果和计数

edA*_*a-y 18 bash

我想知道如果可能的话,我可以在BASH中创建一个简单的作业管理来并行处理多个命令.也就是说,我有一个很大的命令列表要运行,我想在任何给定的时间运行其中两个.

我对bash有很多了解,所以这里有一些要求让它变得棘手:

  • 命令具有可变的运行时间,所以我不能只生成2,等待,然后继续下两个.一旦完成一个命令,就必须运行下一个命令.
  • 控制过程需要知道每个命令的退出代码,以便它可以保持总共失败的数量

我在想我可以使用trap但我没有看到一个简单的方法来获取处理程序中的子项的退出值.

那么,关于如何做到这一点的任何想法?


好吧,这里有一些概念代码可能有用,但它打破了bash:无效的命令行生成,挂起,有时是核心转储.

# need monitor mode for trap CHLD to work
set -m
# store the PIDs of the children being watched
declare -a child_pids

function child_done
{
    echo "Child $1 result = $2"
}

function check_pid
{
    # check if running
    kill -s 0 $1
    if [ $? == 0 ]; then
        child_pids=("${child_pids[@]}" "$1")
    else
        wait $1
        ret=$?
        child_done $1 $ret
    fi
}

# check by copying pids, clearing list and then checking each, check_pid
# will add back to the list if it is still running
function check_done
{
    to_check=("${child_pids[@]}")
    child_pids=()

    for ((i=0;$i<${#to_check};i++)); do
        check_pid ${to_check[$i]}
    done
}

function run_command
{
    "$@" &
    pid=$!
    # check this pid now (this will add to the child_pids list if still running)
    check_pid $pid
}

# run check on all pids anytime some child exits
trap 'check_done' CHLD

# test
for ((tl=0;tl<10;tl++)); do
    run_command bash -c "echo FAIL; sleep 1; exit 1;"
    run_command bash -c "echo OKAY;"
done

# wait for all children to be done
wait
Run Code Online (Sandbox Code Playgroud)

请注意,这不是我最终想要的,但它将成为获得我想要的基础.


后续:我已经用Python实现了一个系统.所以任何使用Python编写脚本的人都可以拥有上述功能.请参阅shelljob

Jay*_*ker 23

GNU Parallel非常棒:

$ parallel -j2 < commands.txt
$ echo $?
Run Code Online (Sandbox Code Playgroud)

它会将退出状态设置为失败的命令数.如果您有超过253个命令,请查看--joblog.如果您事先不知道所有命令,请查看--bg.


lin*_*uts 7

我可以说服你使用make吗?这样做的好处是你可以告诉它并行运行多少命令(修改-j号)

echo -e ".PHONY: c1 c2 c3 c4\nall: c1 c2 c3 c4\nc1:\n\tsleep 2; echo c1\nc2:\n\tsleep 2; echo c2\nc3:\n\tsleep 2; echo c3\nc4:\n\tsleep 2; echo c4" | make -f - -j2
Run Code Online (Sandbox Code Playgroud)

将它粘贴在Makefile中,它将更具可读性

.PHONY: c1 c2 c3 c4
all: c1 c2 c3 c4
c1:
        sleep 2; echo c1
c2:
        sleep 2; echo c2
c3:
        sleep 2; echo c3
c4:
        sleep 2; echo c4
Run Code Online (Sandbox Code Playgroud)

请注意,那些不是行首的空格,它们是TAB,因此剪切和粘贴在这里不起作用.

如果您没有回显命令,请在每个命令的前面放置一个"@".例如:

        @sleep 2; echo c1
Run Code Online (Sandbox Code Playgroud)

这将在第一个失败的命令上停止.如果您需要计算失败,您需要以某种方式在makefile中对其进行设计.也许是这样的

command || echo F >> failed
Run Code Online (Sandbox Code Playgroud)

然后检查失败的长度.