技术笔记:linux中SIGHUP与nohup的关系

简介: 技术笔记:linux中SIGHUP与nohup的关系

SIGHUP信号与控制终端


UNIX中进程组织结构为 session (会话)包含一个前台进程组及一个或多个后台进程组,一个进程组包含多个进程。一个session可能会有一个session首进程,而一个session首进程可能会有一个控制终端。一个进程组可能会有一个进程组首进程。进程组首进程的进程ID与该进程组ID相等。这儿是可能会有,在一定情况之下是没有的。与终端交互的进程是前台进程,否则便是后台进程。


SIGHUP会在以下3种情况下被发送给相应的进程:


1、终端关闭时,该信号被发送到session首进程以及作为job提交的进程(即用 & 符号提交的进程)


2、session首进程退出时,该信号被发送到该session中的前台进程组中的每一个进程


3、若父进程退出导致进程组成为孤儿进程组,且该进程组中有进程处于停止状态(收到SIGSTOP或SIGTSTP信号),该信号会被发送到该进程组中的每一个进程。


系统对SIGHUP信号的默认处理是终止收到该信号的进程。所以若程序中没有捕捉该信号,当收到该信号时,进程就会退出。


下面观察几种因终端关闭导致进程退出的情况,在这儿进程退出是因为收到了SIGHUP信号。login shell是session首进程。


首先写一个测试程序,代码如下:


#include


#include


char args;


void exithandle(int sig)


{


printf("%s : sighup received ",args【1】);


}


int main(int argc,char argv)


{


args = argv;


signal(SIGHUP,exithandle);


pause();


return 0;


}


程序中捕捉SIGHUP信号后打印一条信息,pause()使程序暂停。


编译后的执行文件为sigtest。


1、命 令:sigtest front > tt.txt


操 作:关闭终端


结 果:tt.txt文件的内容为front : sighup received


原 因: sigtest是前台进程,终端关闭后,根据上面提到的第1种情况,login shell作为session首进程,会收到SIGHUP信号然后退出。根据第2种情况,sigtest作为前台进程,会收到login shell发出的SIGHUP信号。


2、命 令:sigtest back > tt.txt &


操 作:关闭终端


结 果:tt.txt文件的内容为 back : sighup received


原 因: sigtest是提交的job,根据上面提到的第1种情况,sigtest会收到SIGHUP信号。


3、命 令:写一个shell,内容为【sigtest &】,然后执行该shell


操 作:关闭终端


结 果:ps -ef | grep sigtest 会看到该进程还在,tt文件为空


原 因: 执行该shell时,sigtest作为job提交,然后该shell退出,致使sigtest变成了孤儿进程,不再是当前session的job了,因此sigtest即不是session首进程也不是job,不会收到//代码效果参考:http://hnjlyzjd.com/hw/wz_24799.html

SIGHUP。同时孤儿进程属于后台进程,因此login shell退出后不会发送SIGHUP给sigtest,因为它只将该信号发送给前台进程。第3条说过若进程组变成孤儿进程组的时候,若有进程处于停止状态,也会收到SIGHUP信号,但sigtest没有处于停止状态,所以不会收到SIGHUP信号。

4、命 令:nohup sigtest > tt


操 作:关闭终端


结 果:tt文件为空


原 因: nohup可以防止进程收到SIGHUP信号


至此,我们就清楚了何种情况下终端关闭后进程会退出,何种情况下不会退出。


要想终端关闭后进程不退出有以下几种方法,均为通过shell的方式:


1、编写shell,内容如下


trap "" SIGHUP #该句的作用是屏蔽SIGHUP信号,trap可以屏蔽很多信号


sigtest


2、nohup sigtest //代码效果参考:http://hnjlyzjd.com/xl/wz_24797.html

可以直接在命令行执行,

若想做完该操作后继续别的操作,可以 nohup sigtest &


3、编写shell,内容如下


sigtest &


其实任何将进程变为孤儿进程的方式都可以,包括fork后父进程马上退出。


signal(SIGHUP, SIG_IGN);


signal信号函数,第一个参数表示需要处理的信号值(SIGHUP),第二个参数为处理函数或者是一个表示,这里,SIG_IGN表示忽略SIGHUP那个注册的信号。


SIGHUP


和控制台操作有关,当控制台被关闭时系统会向拥有控制台sessionID的所有进程发送HUP信号,默认HUP信号的action是


exit,如果远程登陆启动某个服务进程并在程序运行时关闭连接的话会导致服务进程退出,所以一般服务进程都会用nohup工具启动或写成一个 daemon。


、sighup与nohup


sighup(挂断)信号:


在控制终端或者控制进程死亡时向关联会话中的进程发出,默认进程对SIGHUP信号的处理是终止程序,所以我们在shell下建立的程序,在登录退出连接断开之后,会一并退出。


网上搜索到的解释: 什么时候会发送 SIGHUP信号?当一个进程组成为孤儿进程组时,posix.1要求向孤儿进程组中处于停止状态的进程发送SIGHUP(挂断)信号,系统对于这种信号的默认处理是终止进程,然而如果无视这个信号或者另行处理的话,那么这个挂起进程仍可以继续执行。


nohup命令:


故名思议就是忽略SIGHUP信号,一般搭配 & 一起使用,& 表示将此程序提交为后台作业或者说后台进程组。执行下面的命令


nohup bash -c "tail -f /var/log/messages | grep sys" &


1


nohup与&启动的程序, 在终端还未关闭时,完全不像传统的守护进程,因为其不是会话首进程且持有终端,只是其忽略了SIGHUP信号


从nohup源码就可以看到,其实nohup只做了3件事情


dofile函数将输出重定向到nohup.out文件


signal函数设置SIGHUP信号处理函数为SIG_IGN宏(指向sigignore函数),以此忽略SIG_HUP信号


execvp函数用新的程序替换当前进程的代码段、数据段、堆段和栈段。


execvp 函数执行后,新程序(并没有fork进程)会继承一些调用进程属性,比如:进程id、会话id,控制终端等


登录连接断开之后


在终端关闭后,nohup起到类似守护进程的效果,但是跟传统的守护进程还是有区别的


nohup创建的进程工作目录是你执行命令时所在的目录


0 1 2 标准输入 标准输出 标准错误 指向nohup.out文件


nohup创建的进程组中,除首长进程的父进程id变为1之外,其余进程依然保留原来的会话id、进程组id、父进程id,都保持不变


网上搜索到的解释: nohup命令可以将程序以忽略挂起信号的方式运行起来,被运行的程序的输出信息将不会显示到终端。


无论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前目录的 nohup.out 文件中。如果当前目录的 nohup.out


文件不可写,输出重定向到$HOME/nohup.out文件中。如果没有文件能创建或打开以用于追加,那么 command


参数指定的命令不可调用。如果标准错误是一个终端,那么把指定的命令写给标准错误的所有输出作为标准输出重定向到相同的文件描述符。

相关文章
|
2月前
|
Ubuntu Linux Python
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
在Linux系统中,使用Tkinter库时可能会遇到中文显示乱码的问题,这通常是由于字体支持问题导致的,可以通过更换支持中文的字体来解决。
164 0
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
|
2月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
113 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
2月前
|
Linux 虚拟化
Vmware 傻瓜式安装(不可不知道的Linux基础知识和技术 01)
本文介绍了VMware虚拟机的下载与安装步骤。首先,通过提供的网盘链接下载VMware安装包。接着,详细描述了安装流程,包括接受协议、选择安装路径(建议避免系统C盘)、取消更新选项等。最后,输入许可证密钥完成安装,并展示了打开虚拟机后的主界面。整个过程简单易懂,适合新手操作。
163 1
|
4月前
|
Unix Linux 开发工具
linux笔记 diff及patch的制作与使用
这篇文章是关于Linux系统中使用`diff`命令生成补丁文件以及使用`patch`命令应用这些补丁的详细教程和实战案例。
115 2
linux笔记 diff及patch的制作与使用
|
3月前
|
安全 Linux Android开发
Linux CFI (Control-flow integrity)技术相关资料汇总
Linux CFI (Control-flow integrity)技术相关资料汇总
|
4月前
|
存储 监控 Linux
在Linux中,如何进行虚拟化技术的应用?
在Linux中,如何进行虚拟化技术的应用?
|
4月前
|
存储 分布式计算 负载均衡
在Linux中,什么是集群,并且列出常见的集群技术。
在Linux中,什么是集群,并且列出常见的集群技术。
|
4月前
|
Linux KVM 虚拟化
在Linux中,什么是虚拟化?并且列出常见的虚拟化技术。
在Linux中,什么是虚拟化?并且列出常见的虚拟化技术。
|
4月前
|
Ubuntu Linux Shell
【linux】PetaLinux 2024.1安装笔记
【linux】PetaLinux 2024.1安装笔记
302 0
|
监控 关系型数据库 应用服务中间件