监听给定 pid $$ 的进程退出

监听给定 pid $$ 的进程退出

假设我手上有一个pid,mypid=$$

是否有一些 bash/系统命令我可以用来监听给定 pid 的进程的退出?

如果不存在带有 mypid 的进程,我想该命令应该会失败。

答案1

我从这个答案中得到了我需要的东西:https://stackoverflow.com/a/41613532/1223975

..结果使用wait <pid> 仅当该 pid 是当前进程的子进程时才有效

然而,以下内容适用于任何流程:

等待任何进程完成

Linux:

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

Darwin(需要$pid打开文件):

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

有超时(秒)

Linux:

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

Darwin(需要$pid打开文件):

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

答案2

可移植的方法是使用kill进行轮询,即类似:

until kill -s 0 "$pid" 2>/dev/null; do sleep 1; done

这不需要诸如 GNU tail 或 lsof 之类的不可移植命令,并且在 bash 中,仅调用一个外部命令,即 sleep。 GNU tail 可能更高效一些,因为它是用 C 编写的(理论上可以利用高级函数,例如pidfd_open),并且 lsof 可能会产生大量开销。

粗略的超时可以通过计算循环迭代的次数来实现。

一种仅适用于一个服务员的可移植性稍差的解决方案是使用 ptrace(2),它没有可移植的 shell 接口,但可以在某些系统上使用 strace 命令进行访问:

strace -e exit -e signal=none -p "$pid"

答案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

答案4

关于https://stackoverflow.com/a/41613532/1223975Alexander Mills 重新发布的解决方案Timeout in Seconds Darwin是针对没有 GNU 的类 UNIX 操作系统的解决方法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 11是轮询间隔(以秒为单位),因此可以更改它以适应情况。

相关内容