Linux守护进程、sighup与nohup详解(3)

// 创建子进程,并退出当前父进程
    if((pid = fork()) < 0){
        syslog(LOG_INFO,"sampled : fork error");
        return -1;
    }
    if ( pid != 0) {
        //  父进程直接退出
        exit(0);
    }

// 新建会话,成功返回值是会话首进程id,进程组id ,首进程id
    pid = 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的进程接管。此时的进程已经成为一个守护进程。

Linux守护进程、sighup与nohup详解

sighup与nohup

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

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

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

Linux守护进程、sighup与nohup详解

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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/f1a3a6f773e083b9c97fa8acf011a20e.html