与守护进程有关的一个问题是如何处理出错消息。因为它没有控制终端,所以不能只是简单地写到标准出错上,我们希望
有一个集中的守护进程出错记录设施。
自4.2BSD以来,BSD syslog设施得到了广泛应用。大多数守护进程使用这一设施。下图显示了syslog设置的详细组织结构;
有三种方法产生日志消息:
1.内核例程可以调用log函数。任何一个进程通过打开然后读/dev/klog设备就可以读取这些消息。
2.大多数用户进程调用syslog函数产生日志消息。这使消息发送至UNIX域数据报套接字/dev/log。
3.在此主机上的一个用户进程,或通过TCP/IP网络连接到此主机的其他主机上的一个用户进程可日志消息发给UDP端口514,
注意,syslog函数并不产生这些UDP数据报,而是要求产生此日志消息的进程进行显式地网络编程。
syslog函数如下:
#include <syslog.h> void openlog(const char *ident, int option, int facility); void syslog(int priority, const char *format, ...); void closeflag(void); int setlogmask(int maskpri); //前日志记录优先级屏蔽值。
调用openlog是可选择的。如果不调用openlog,则在第一次调用syslog时,自动调用openlog。调用closelog也是可选择的,
它只是关闭曾被用于与syslog守护进程通信的描述符。
调用openlog使我们可以指定一个ident,将它加入到每则日志消息中。ident一般是程序的名称。option参数的说明如下(可以
将多个参数进行与运算)
facility参数可以选取下表中的值。
如果不调用openlog,或者以facility为0来调用它,那么在调用syslog时,可以将facility作为priority参数的一部分来进行说明。
调用syslo*生一个日志消息,其priority参数是facility和level的组合,它们可选取的值分别位于上表和下表中。
setlogmask函数用于设置进程的记录优先级屏蔽字。它返回调用它之前的屏蔽字。当设置了记录优先级屏蔽字时,除非
消息的优先级已在记录优先级屏蔽字中设置,否则消息不被记录。
大多数syslog实现将使消息短时间处于队列中。如果在此段时间中到达了重复消息,那么syslog守护进程将不会把它写到日志
记录中,而是答应输出一条消息。类似于“上一条消息重复N次”
实践:
我们将为自己的应用程序指定特定的日志文件。首先修改配置文件/etc/rsyslog.d/50-default.conf(ubuntu),添加以下配置:
user.info /var/log/user.log
重新rsyslog服务:
/etc/init.d/rsyslog restart
写log的代码如下:
#include <syslog.h> int main(int argc, char **argv) { openlog("yantest", LOG_CONS|LOG_PID, 0); syslog(LOG_USER|LOG_INFO, "This is a syslog test debug message generated by program %s", argv[0]); closelog(); return 0; }运行结果:
root@yanwenjie-vm:/home/yan/apue# cat /var/log/user.log
Jan 6 21:49:57 yanwenjie-vm yantest[5741]: This is a syslog test message generated by program ./a.out