Оператор Bash & (амперсанд)
Я пытаюсь запустить 3 команды параллельно в оболочке bash:
$ (first command) & (second command) & (third command) & wait
Проблема в том, что если first command
сбой, например, код выхода 0
(Я думаю, потому что wait
успешно).
Желаемое поведение состоит в том, что в случае сбоя одной из команд код выхода будет отличным от нуля (и в идеале другие выполняющиеся команды будут остановлены).
Как я мог этого добиться?
Обратите внимание, что я хочу запускать команды параллельно!
3 ответа
Лучшее, что я могу придумать, это:
first & p1=$!
second & p2=$!
...
wait $p1 && wait $p2 && ..
или же
wait $p1 || ( kill $p2 $p3 && exit 1 )
...
однако это по-прежнему обеспечивает порядок проверки процессов, поэтому, если третий сбой немедленно, вы не заметите его, пока не закончится первый и второй.
Вы должны использовать &&
вместо &
, например:
first command && second command && third command && wait
Однако это НЕ будет запускать вашу команду параллельно, так как выполнение каждой последующей команды будет зависеть от кода выхода 0 предыдущей команды.
Это может работать для вас:
parallel -j3 --halt 2 <list_of_commands.txt
Это будет запускать 3 команды параллельно.
Если какое-либо работающее задание завершится неудачно, оно уничтожит оставшиеся работающие задания и остановится, вернув код завершения неудачного задания.
Приведенная ниже функция оболочки будет ожидать завершения всех PID, переданных в качестве аргументов, возвращая 0, если все PID выполняются без ошибок.
Первый PID, который существует с ошибкой, приведет к уничтожению PID, которые идут после него, а код выхода, вызвавший ошибку, будет возвращен функцией.
wait_and_fail_on_first() {
local piderr=0 i
while test $# -gt 0; do {
dpid="$1"; shift
wait $dpid || { piderr=$?; kill $@; return $piderr ;}
} done
}
Вот как им пользоваться:
(first command) & pid1=$!
(second command) & pid2=$!
(third command) & pid3=$!
wait_and_fail_on_first $pid1 $pid2 $pid3 || {
echo "PID $dpid failed with code $?"
echo "Other PIDs were killed"
}