这个问题启发了我另一个相关问题。想象一下你开始
% nohup a.sh &
然后要在完成b.sh
时执行(例如,将处理的输出。和都是长时间运行的过程,需要数小时才能完成。)a.sh
b.sh
a.sh
a.sh
b.sh
基本上你想模拟
% nohup a.sh && b.sh
b.sh
但你启动时忘记添加了a.sh
。这能实现吗?最好是在 zsh 中。
答案1
如果启动该进程的 shell 仍然知道它(尝试jobs
),那么内置的 shellwait
可以等待它完成。像这样的事情可能会起作用:
$ jobs
[1] nohup a.sh
$ wait -f %1 && nohup b.sh &
如果您在 shell 中丢失了关联,则该pidwait
命令可能会以类似的方式工作,尽管它可能无法捕获第一个进程的退出值,并且即使第一个进程失败也可能运行第二个进程,这与所做的不同&&
。
答案2
只有父进程(或子子收割机,如果有或init
父进程死亡)可以检索进程的退出状态。
从启动命令的 shell 中,您可以等待它,如果成功,则b.sh
在后台启动:a.sh
wait $pid && nohup b.sh &
在 zsh 中或:
wait -f "$pid" && { nohup b.sh & }
在最新版本的 bash 中(当进程仅停止时,-f
for不返回;这是 中的默认行为)。wait
zsh
但是wait
必须在前台运行。如果在后台运行,它将位于子 shell 进程中,因此将不再是正在运行的进程的父进程nohup a.sh
。
要检索不是您的子进程的退出状态,一种方法是使用调试器并拦截_exit()
或exit_group()
等效的系统调用。
例如,在 Linux 上,可以这样做:
ret=$(strace -qqqa0 -e signal=none -e exit_group -p "$pid" 2>&1 | grep -Po '\(\K\d+')
macos 的等效项可能涉及truss
ordtrace
命令,但我没有机器来测试它。