还记得刚开发后端服务的时候,啪啪啪一顿猛敲,接口测试通过,程序启动上线。对着老大和前端说:我的接口部署好了,你们能够测试了。而后洒脱的收包、闪人,心中默念一句:你们这群低效的加班狗。前脚还没跨出大门,就听到“xxx,你的接口挂了”。
回到座位查看了下,果然无奈调用,登录服务器查看,过程都没了,这是咋回事?隔壁的老炮看了下我的操作记录,而后在启动命令上加了“nohup &”,所有ok了。
这是我第一次接触nohup命令,起初才晓得这个命令会使程序疏忽 HUP 信号,保障程序可能失常进行。在终端退出时,会向它所关联的过程所发SIGHUP信号,过程收到这个信号后就会停止运行。所以如果你不心愿过程被这个信号干掉的话,就能够疏忽这个信号。而 nohup 命令做的就是这个事件。然而原理是什么呢?
这里咱们再来理解两个概念:过程组和会话。
过程组
过程组就是一系列互相关联的过程汇合,零碎中的每一个过程也必须从属于某一个过程组;每个过程组中都会有一个惟一的 ID(process group id),简称 PGID;PGID 个别等同于过程组的创立过程的 Process ID,而这个进过程个别也会被称为过程组先导(process group leader),同一过程组中除了过程组先导外的其余过程都是其子过程;过程组的存在,不便了系统对多个相干过程执行某些对立的操作,例如,咱们能够一次性发送一个信号量给同一过程组中的所有过程。
会话
会话(session)是一个若干过程组的汇合,同样的,零碎中每一个过程组也都必须从属于某一个会话;一个会话只领有最多一个管制终端(也能够没有),该终端为会话中所有过程组中的过程所共用。一个会话中前台过程组只会有一个,只有其中的过程才能够和管制终端进行交互;除了前台过程组外的过程组,都是后盾过程组;和过程组先导相似,会话中也有会话先导(session leader)的概念,用来示意建设起到管制终端连贯的过程。在领有管制终端的会话中,session leader 也被称为管制过程(controlling process),一般来说管制过程也就是登入零碎的 shell 过程(login shell);
执行睡眠后盾过程sleep 50 & 之后,通过ps命令查看该过程及shell信息如上图:
•PPID 指父过程 id•PID 指过程 id•PGID 指过程组 id•SID 指会话 id•TTY 指会话的管制终端设备•COMMAND 指过程所执行的命令•TPGID 指前台过程组的 PGID
SIGHUP信号的触发及默认解决
在对会话的概念有所理解之后,咱们当初开始正式介绍一下SIGHUP信号,SIGHUP 信号在用户终端连贯(失常或非正常)完结时收回, 通常是在终端的管制过程完结时, 告诉同一session内的各个作业, 这时它们与管制终端不再关联. 系统对SIGHUP信号的默认解决是终止收到该信号的过程。所以若程序中没有捕获该信号,当收到该信号时,过程就会退出。
SIGHUP会在以下3种状况下被发送给相应的过程:
1.终端敞开时,该信号被发送到session首过程以及作为job提交的过程(即用 & 符号提交的过程);2.session首过程退出时,该信号被发送到该session中的前台过程组中的每一个过程;3.若父过程退出导致过程组成为孤儿过程组,且该过程组中有过程处于进行状态(收到SIGSTOP或SIGTSTP信号),该信号会被发送到该过程组中的每一个过程。
起因搞明确了,那除了nohup,还有什么形式能够防止HUP信号导致程序退出呢?答案是c库函数sginal()
void (*signal(int sig, void (*func)(int)))(int)
其中
•sig -- 在信号处理程序中作为变量应用的信号码。文章中提到的SIGHUP就是信号码•func -- 收到信号后的处理函数
咱们调用该函数设置一个函数来解决信号,只打印不退出就能够了,试验代码如下:
#include <stdio.h>#include <signal.h>#include <unistd.h>void handler(int a) { printf("hello\n");}int main(){ int i; signal(SIGHUP,handler); for(i=1;i<1000;i++){ printf("sleep %d ...\n",i); sleep(1); fflush(stdout); } return 0;}
咱们来看一下试验成果,编译启动,而后敞开终端
关上一个新的终端,查看过程是否还在运行,以及设置的信号处理函数是否被调用
程序未退出,hello也胜利输入了。除了用nohup,咱们能够在代码中设置信号处理函数来达到雷同的成果。
此外还有一些场景咱们不能间接用默认的处理函数,比方高可用场景下,咱们须要应用父子过程的形式,父过程监控并保护子过程的启停和扩大、一些简单的业务逻辑中,不想被用户Ctrl+C中断的、程序应用了大量内部资源,在退出时须要优雅的回收等等,而很多成熟优良的程序都是这样做的,比方postgreSQL
援用
•https://blog.csdn.net/z\_ryan/article/details/80952498
•https://mp.weixin.qq.com/s/nyT-FPdIUdJUiUCYVGEnTg