前言
对于守护进程,因为它没有控制终端,所以不能往标准出错上面打印。
在很多工作站上,控制台设备运行一个窗口系统,我们不希望所有守护进程都写到控制台设备上。
我们也不希望每个守护进程都单独的写到一个文件里面。
对系统管理员来说,如果要去各个守护进程的文件中查看日志,将是一件很头疼的事情。
所以,我们需要集中的管理守护进程的出错信息。
因此Linux使用syslogd将所有的日志信息集中的管理起来。
整体架构如图所示:
从上面可以看到日志有3个来源:
1. 内核中的日志信息被klogd daemon程序读取,然后转发给syslogd daemon程序。
2. 应用程序调用syslog函数来产生日志信息。
3. 本地主机的应用程序或者来自网络上的其它程序,可以向端口514发送UDP报文来产生日志信息。
syslogd守护进程会处理上面3种类型的日志信息。
syslogd守护进程在启动时候,通常会去读/etc/syslog.conf配置文件,该文件决定了不同类型的消息应该怎么处理。
例如:紧急消息可发给系统管理员,并在控制台上面显示出来,而警告消息则可记录在文件中。
应用程序日志
相关函数如下
#include <syslog.h>
/**
* 初始化log相关的属性
* @param ident log的标志,一般指定为程序的名字,将会出现在每一条log中。
* @param option 设置一些可选的配置信息。所有可选的配置说明见表13-1.
* @param facility 指定日志的类型。所有的类型说明见表13-2.
*/
void openlog(const char *ident, int option, int facility);
/**
* 产生日志消息
* @param priority 日志的类型和级别。所有的级别见表13-3。
* @param format 日志的内容。format中的每一个%m会被替换为strerror(errno)对应的字符串。
*/
void syslog(int priority, const char *format, ...);
/**
* 关闭所有syslog打开的描述符
*/
void closelog(void);
/**
* 设置进程优先级屏蔽字,返回调用之前的屏蔽字。
* @param maskpri 新的掩码
* @return 返回上一次的掩码
*/
int setlogmask(int maskpri);
调用openlog是可选的,如果不调用openlog,那么在第一次调用syslog时会自动调用openlog。
调用closelog也是可选的。它只是关闭用于与syslogd守护进程通信的文件描述符。
实 例
在一个行式打印机中,可能存在如下的log输出函数:
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "open error for %s: %m", filename);
openlog将ident设置为程序的名字lpd,option指定每一次都输出进程的pid,facility指定为行式打印机系统。
syslog指定输出级别为LOG_ERR,然后跟上输出的内容。其中%m被替换为strerror(errno)对应的字符串。
若不调用openlog,直接调用syslog形式可能是:
syslog(LOG_ERR | LOG_LPR, "open error for %s: %m", filename);
在syslog的priority中同时指定打印级别和类型。
除了syslog很多平台还提供一种变体处理可变参数列表的方法。
#include <syslog.h>
#include <stdarg.h>
void syslog(int priority, const char *format, va_list arg);
内核日志
内核使用printk产生日志消息,比如:
printk("<5>This is kernel log message");
或者
printk(KERN_NOTICE "This is kernel log message");
其中的<5>和KERN_NOTICE表示日志的级别,在klogd中会去解析日志级别,做不同的处理。
在Linux 2.6.39中的include/linux/printk.h中定义了日志的级别。
#define KERN_EMERG "<0>" /* system is unusable */
#define KERN_ALERT "<1>" /* action must be taken immediately */
#define KERN_CRIT "<2>" /* critical conditions */
#define KERN_ERR "<3>" /* error conditions */
#define KERN_WARNING "<4>" /* warning conditions */
#define KERN_NOTICE "<5>" /* normal but significant condition */
#define KERN_INFO "<6>" /* informational */
#define KERN_DEBUG "<7>" /* debug-level messages */