假设我手上有一个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 1
,1
是轮询间隔(以秒为单位),因此可以更改它以适应情况。