Linux -- 多进程编程之 - 守护进程的出错处理

  书接上文守护进程的基础知识,这一篇继续来说明守护进程相关的出错处理。

四、守护进程的出错处理

  因为守护进程完全脱离终端控制,所以不能像其它进程一样将错误信息输出到控制终端。所以如何处理错误消息是一个问题。在Linux系统中,一般通用的办法是使用syslog服务,将程序中出错信息输入到系统日志文件中(如"/var/log/messages",此文件需要用用root权限的用户查看),从而可以直观地看到程序的问题所在。在不同的Linux发行版中,系统日志的文件路径全名可能有所不同(比如可能是"/var/log/syslog")

  syslog 是Linux系统日志管理服务,通过守护进程 syslogd 来维护。改守护进程在启动时会读取一个配置文件“/etc/syslog.conf”。该文件决定了不同种类的信息会发送到何处。

  自4.2BSD依赖,BSD的syslog设施得到了广发的应用,大多数守护进程都使用这一设施。syslog的详细组织结构如图4.1所示。

图4.1 syslog的详细组织结构图

  该机制提供了 3syslog 相关的函数,分别是 openlog()、syslog()、closelog()。通常,openlog() 用来打开系统日志服务的一个连接,syslog() 函数用来想日志文件中写入消息,在这里可以规定消息的优先级,消息输出格式等,closelog() 函数用来关系系统日志服务的连接。函数的原型如下所示。

#include <syslog.h>

void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);

4.1、openlog()函数

功能:
  用于打开与程序的系统记录器的连接
参数:
  ident  :要向每个消息加入的字符串,通常为程序的名称
  option:用于指定各个选项的为屏蔽。可选的参数为:
    LOG_CONS    :如果消息无法发送到系统日志服务,则直接输出到系统控制终端上
    LOG_NDELAY:立即打开系统日志服务的连接
    LOG_NOWAIT:不要等待可能已经创建的子进程,此选项对Linux无效果
    LOG_ODELAY:与LOG_NDELAY相反,连接的打开被延迟,直到调用 syslog()
    LOG_PERROR:将消息同时发送到标准出错(stderr)上
    LOG_PID      :在每条消息中都包含进程的PID
  facility:指定程序发送的消息类型,可选的参数为:
    LOG_AUTH     :安全/授权信息
    LOG_AUTHPRIV  : 安全/授权信息(私有)
    LOG_CRON     :时间守护进程(cron 和 at)
    LOG_DAEMON   :其他系统的守护进程
    LOG_FTP      :ftp的守护进程
    LOG_KERN     :内核消息(不能从用户进程生成)
    LOG_LOCAL[0~7]:保留给本地使用
    LOG_LPR       :行打印机子系统
    LOG_MAIL      :邮件子系统
    LOG_NEWS      :新闻子系统
    LOG_SYSLOG    :syslogd()内部产生的消息
    LOG_USER(默认): 一般使用者等级消息
    LOG_UUCP      :UUCP子系统
返回:
  函数无返回

  调用 openlog() 是可选择的。假设不调用 openlog(),则在第一次调用 syslog() 时,自己主动调用 openlog()

4.2、syslog()函数

功能:
  用于把日志消息发给系统程序syslogd记录
参数:
  priority:指定消息的重要性,可有以下选项:
    LOG_EMERG  :系统无法使用
    LOG_ALERT  :需要立即采取措施
    LOG_CRIT   :有重要情况发生
    LOG_ERR    :有错误发生
    LOG_WARNING:有警告发生
    LOG_NOTICE :正常情况,但也有重要情况
    LOG_INFO   :信息消息
    LOG_DEBUG  :调试信息
  format  :以字符串指针的形式表示输出的格式,类似于printf中的格式
返回:
  函数无返回

4.3、closelog()函数

  closelog() 函数关闭用来编写系统 closelog logger 的描述符。closelog() 函数的使用是可选的,因为在程序结束后,会自动关闭与 system log 的连接。

4.4、代码示例

  借用上面创建守护进程的代码,将写入文件的功能修改成为写入到系统日志文件中,每隔2秒时间向日志文件“/daemon.log”文件中写入内容。实现的代码如下所示。

#include <fcntl.h>     // for O_APPEND ..
#include <stdio.h>     // for perror ..
#include <stdlib.h>    // for exit ..
#include <string.h>    // for strlen
#include <sys/stat.h>  // for umask
#include <sys/types.h> // for setsid
#include <syslog.h>    // for openlog ..
#include <unistd.h>    // for setsid

int main(int argc, const char *argv[])
{
    pid_t pid = 0, sid = 0;

    /* 创建子进程,父进程退出 */
    pid = fork();
    if (pid == -1) /* fork出错 */
    {
        perror("fork error");
        exit(EXIT_FAILURE);
    }
    else if (pid == 0) /* 子进程 */
    {
        /* 打开系统日志服务器 */
        openlog("daemon.syslog", LOG_PID, LOG_DAEMON);

        /* 创建新的会话 */
        if ((sid = setsid()) < 0)
        {
            /* 向系统日志服务器写入错误信息 */
            syslog(LOG_ERR, "%s\n", "setsid() error");
            exit(EXIT_FAILURE);
        }

        /* 改变当前的工作路径 */
        if ((sid = chdir("/")) < 0)
        {
            syslog(LOG_ERR, "%s\n", "chdir() error");
            exit(EXIT_FAILURE);
        }

        /* 改变进程本身的umask */
        umask(0);
        /* 关闭所有可能已打开的文件描述符 */
        int num = getdtablesize(); /* 获取当前进程文件描述符表大小 */
        for (i = 0; i < num; i++)
        {
            close(i);
        }

        /* 周期计数的变量 */
        int cycleCnt = 0;

        /* 至此,守护进程创建完成,以下正式开始守护进程的工作 */
        while (1)
        {
            /* 周期运行计数自加 */
            cycleCnt++;
            /* 写入到系统日志中 */
            syslog(LOG_NOTICE, "I'm Daemon Process, Running %d", cycleCnt);
            /* 休眠片刻 */
            sleep(2);
        }
    }
    else /* 父进程 */
    {
        /* 父进程退出 */
        exit(EXIT_SUCCESS);
    }
    /* 关闭系统日志服务器 */
    closelog();
    return 0;
}

  编译并运行上述程序,输入指令 ps -ajx | grep "./syslog" 查看对应的进程状态,使用指令 cat /var/log/syslog 查看系统日志,总体显示效果图4.2所示。

图4.2 syslog的测试显示效果图

  好啦,废话不多说,总结写作不易,如果你喜欢这篇文章或者对你有用,请动动你发财的小手手帮忙 **点个赞**,当然 **关注一波** 那就更好了,就到这儿了,么么哒(*  ̄3)(ε ̄ *)。

上一篇:Linux – 多进程编程之 - 守护进程
下一篇:Linux – 多线程编程之 - 基础实现一

  • 19
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青椒*^_^*凤爪爪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值