我们先了解一下 SIGHUP信号和 nohup命令的一些知识点:
SIGHUP 信号
1、终端关闭时,该信号被发送到 session 首进程以及作为 job 提交的进程(即用 & 符号提交的进程)
2、session首进程退出时,该信号被发送到该 session 中的前台进程组中的每一个进程,但不会发送给 job 提交的进程。
3、若父进程退出导致进程组成为孤儿进程组,且该进程组中有进程处于停止状态(收到SIGSTOP或SIGTSTP信号),该信号会被发送到该进程组中的每一个进程。
终端关闭的情景如断网或者手动关闭了会话窗口,这时即便你的命令 & 了,仍然会被 SIGHUP 信号中断。
Exit 和 Logout 命令
session 首进程退出则是你使用 exit 或者 logout 命令正常,这种退出并不会向 & 的任务发送 SIGHUP 信号
NOHUP 命令
而 nohup 命令则是应对终端异常断掉时的场景,当我们使用 nohup command & 将任务切换到后台执行时,即便此时终端突然断掉,SINHUP 信号也会被 nohup 屏蔽掉而不会终止你的后台任务。
1、bg / fg / jobs 和 ctrl-z / & 的联用
注意:当任务被 & 到后执行时,你使用 exit 或者 logout 正常登出只会结束前台命令,并不会终止你后台任务。但如果你直接关闭会话窗口或者意外断网,系统都会向当前会话下的进程发送 SIGHUP 信号。而进程对此信号的默认处理方式是退出执行。
当想要将程序后台运行时,你可以在运行命令时使用:
# 使用 & 将其挂到后台任务队列 会返回任务编号
command &
# 使用 fg 则可以将任务队列中的任务切换到前台来 可以根据任务编号选取 默认是最新的任务
fg
#或者运行命令后 ctrl-z bg 将其挂载到后台任务队列
command
#会获取任务编号 将任务暂停
ctrl-z
#bg 后面可以加任务编号 默认是将最新的任务挂载到后台任务队列
bg
# 使用 jobs 可以查看任务队列的状态
jobs
# 将第二个任务切换到前台
fg 2
# 将其重新挂载到后台
ctrl-z
bg
exit 或者 logout 后 & 进程并不会被中断
断网或者关闭窗口 & 进程也会被中断
可以看到这个会话里两个后任务没了,那是因为我强关了开启这两任务的窗口,SIGHUP 信号会发给后台任务
2、nohup 则是可以将任务以不挂断的方式运行(不挂断是说任务不接收 SIGHUP 信号)
这里说的不挂断是说当我们用 & ctrl-z + bg 等命令将任务挂在后台执行时,如果网络中断或窗口被关闭的话,系统会发送 SIGHUP 信号到你的所有任务,即便他们是以后台 & 方式运行
如果我们使用了 nohup 命令,则会将 SIGHUP 命令屏蔽掉,不会被终端
#后台运行
nohup ./test.sh &
#挂载到后台
nohup ./test.sh
ctrl-z
bg
看着其实和上面讲的没什么区别,此时别说你正常的使用 exit 或 logout 正常登出,就算突然断网或者关闭窗口任务也不会被终止。
在3会话开启的 nohup 后台任务,然后关掉窗口
可以看到我关闭了3会话(呃,他编号就跟进了一位,4变成3了...),但任务仍然在运行,如果我不使用 nohup,这两任务就中断了...
总结:
1、exit 或 logout 正常登出并不会终止 & 的后台任务,此时的 SIGHUP 信号只会发给前台任务
2、关闭窗口或断网,前后台任务都会收到 SIGHUP 信号,但如果我们试用了 nohup 则可以屏蔽此信号,让任务仍不被中断。
3、进程收到 SIGHUP 信号时默认的操作是退出执行。但我们可以在代码里使用信号捕捉的方法,捕捉或忽略 SIGHUP 信号的处理,这样进程就不会退出了。