ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

守护进程与系统日志配合使用

2021-05-01 21:59:27  阅读:252  来源: 互联网

标签:LOG pid syslog 系统日志 进程 日志 守护


守护进程

某些服务需要一直在后台跑

守护进程一般是一个会话的Leader,也是一个进程组的Leader。
一个session(会话)中存在多个进程,前台进程组,后台进程组。最多只有一个前台进程组,可以没有。只有前台进程组能使用标准输入输出

守护进程的特点
setsid();//创建一个会话,并设置进程组ID。
只有子进程才能创建会话,调用方会成为新的会话的leader,会成为当前新的进程组的leader,并脱离控制终端。
执行ps axj命令:
守护进程的tty为’?’,sid,pgid,pid相同。如果创建的子进程是守护进程,那么其父进程不会一直等,
所以守护进程的ppid为1。(不一定,ubuntu较新的发行版都用 upstart 代替 init 来收养孤儿进程。)


几个进程组函数:

int setpgid(pid_t pid, pid_t pgid); //将指定pid号的进程放到pgid进程组
pid_t getpgid(pid_t pid); //返回指定pid号的进程的进程组id,为0时返回当前进程id
pid_t getpgrp(void); //返回当前进程的进程组id,POSIX.1方言
pid_t getpgrp(pid_t pid); //查看某个进程的进程组id,BSD方言

单实例守护进程:锁文件/var/run/name.pid ,记录了某些守护进程的pid。
(一些守护进程如sshd、rsyslogd,同一时间只能跑一份,利用锁文件来完成单实例守护进程的控制)
启动脚本文件:/etc/rc*…,人为将某个守护进程添加到启动项

系统日志文件 /var/log

“每个系统服务都有必要写系统日志,但我又不能让人人都写” --> 权限分隔层
root将写系统日志的权限交给syslogd服务,所有要写系统日志的进程都将日志信息提交syslogd, 由syslogd统一地接收、写系统日志。

相关函数:

#include <syslog.h>
openlog(); //与syslog关联
syslog(); //提交
closelog();

①函数原型:void openlog(const char *ident, int option, int facility);
 ident:可以是任何字段,一般是程序名字
 option:一些控制标志,如LOG_PID表示每条日志信息包含PID;LOG_PERROR表示同时将error信息打印到stderr
 facility:提交日志信息的服务类型,也可以说是日志信息来源;
如LOG_DAEMON表示系统守护进程的日志,LOG_FTP表示是FTP的日志信息

②函数原型:void syslog(int priority, const char *format, …);
priority:是facility或上level的结果,level是级别,如LOG_ERR,LOG_WARNING,LOG_INFO
 format:类似printf的格式,不用’\n’,因为我们只是提交信息,由syslogd服务实际写日志。

/var/log/syslog记录了系统大部分日志信息
/etc/rsyslog.conf为syslog配置文件,如约定level>LOG_INFO才往日志中写信息。


程序实例

创建一个守护进程,守护进程负责不断往/tmp/out中写数字;并将程序中的错误提交系统日志。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <syslog.h>

#define FNAME "/tmp/out"

static int creatdaemon(void)
{
    int fd;
    pid_t pid;
    pid = fork();

    if(pid < 0)
        return -1; //fork失败

    if(pid > 0)
    {
        //printf("[%d]:parent exit\n",pid);
        exit(0); //父进程直接退出
    }


    //printf("[%d]:child is working\n",pid);
    fd = open("/dev/null",O_RDWR);
    if(fd < 0) 
        return -2;  //open失败

    //脱离控制终端,将0,1,2重定向到/dev/null
    dup2(fd,0);
    dup2(fd,1);
    dup2(fd,2);
    close(fd);
    
    setsid();
    chdir("/");//守护进程一直在跑,最好就将PWD切换成根,因为根是一直存在的 
    return 0;
}
static void daemontask(void)
{
    int i = 0;
    FILE *fp;

    fp = fopen(FNAME,"w");
    if(fp == NULL)
    {
        syslog(LOG_ERR,"fopen() failed!");
        exit(1);
    }

    while(1)
    {
        fprintf(fp,"%d\n", i++);
        fflush(fp); //文件是全缓冲,要刷新缓冲区
        sleep(1);
    }
    fclose(fp);
}

int main(int argc, char **argv)
{
    int ret = 0;
    openlog("mydaemon",LOG_PID,LOG_DAEMON);//关联syslog,想要写日志的人物为mydaemon,日志包含其
pid,日志的来源为守护进程

    ret = creatdaemon();
    if(ret < 0)
    {
        syslog(LOG_ERR,"creatdaemon() failed!");
        if(ret == -1)
            syslog(LOG_ERR,"fork() failed!");
        if(ret == -2)
            syslog(LOG_ERR,"open() failed!");

        exit(1);
    }
    else
        syslog(LOG_INFO,"creatdaemon() success!");

    daemontask();

    exit(0);
}

测试运行:

①先将文件设置为不可写:chmod u-w /tmp/out
②运行程序并检查守护进程是否创建成功

③查看系统日志文件/var/log/syslog

标签:LOG,pid,syslog,系统日志,进程,日志,守护
来源: https://blog.csdn.net/weixin_43796767/article/details/116333413

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有