当脚本末尾有循环时,Bash `&` 行为不一致

当脚本末尾有循环时,Bash `&` 行为不一致

当我启动 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()离开了它的父进程,所以它不受影响。

相关内容