Прослушайте выход процесса из данного pid $$

16

Скажи, что у меня в руке пид, mypid=$$

Есть ли какая-нибудь команда bash / system, которую я могу использовать для прослушивания выхода этого процесса с данным pid?

Если не существует никакого процесса с mypid, я думаю, что команда должна просто потерпеть неудачу.

Александр Миллс
источник
Я не использую C #, но, видимо, должен быть способ: msdn.microsoft.com/en-us/library/fb4aw7b8(v=vs.110).aspx
Александр Миллс,
В Unix обычно ждут дочерние процессы, использующие waitв оболочке или wait()функции библиотеки C. У AFAIK нет стандартного способа ожидания не дочернего процесса. Также неясно, может ли функция C # сделать это (это зависит от того, что такое «связанный процесс»).
Кусалананда
Я мог бы сделать это с помощью опроса, но это было бы ужасно
Александр Миллс
Это также может дать вам неправильные результаты. Повторное использование PID теоретически может означать, что процесс может ожить с тем же PID, что и процесс, который вы ожидаете. В Linux (с последовательными PID) это было бы маловероятным , но в таких системах, как OpenBSD (рандомизированное распределение PID), это было бы проблемой.
Кусалананда

Ответы:

21

Я получил то, что мне было нужно из этого ответа: https://stackoverflow.com/a/41613532/1223975

.. выход из использования wait <pid> будет работать только в том случае, если этот pid является дочерним процессом текущего процесса .

Однако следующее будет работать для любого процесса:

Дождаться окончания любого процесса

Linux:

tail --pid=$pid -f /dev/null

Дарвин (требует наличия $pidоткрытых файлов):

lsof -p $pid +r 1 &>/dev/null

С таймаутом (секунды)

Linux:

timeout $timeout tail --pid=$pid -f /dev/null

Дарвин (требует наличия $pidоткрытых файлов):

lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)
Александр Миллс
источник
Это не связано с Linux, это особенность GNU tail. Таким образом, он будет работать на любой системе с хвостом GNU, например на GNU / Linux, и не будет работать на системах, не основанных на Linux.
Стефан Шазелас
Я боюсь, что tail / lsof будет использовать опрос в этом случае, по крайней мере, с учетом эмпирических доказательств, что это выглядит так на MacOS.
Александр Миллс
lsof + r переводит его в режим повтора, так что команда повторяется каждую секунду, поэтому он использует опрос, черт побери
Александр Миллс
3

Вы можете использовать встроенный bash wait:

$ sleep 10 &
[2] 28751
$ wait 28751
[2]-  Done                    sleep 10
$ help wait
wait: wait [-n] [id ...]
    Wait for job completion and return exit status.

    Waits for each process identified by an ID, which may be a process ID or a
    job specification, and reports its termination status.  If ID is not
    given, waits for all currently active child processes, and the return
    status is zero.  If ID is a a job specification, waits for all processes
    in that job's pipeline.

    If the -n option is supplied, waits for the next job to terminate and
    returns its exit status.

    Exit Status:
    Returns the status of the last ID; fails if ID is invalid or an invalid
    option is given.

Он использует системный вызов waitpid()..

$ whatis waitpid
waitpid (2)          - wait for process to change state
Дерек Каллавей
источник
хорошо, что работает для меня, надеюсь, не использовать опрос под капотом, спасибо!
Александр Миллс
1
да, это не сработает для моего варианта использования, я получаю эту ошибку: bash: wait: pid 47760 is not a child of this shell... назад к чертежной доске lol
Александр Миллс
У меня есть ответ, я только что отправил это thx
Александр Миллс
2
Это будет ожидать только дочерние процессы, а не процесс, не связанный с текущим процессом.
Кусалананда
1

Относительно решения https://stackoverflow.com/a/41613532/1223975, которое разместил Александр Миллс, Timeout in Seconds Darwinэто обходной путь для UNIX-подобной ОС, которая не имеет GNU tail. Он не является специфическим для Darwin, но, в зависимости от возраста операционной системы, подобной UNIX, предлагаемая командная строка является более сложной, чем необходимо, и может дать сбой:

lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)

По крайней мере на одном старом UNIX lsofаргумент +r 1m%sтерпит неудачу (даже для суперпользователя):

lsof: can't read kernel name list.

Это m%sспецификация выходного формата. Более простой постпроцессор не требует этого. Например, следующая команда ожидает PID 5959 до пяти секунд:

lsof -p 5959 +r 1 | awk '/^=/ { if (T++ >= 5) { exit 1 } }'

В этом примере, если PID 5959 выходит сам по себе до истечения пяти секунд, ${?}это 0. Если не ${?}возвращается 1через пять секунд.

Она также может быть стоит прямо отметить , что в +r 1, то 1есть интервал опроса (в секундах), так что он может быть изменен в соответствии с ситуацией.

kbulgrien
источник