захватить pid завершенного фонового процесса, используя trap в bash - PullRequest
5 голосов
/ 02 марта 2012

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

Я рассмотрел использование wait, чтобы pids каждого порожденного процесса захватывался и сохранялся в массиве, а затем массив перебирался, и ожидание вызывалось для каждого процесса.Этот метод описывается здесь по-разному:

https://stackoverflow.com/a/356154/366856

Проблема с этим, если я правильно понимаю, заключается в том, что она может быть относительно неэффективной, если вы хотите выполнить какое-либо действие, каккак только отдельный процесс заканчивается.Например, если вы порождаете процессы A и B, а B завершается раньше, чем A, то выполнение должно ждать, пока завершатся и A, и B.Мне нужно выполнить действие, как только закончится B.

Кажется, trap SIGCHLD - это способ выполнить действие сразу после завершения дочернего процесса, но проблема в том, что я не могу найти способ определить pidисточника сигнала SIGCHLD, который мне тоже нужен.Наиболее близкий момент, который я нашел к рабочему примеру этого, - третий пример кода в этом посте:

http://www.linuxforums.org/forum/programming-scripting/103996-multithreading-bash.html#post510187

Я скопировал его сюда для удобства:

#!/bin/bash

iNext=0

function ChildReturned() {
        wait $1
        echo "$1 was returned. Its exits status was: $?"
        iNext=$((iNext+1))
        StartChild $iNext
}


function StartChild {
        ./child $1 &
        pid=$!
        echo "Started: $1  PID= $pid"
        trap 'ChildReturned $pid' SIGCHLD
}


set -bm

for (( iNext=0; iNext<=10; iNext++ ));
do
        StartChild $iNext
done

wait

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

Есть ли способ получить pid завершенного дочернего процесса, используя trap в bash?

Обновление

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

http://mywiki.wooledge.org/ProcessManagement#I_want_to_process_a_bunch_of_files_in_parallel.2C_and_when_one_finishes.2C_I_want_to_start_the_next._And_I_want_to_make_sure_there_are_exactly_5_jobs_running_at_a_time.

1 Ответ

3 голосов
/ 02 марта 2012

Установите ловушку один раз, и в ловушке вы можете позвонить jobs -n, чтобы увидеть, какие дети закончили со времени вашей последней проверки. Обратите внимание, что это не говорит вам, какой ребенок отправил SIGCHLD; рассмотрим случай, когда двое детей умирают, прежде чем попасть в ловушку. В этом случае вы попадете в ловушку только один раз, и это спорный вопрос, на какой сигнал ребенка вы фактически реагируете. Обратите внимание, что -n является расширением bash, и вы можете использовать jobs -l.

...