Linux——1、守护进程、SIGHUP与nohup

article/2025/11/10 5:06:30

一、守护进程

脱离于终端并且在后台运行的进程,用于长期运行,守护自己的职责(如:监听端口、服务等)。

1、特点:

  1. 不受用户登录、注销影响。大多数Linux下的服务器都是利用守护进程实现的,如MySQL数据守护进程mysqld,HTTP服务器守护进程httpd;
  2. 父进程不是用户创建的进程。
  • 以pid=1的进程为父进程的有:
    int进程或者systemd(pid=1)以及用户人为启动的用户层进程。
  • 以kthreadd为父进程的:
    以kthreadd内核进程创建的守护进程。
  1. 守护进程一般为会话首进程、组长进程。
  2. 工作目录为根目录("/"),主要是为了防止占用磁盘导致无法卸载磁盘。

2、创建守护进程步骤:

  1. 创建子进程、父进程退出;
  2. 子进程调用系统函数 setsid 创建新的会话;
  3. 改变当前目录为根目录;
  4. 重设文件权限掩码;
  5. 关闭文件描述符;

详细见《后台开发核心技术与应用实践》p348

需掌握相关概念:
进程组、会话周期。

3、创建守护进程示例:

#include <stdio.h>
#include <syslog.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>#define PID_FILE "/var/run/sampled.pid"int sampled_running(){FILE * pidfile = fopen(PID_FILE,"r");pid_t pid;int ret ;if (! pidfile) {return 0;}ret = fscanf(pidfile,"%d",&pid);if (ret == EOF && ferror(pidfile) != 0){syslog(LOG_INFO,"Error open pid file %s",PID_FILE);}fclose(pidfile);// 检测进程是否存在if ( kill(pid , 0 ) ){syslog(LOG_INFO,"Remove a zombie pid file %s", PID_FILE);unlink(PID_FILE);return 0;}return pid;
}pid_t sampled(){pid_t pid;struct rlimit rl;int fd,i;// 创建子进程,并退出当前父进程if((pid = fork()) < 0){syslog(LOG_INFO,"sampled : fork error");return -1;}if ( pid != 0) {//  父进程直接退出exit(0);}// 新建会话,成功返回值是会话首进程id,进程组id ,首进程idpid = setsid();if ( pid < -1 ){syslog(LOG_INFO,"sampled : setsid error");return -1;}// 将工作目录切换到根目录if ( chdir("/") < 0 ) {syslog(LOG_INFO,"sampled : chidr error");return -1;}// 关闭所有打开的句柄,如果确定父进程未打开过句柄,此步可以不做if ( rl.rlim_max == RLIM_INFINITY ){rl.rlim_max = 1024;}for(i = 0 ; i < rl.rlim_max; i ++) {close(i);}// 重定向输入输出错误fd = open("/dev/null",O_RDWR,0);if(fd != -1){dup2(fd,STDIN_FILENO);dup2(fd,STDOUT_FILENO);dup2(fd,STDERR_FILENO);if (fd > 2){close(fd);}}// 消除文件掩码umask(0);return 0;
}int pidfile_write(){// 这里不用fopen直接打开文件是不想创建666权限的文件FILE * pidfile = NULL;int pidfilefd = creat(PID_FILE,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);if(pidfilefd != -1){pidfile = fdopen(pidfilefd,"w");}if (! pidfile){syslog(LOG_INFO,"pidfile write : can't open pidfile:%s",PID_FILE);return 0;}fprintf(pidfile,"%d",getpid());fclose(pidfile);return 1;
}int main(){int err,signo;sigset_t mask;if (sampled_running() > 0 ){exit(0);}if ( sampled() != 0 ){}// 写记录锁文件  if (pidfile_write() <= 0) {exit(0);}while(1) {// 捕捉信号err = sigwait(&mask,&signo);if( err != 0  ){syslog(LOG_INFO,"sigwait error : %d",err);exit(1);}switch (signo){default :syslog(LOG_INFO,"unexpected signal %d \n",signo);break;case SIGTERM:syslog(LOG_INFO,"got SIGTERM. exiting");exit(0);}}}

程序编译运行结果,可以看到:
pid 、进程组id、会话id是一样的,没有终端,并且直接由pid为1的进程接管。此时的进程已经成为一个守护进程。
在这里插入图片描述

二、sighup与nohup

sighup(挂断)信号

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

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

nohup命令

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

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

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

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

  1. dofile函数将输出重定向到nohup.out文件
  2. signal函数设置SIGHUP信号处理函数为SIG_IGN宏(指向sigignore函数),以此忽略SIG_HUP信号
  3. execvp函数用新的程序替换当前进程的代码段、数据段、堆段和栈段。

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

登录连接断开之后
在这里插入图片描述
在终端关闭后,nohup起到类似守护进程的效果,但是跟传统的守护进程还是有区别的

  1. nohup创建的进程工作目录是你执行命令时所在的目录
  2. 0 1 2 标准输入 标准输出 标准错误 指向nohup.out文件
  3. nohup创建的进程组中,除首长进程的父进程id变为1之外,其余进程依然保留原来的会话id、进程组id、父进程id,都保持不变

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

无论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前目录的 nohup.out 文件中。如果当前目录的 nohup.out
文件不可写,输出重定向到$HOME/nohup.out文件中。如果没有文件能创建或打开以用于追加,那么 command
参数指定的命令不可调用。如果标准错误是一个终端,那么把指定的命令写给标准错误的所有输出作为标准输出重定向到相同的文件描述符。


http://chatgpt.dhexx.cn/article/MnZ3lXmi.shtml

相关文章

Failed to ignore SIGHUP: No error

memcache下载:https://www.runoob.com/memcached/window-install-memcached.html 下载下来需要install一下: c:\memcached\memcached.exe -d install c:\memcached\memcached.exe -d start c:\memcached\memcached.exe -d stop 然后报错: 我下载的版本是1.4.5按照网上说的: 以…

安装Memcached:Failed to ignore SIGHUP: No error 解决方式

Memcached安装1.4.5 版本 管理员运行cmd&#xff0c;出现如下错误&#xff1a; 解决方式&#xff1a; 命令行中输入schtasks /create /sc onstart /tn memcached /tr "c:\memcached\memcached.exe -m 512",回车 注意&#xff1a;c:\memcached\memcached.exe替换自己…

系统信号(SIGHUP ,SIGPIPE,SIGURG)

对于信号的介绍&#xff0c;我再前面的一篇博客中做过专门的总结&#xff0c;感兴趣的可以看看。本文主要介绍在网络编程中几个密切相关的函数&#xff1a;SIGUP&#xff0c;SIGPIPE&#xff0c;SIGURG。 SIGHUP信号 在介绍SIGHUP信号之前&#xff0c;先来了解两个概念&#x…

PostgreSQL参数重载信号SIGHUP的处理

前边讲过&#xff0c;配置文件重载可以使用SIGHUP信号&#xff0c;也可以使用 pg_ctl reload&#xff0c;后者实际上也是发送SIGHUP给postmaster。 1、postmaster 的SIGHUP处理 下边的代码位于 src/backend/postmaster/postmaster.c 中的函数 SIGHUP_handler&#xff1a; erepo…

Unix/Linux编程:SIGHUP信号

当会话首进程打开了一个控制终端之后它同时也成为了该终端的控制进程&#xff1b;当一个控制进程失去其终端连接后&#xff0c;内核会向其发送一个SIGHUP信号来通知它这一事实(还会发送一个SIGCONT信号以确保当该进程之前被一个信号停止时重新开始该进程)。一般来讲&#xff0c…

Linux(程序设计):59---SIGHUP、SIGPIPE、SIGURG信号处理(附SIGURG信号处理普通数据与外带数据案例)

本文介绍3个与网络编程有关的3个信号 一、SIGHUP信号处理 信号产生的情景&#xff1a; 1.如果终端接口检测到一个连接断开&#xff0c;则将此信号送给与该终端相关的控制进程&#xff08;会话首进程&#xff09; 此信号被送给session结构中s_leader字段所指向的进程。仅当终端…

图解sql server 命令行工具sqlcmd的使用

一 操作实例 安装了sql server后此工具已经有了&#xff1b; 以sa登录&#xff1b; 打个命令&#xff0c;没反映&#xff1b; 可执行操作系统命令&#xff1b;加上!!即可&#xff1b; 查看帮助&#xff1b; 再打命令&#xff0c;也没反映&#xff1b;查询结果不显示&#xff1…

在ubuntu中使用命令行工具sqlcmd连接sql server数据库

步骤&#xff1a; 首先安装sqlcmd工具 注意&#xff1a;如果你连接的用户是 root用户&#xff0c;命令中带有 sudo 的&#xff0c;sudo都可以酌情去掉&#xff0c;不行再加上 1 安装curl软件包&#xff1a; sudo apt install curl 2 导入公共存储库 GPG 密钥 curl https:…

ssms,新建查询设置字体_如何在SSMS查询编辑器中使用SQLCMD命令

ssms,新建查询设置字体 SQLCMD Mode allows creating, testing, executing SQLCMD commands or scripts in SQL Server Management Studio directly in the query editor. This option is available since SQL Server 2005. SQLCMD模式允许直接在查询编辑器中在SQL Server Man…

使用SQLCMD在SQLServer执行多个脚本

使用SQLCMD在SQLServer执行多个脚本 概述&#xff1a; 作为DBA&#xff0c;经常要用开发人员提供的SQL脚本来更新正式数据库&#xff0c;但是一个比较合理的开发流程&#xff0c;当提交脚本给DBA执行的时候&#xff0c;可能已经有几百个sql文件&#xff0c;并且有执行顺序&…

sqlcmd命令执行大的SQL脚本

前言 这两天从服务器导出一个150多MB的脚本文件&#xff0c;导入到我本地的SQLServer数据库中时&#xff0c;直接打开执行提示内存不足的错误&#xff0c;于是google搜索发现微软针对此类情况有不少命令行工具&#xff0c;其中有一款sqlcmd 实用工具&#xff0c;官方文档地址为…

sql安装弹出sqlcmd_使用SQL Server命令行(sqlcmd)

sql安装弹出sqlcmd 介绍 (Introduction) Sqlcmd allows executing queries, T-SQL sentences and SQL Server scripts using the command line. Sqlcmd允许使用命令行执行查询&#xff0c;T-SQL语句和SQL Server脚本。 In the previous article How to work with the command…

SQL Server Management Studio 查询中使用 SQLCMD 模式

从 SQL Server 2005 开始&#xff0c;可以在 SQL Server Management Studio 查询编辑器中使用 SQLCMD 模式执行 TSQL。要在查询编辑器中编写或编辑 SQLCMD 脚本&#xff0c;需要启用 SQLCMD 模式。默认情况下&#xff0c;此模式是关闭的。 若要启用 SQLCMD 模式&#xff0c;请单…

sqlcmd去掉表头和X行受影响

使用sql语句导出到文件 sqlcmd -d test01 -U test01 -P test01 -S testdb.database.windows.net -Q "select * from test01" -o "test01.csv" -s "," -W -h-1 -k1 -d:数据库名 -U 用户名 -P 密码 -S 服务器名 -Q 执行查询后退出 -o 输出…

sqlcmd 命令

SQLCMD的介绍 文章转载自&#xff1a;http://blog.sina.com.cn/s/blog_3eec0ced0100mhm2.html 最近经常用到超过80M *.sql文件的导入问题。 上网找了一下&#xff0c;发现超过80M的文件是不能在查询分析器中执行的。 找了些解决方案&#xff0c;个人感觉最简单的方法就是这个…

cmd执行服务器sql文件命令行,Dos命令提示符下 - 用sqlcmd执行*.sql语句

Dos命令提示符下 - 用sqlcmd执行*.sql语句 1)在Dos命令下执行sqlcmd命令(当然事先需要将sqlcmd增加到环境变量中去), 2)下面白色部分替换为服务器名或计算机名即可 sqlcmd -S (local) -U sa -P 123 -d testdb -i C:\temp\data.sql 参数说明:-S 服务器地址 -U 用户名 -P 密码…

sql安装弹出sqlcmd_SQL Server中SQLCMD实用工具概述

sql安装弹出sqlcmd This article is aimed at helping you understand the sqlcmd utility. Of course, this is a tool most of us have used it at several occasions given that the tool has been around for a decade now. However, to be a solid starting point, this a…

SQLServer知识:sqlcmd用法笔记

今天给大家介绍sqlcmd用法笔记&#xff0c;希望对大家能有所帮助&#xff01; 1、介绍 sqlcmd是一个 Microsoft Win32 命令提示实用工具&#xff0c;可以通过该命令工具实现SQL语句、脚本的执行&#xff0c;并且可以实现脚本任务的自动化。 2、使用场景 2.1 针对大文件脚本的执…

Sqlcmd使用详解

Sqlcmd实用工具&#xff0c;可以输入 TRANSACT-SQL 语句、 系统过程和脚本文件&#xff0c;通过各种可用模式&#xff1a; 通过命令提示符。在中查询编辑器在 SQLCMD 模式下。在 Windows 脚本文件。在 SQL Server 代理作业的操作系统 (Cmd.exe) 作业步骤。 该实用工具使用 OD…

如何在CMD下写SQL语句

1、WinX->搜索环境变量 2、选择环境变量 3、在系统变量中找到Path&#xff0c;并双击进入 4、选择新建 5、选择安装MySQL的盘&#xff0c;找到bin&#xff0c;并复制路径到刚刚新建的Path中&#xff0c;例如笔者安装的盘是D盘 6、把复制好的路径放到Path中 7、WinR->直…