我正面临内置等待的意外行为。
~
❯ sleep 1 &
[1] 72009
~
❯
[1] + 72009 done sleep 1
~
❯ wait 72009
~
❯ echo $?
0
尽管 PID 不再存在,但等待仍然以零退出状态退出。
问题
- 这种行为的原因是什么?
- 等待是如何进行的?它在幕后做什么?
答案1
在这种情况下, Bashwait
返回 0,因为它“记住”进程 72009 是其子进程之一,并且它记住其子进程的退出代码,而退出代码为 0。(文档在这里有些误导,因为它明确提到了“活动”进程.)
在幕后,wait
确定给定的进程标识符是否对应于 shell 的子进程之一(可能在作业中);如果是,则检查该进程是否仍在运行。如果它仍在运行,它将等待它完成。完成后,它会确定相应的退出代码(可能仅适用于进程,或适用于整个作业),并返回该退出代码。正确处理信号、进程替换、控制终端等有很多额外的复杂性,但这与这里无关。
退出代码(至少)被记住在作业表中。您可以通过运行具有不同退出代码(false &
和true &
)的两个命令并等待各自的进程标识符来查看其实际情况。只要作业表没有被清除,wait
就会给出正确的退出代码。不带参数运行wait
以从作业表中删除已完成的作业,您将看到无法再检索早期作业的退出代码。
答案2
这就是wait
shell 中内置函数的定义方式。
- 等待已经终止的子进程会
wait
导致返回 0。
某些 shell(例如ksh93
)具有最后几个进程的缓存,并且可能返回此类子进程的退出代码。