Выполнять команды bash параллельно, отслеживать результаты и считать

Мне было интересно, как, если возможно, я могу создать простое управление заданиями в BASH для обработки нескольких команд в параллели. То есть у меня есть большой список команд, которые нужно запускать, и я хотел бы, чтобы две из них выполнялись одновременно.

Я довольно много знаю о bash, поэтому вот требования, которые делают его сложным:

  • Команды имеют переменное время выполнения, поэтому я не могу просто создать 2, подождать, а затем продолжить со следующими двумя. Как только одна команда выполнена, должна быть запущена следующая.
  • Управляющий процесс должен знать код выхода каждой команды, чтобы он мог сохранить общее количество неудачных

Я думаю, как-нибудь я могу используйте ловушку , но я не вижу простого способа получить значение выхода дочернего элемента внутри обработчика.

Итак, есть идеи, как это можно сделать?


Ну, вот какое-то доказательство концептуального кода, который, вероятно, должен работать, но он нарушает 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

Обратите внимание, что это не то, что я в конечном итоге хочу, но это будет фундамент для получения того, что я хотите.


Followup : Я реализовал систему для этого на Python. Таким образом, любой, кто использует Python для написания сценариев, может иметь вышеуказанные функции. См. shelljob

18
задан Benjamin 17 July 2014 в 22:22
поделиться