![当脚本末尾有循环时,Bash `&` 行为不一致](https://linux22.com/image/148983/%E5%BD%93%E8%84%9A%E6%9C%AC%E6%9C%AB%E5%B0%BE%E6%9C%89%E5%BE%AA%E7%8E%AF%E6%97%B6%EF%BC%8CBash%20%60%26%60%20%E8%A1%8C%E4%B8%BA%E4%B8%8D%E4%B8%80%E8%87%B4.png)
当我启动 Linux Mint 19 时,我喜欢启动一些东西。因此,我一直在 MATE 终端窗口中使用脚本 ( ./get-to-work
) 一次性启动它们:
chromium-browser --start-maximized &
thunderbird &
code -n path/to/my/workspace &
效果很好。我启动脚本,关闭终端窗口,三个程序继续运行。
然而,我最近添加了一条线,每五分钟打开一个黄色大窗口(提醒我坐直):
chromium-browser --start-maximized &
thunderbird &
code -n path/to/my/workspace &
for i in {1..1000}; do sleep 300 ; xterm -bg yellow -g 240x80 ; done
现在,如果我关闭启动此脚本的终端,脚本仍在运行,并且它会被终止,然后我不会收到任何黄色弹出窗口。这实际上对我来说是一个功能——只要我想要弹出窗口,我就会保持终端打开,然后关闭它,例如,当我在屏幕共享时。
但无论出于何种原因,关闭终端并终止脚本不仅会停止弹出循环,而且现在还会关闭 Chromium 和 Thunderbird。 VSCode ( code
) 保持打开状态。为什么?
答案1
第一种情况会发生什么:
脚本中的最后一个命令进入后台后,执行脚本的 shell 立即退出。该 shell 进程是从脚本启动的 3 个程序的父进程。现在它们的父进程已经退出,PID-1 进程(init
或者systemd
现在经常)成为它们的父进程。
终端和从脚本启动的程序之间的链接消失了,因为终端程序不再是它们的(祖)父进程。
第二种情况会发生什么:
在最后一个后台进程之后,脚本保持活动状态以运行循环。当终端退出时,它向其子进程发送SIGHUP; shell 作为其子进程,将此信号传播到其子进程(您的程序)。
当进程收到 HUP 信号时的默认操作是退出。显然 VSCode
忽略了SIGHUP,或者fork()
离开了它的父进程,所以它不受影响。