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 <stdio.h>
#include <signal.h>
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,不会收到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 可以直接在命令行执行,
       若想做完该操作后继续别的操作,可以 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
参数指定的命令不可调用。如果标准错误是一个终端,那么把指定的命令写给标准错误的所有输出作为标准输出重定向到相同的文件描述符。

linux——signal信号(SIGHUP、SIGINT、SIGQUIT、SIGILL、SIGTRAP、SIGABRT...........................)

https://blog.csdn.net/u014470361/article/details/83591513

linux中SIGHUP与nohup的关系的更多相关文章

  1. 【linux编程】linux中HZ和Jiffies的关系

    读cubic源码的时候遇到了HZ和jiffies,不懂这两者代表什么.网上描述的是这样的 全局变量jiffies用来记录自系统启动以来产生的节拍的总数.启动时,内核将该变量初始化为0,此后,每次时钟中 ...

  2. Linux学习笔记:nohup & 后台任务

    在linux中,使用nohup xxx.sh &可以将前台任务变成后台任务执行,如果只使用&的话,在突然断网或者关闭启动终端时,内核会向后台任务发送sighup信号,从而导致后台任务停 ...

  3. linux中的权限

    第1章 显示或设置网络相关信息 1.1 ip address 与ifconfig 类似 [root@znix ~]# ip address 1: lo: <LOOPBACK,UP,LOWER_U ...

  4. linux守护进程、SIGHUP与nohup详解

    前端时间帮忙定位个问题.docker容器故障恢复后,其中的keepalived进程始终无法启动,也看不到Keepalived的日志. strace 查看系统调用之后,发现了原因所在 socket(PF ...

  5. linux中nohup 与 & 的区别

    Linux/Unix下,通常只有守护进程可在脱离终端的情况下能继续执行,而普通进程在关闭终端时会因收到SIGHUP信号(挂起信号)而退出.当终端退出后,由该终端启动的后台程序自动退出. 若想命令在后台 ...

  6. Linux中的文件描述符与打开文件之间的关系

    Linux中的文件描述符与打开文件之间的关系 导读 内核(kernel)利用文件描述符(file descriptor)来访问文件.文件描述符是非负整数.打开现存文件或新建文件时,内核会返回一个文件描 ...

  7. Linux中service命令和/etc/init.d/的关系

    Linux中service命令和/etc/init.d/的关系   service xxx启动 /etc/init.d/ 目录下的xxx脚本 如一个脚本名为 mysvc保存在/etc/init.d/下 ...

  8. nohup在linux中的挂起

    笔者也是一个linux新手,最近在学习linux相关的东西,本人是一个node爱好者,想在linux上写一个linux服务,我的环境是centeros7,用putty链接远端的服务器,要想让服务在服务 ...

  9. 关于Linux中nohup.out日志过大问题

    背景,java项目,一般在运行JAVA程序时需要用到nohup命令来实现后台启动日志,默认保存在当前目露nohup.out文件.但是有些程序输出nohup文件会出现过大的情况. 在此解决如下: 1,在 ...

随机推荐

  1. Java 之 匿名对象

    一.匿名对象 创建对象时,只有创建对象的语句,却没有把对象地址赋值给某个变量. 虽然是创建对象的简化写法,但是应用场景非常有限. 匿名对象:没有变量名的对象. 语法格式: new 类名(参数列表): ...

  2. Java深入学习(4):Future模式

    Future模式: 其实相当于是前端的Ajax 比如我们使用多线程下载文件时候,每一个线程都会发送HTTP请求资源.而我如何知道,文件下载完毕呢? 也就是说,主线程如何获得子线程的执行结果呢? 创建多 ...

  3. windows mysql服务器

    安装完mysql服务器后,需要启动服务器, 才可提供数据库存储服务.windows上如何启动和关闭mysql服务器呢? 1. 启动 进入mysql的安装目录,如D:\Program Files\mys ...

  4. java版ftp简易客户端(可以获取文件的名称及文件大小)

    java版ftp简易客户端(可以获取文件的名称及文件大小) package com.ccb.ftp; import java.io.IOException; import java.net.Socke ...

  5. Win10 Microsoft Store 微软商店 Error 0x00000193 解决方法

    0x00 前言 最近使用 CFW 过程中使用 Fiddle Web Debug 设置 Store 的回环代理的过程中发现无论是否使用代理,Store 都无法访问网络的问题,在最下面的提示中出现了 0x ...

  6. k8s Storage Classes

    Storage Classes 介绍 StorageClass 为管理员提供了描述存储 "类" 的方法. 不同的类型可能会映射到不同的服务质量等级或备份策略,或是由群集管理员制定的 ...

  7. Codeforces A. Password(KMP的nxt跳转表)

    题目描述: Password time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  8. Linux创建目录和文件的默认权限设置

    这两天,项目中使用jenkins自动构建系统时遇到了在Linux中创建目录和文件的权限问题,临时的解决办法是在脚本中增加了chmod赋权限命令; 偶然想到Linux应该是可以设置默认权限的,故学习了一 ...

  9. font-awesome图标显示问题解决方案

    font-awesome一个很强大的字体图标库.下载链接:http://fontawesome.dashgame.com/刚开始使用font-awesome的新手往往容易只引入一个css文件,这样就会 ...

  10. discuz! X3.4特殊字符乱码解决方案

    Discuz! X3.4升级后,帖子内容使用Unicode编码会出现直接显示源码问题 打开:source\function\function_core.php $string = str_replac ...