Java教程

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

本文主要是介绍守护进程与系统日志配合使用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

守护进程

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

守护进程一般是一个会话的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

这篇关于守护进程与系统日志配合使用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!