Выполнять несколько сценариев оболочки одновременно - PullRequest
9 голосов
/ 23 ноября 2011

Я хочу сделать следующие вещи:

  • Одновременное выполнение нескольких сценариев оболочки (здесь 2 сценария).

  • Дождитесь окончания обоих сценариев

  • Дамп возвращаемого значения каждого скрипта

Однако main.sh не работает должным образом.


main.sh

#!/bin/bash

ret1=`./a.sh` &
ret2=`./b.sh`

if [ "${ret1}"="" -a "${ret2}"="" ]; then
   sleep 1
else
   echo ${ret1},${ret2}
end

a.sh

#!/bin/bash
sleep 10
echo 1

b.sh

#!/bin/bash
sleep 5
echo 2

Ответы [ 5 ]

7 голосов
/ 21 марта 2012

Если у вас установлена ​​GNU Parallel http://www.gnu.org/software/parallel/, вы можете сделать это:

parallel -j0 '{}; echo $?' ::: a.sh b.sh

У меня есть подозрение, что вы хотите, чтобы код выхода проверял, не сработал ли один из них, и что вына самом деле все равно, какой был точный код выхода.В этом случае вы можете сделать:

parallel -j0 ::: a.sh b.sh || echo one or both of them failed

Если достаточно получить код ошибки последнего, который не прошел:

parallel -j0 --halt 1 ::: a.sh b.sh; echo $?

Может быть, вы хотели бы убить a.sh, еслиb.sh заканчивает работу рано, но терпит неудачу:

parallel -j0 --halt 2 ::: a.sh b.sh; echo $?

Вы можете установить GNU Parallel просто:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

Посмотрите вступительные видеоролики по GNU Parallel, чтобы узнать больше: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

5 голосов
/ 23 ноября 2011

Вот некоторый код, который я выполнял, который, кажется, делает именно то, что вы хотите. Просто вставьте ./a.sh и ./b.sh, где это необходимо:

# Start the processes in parallel...
./script1.sh 1>/dev/null 2>&1 &
pid1=$!
./script2.sh 1>/dev/null 2>&1 &
pid2=$!
./script3.sh 1>/dev/null 2>&1 &
pid3=$!
./script4.sh 1>/dev/null 2>&1 &
pid4=$!

# Wait for processes to finish...
echo -ne "Commands sent... "
wait $pid1
err1=$?
wait $pid2
err2=$?
wait $pid3
err3=$?
wait $pid4
err4=$?

# Do something useful with the return codes...
if [ $err1 -eq 0 -a $err2 -eq 0 -a $err3 -eq 0 -a $err4 -eq 0 ]
then
    echo "pass"
else
    echo "fail"
fi

Обратите внимание, что это фиксирует состояние выхода скрипта, а не то, что он выводит на stdout. Нет простого способа захвата stdout скрипта, работающего в фоновом режиме, поэтому я бы посоветовал вам использовать exit status для возврата информации в вызывающий процесс.

2 голосов
/ 07 сентября 2013

Если у вас есть bash 4.2 или более поздняя версия, вам может быть полезно следующее. Он использует ассоциативные массивы для хранения имен задач и их «кода», а также имен задач и их pids. Я также встроил простой метод ограничения скорости, который может пригодиться, если ваши задачи потребляют много ресурсов ЦП или ввода-вывода и вы хотите ограничить количество одновременных задач.

Скрипт запускает все задачи в первом цикле и использует результаты во втором.

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

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

* * 1010
2 голосов
/ 23 ноября 2011

Ответ, который вы ищете в этом вопросе shell - получить код завершения фонового процесса

По сути, когда вы создаете фоновый процесс, вы не можете получить его код выхода напрямую.Но если вы запустите команду bash wait, то код выхода wait вернет код завершения фонового процесса.

./a.sh &
pid1=$!
./b.sh
ret2=$?
wait ${pid1}
ret1=$?

Это будет работать, даже если a.sh завершится до того, как вы запустите wait.Специальная переменная $? содержит код завершения предыдущего процесса.И $! содержит идентификатор процесса ранее запущенного процесса.

0 голосов
/ 24 ноября 2011

Обратные метки дают не значение, возвращаемое командой, а вывод команды. Чтобы получить возвращаемые значения:

#!/bin/sh

./a.sh &
./b.sh
ret2=$?   # get value returned by b.sh
wait %1   # Wait for a.sh to finish
ret1=$?   # get value returned by a.sh
echo "$ret1: $ret2"

Если вы ошиблись в вопросе и действительно хотите получить вывод команд, вы получите и это, поскольку они оба перейдут на стандартный вывод сценария.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...