Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1745188
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: 系统运维

2012-04-01 17:59:20

守护进程的一个问题是如何处理错误消息。它不能简单地向标准错误输出,因为它没有一个控制终端。我们不想所有的守护进程写到控制台设备,因为在许多 工作站上,控制台设备运行一个窗口系统。我们也不想每个进程把它自己的错误写入分开的文件里。对任何管理系统的人来说,追踪哪个守护进程写到哪个记录文件 并在日常基础上检查这些文件,是件头疼的事。我们需要一个集中的守护进程错误记录的设施。


BSD的syslog设施在Berkeley被开发,并广泛应用在4.2BSD里。多数继承自BSD的系统都支持syslog。


直到SVR4,系统V还没有一个集中的守护进程日志设施。


syslog函数作为一个XSI扩展被SUS包含。


BSD的syslog设施自从4.2BSD被广泛应用。多数守护进程使用这个设施。下图演示了它的结构:



有三种方法来产生记录消息:


1、内核例程可以调用log函数。这些消息可以被任何open或read设备/dev/klog的用户进程读。我们不会再描述这个函数,因为我们对写内核例程不感兴趣。


2、多数用户进程(守护进程)调用syslog函数来产生日志消息。我们稍后描述它的调用序列。这导致消息被发送给UNIX域的数据报套接字/dev/log。


3、在这个主机或通过TCP/IP网络连到这个主机的其它主机上,一个用户进程可以向UDP端口514发送日志消息。注意syslog函数从不产生这些UDP数据报:它们需要产生记录消息的进程显式地网络编程。


通 常,syslogd守护进程读取这三种形式的日志消息。在启动时,守护进程读取一个配置文件,通常是/etc/syslog.conf,它决定哪些类型的 消息会被发送。例如,紧急消息可以被发送给系统管理员(如果登录的话)并在控制台打印消息,而警告可能被记录到一个文件。


我们到这个设置的接口是通过syslog函数。



  1. #include <syslog.h>

  2. void openlog(const char *ident, int option, int facility);

  3. void syslog(int priority, const char *format, ...);

  4. void closelog(void);

  5. int setlogmask(int maskpri);

  6. 返回之前日志优先级掩码值。


调用openlog是可选的。如果它不被调用,syslog第一次调用时,openlog会自动被调用。调用closelog也是可选的--它只关闭用来与syslogd守护进程通信的文件描述符。


调用openlog让我们指明一个被加入到每个日志消息的ident。这通常是程序名(cron、inetd等)。option参数是指定各种选项的一个位掩码。下表描述了可用的选项,包括XSI列里的着重号,如果选项包含在SUS里的openlog定义里。


openlog的option参数
optionXSI描述
LOG_CONS*如果日志消息不能通过UNIX域数据报发送给syslogd,那么消息被写到控制台。
LOG_NDELAY*立即打开到syslogd守护进程的UNIX域数据报套接字;不要等待到第一个消息被记录。通常,套接字直到第一个消息被记录时才被打开。
LOG_NOWAIT*不要等待可能在记录消息的进程里创建的子进程。这避免了和捕获SIGCHLD的应用的冲突,因为应用可能在syslog调用wait时已经得到子进程的状态了。
LOG_ODELAY*延迟到syslogd守护进程的连接,直到第一个消息被记录。
LOG_PERROR
除了发送给syslogd之外还向标准错误写日志消息。(Solaris上不可用。)
LOG_PID*在每个消息里记录进程ID。这是为了让fork一个子进程来处理不同请求的守护进程(和从不调用fork的守护进程相反,比如syslogd)。


openlog 的facility参数从下表中选取。注意SUS只定义了在给定平台上常用的facility代码的子集。facility参数的原因是让配置文件指明从 不同设施来的消息用不同的方式处理。如果我们不调用openlog,或我们用0的facility调用它,那么我们仍可以指定设施,作为syslog的 priority参数的一部分。


openlog的facility参数
facilityXSI描述
LOG_AUTH
身份识别程序:login、su、getty……
LOG_AUTHPRIV
和LOG_AUTH相同,但记录到严格权限的文件
LOG_CRON
cron和at
LOG_DAEMON
系统守护进程:inetd、routed、……
LOG_FTP
FTP守护进程(ftpd)
LOG_KERN
内核产生的消息
LOG_LOCAL0*为本地使用保留
LOG_LOCAL1*为本地使用保留
LOG_LOCAL2*为本地使用保留
LOG_LOCAL3*为本地使用保留
LOG_LOCAL4*为本地使用保留
LOG_LOCAL5*为本地使用保留
LOG_LOCAL6*为本地使用保留
LOG_LOCAL7*为本地使用保留
LOG_LPR
行打印机系统:lpd、lpc、……
LOG_MAIL
邮件系统
LOG_NEWS
Usenet网络新闻系统
LOG_SYSLOG
syslogd守护进程本身
LOG_USER*用户进程来的消息(默认)
LOG_UUCP
UUCP系统

我们调用syslog来产生一个记录消息。priority参数是上表所示的facility与和下表的等级的联合。这些等级通过优先级排序,由高到低。

syslog等级(排序的)
等级描述
LOG_EMERG紧急(系统不稳定)(最高优先级)
LOG_ALERT情况必须立即修复
LOG_CRIT危急情况(例如硬件设备错误)
LOG_ERR错误情况
LOG_WARNING警告情况
LOG_NOTICE普通,但重要的情况
LOG_INFO信息消息
LOG_DEBUG调试消息(最低优先级)


format参数和任何剩余的参数被传递给vspring函数来格式化。在格式里的两个字符%m的任何出现将被对应于errno值的错误消息字符串(strerror)代替。


setlogmask函数可以用来为进程设置优先级掩码。这个函数返回前一个掩码。当记录优先级掩码被设置时,消息不会被记录,除非它们的优先级在掩码里被设置。注意设置记录优先级掩码为0的尝试将没有效果。


logger程序被许多系统提供,作为向syslog设施发送记录消息的一种方法。一些实现允许这个程序的可选参数,可指定facility、level和ident,尽管SUS没有定义这些选项。logger命令是为了需要产生记录消息的外壳脚本的非交互式运行。


在一个(假设的)行打印机假脱机系统守护进程里,你可以碰到代码:
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "open error for %s: %m", filename);


第一个调用设置了ident字符串为程序名,指定进程ID应该总是被打印,并设置默认的facility为行打印系统。syslog的调用指明一个错误情况和一个消息字符串。如果我们没有调用openlog,那么第二个调用可能是:
syslog(LOG_ERR | LOG_LPR, "open error for %s: %m", filename);


这里,我们指定priority参数为等级和设施的联合。


除了syslog,许多平台提供了一个处理可变参数列表的变体。



  1. #include <syslog.h>
  2. #include <stdarg.h>

  3. void vsyslog(int priority, const char *format, va_list arg);


本文的四个平台都提供了vsyslog,但它没有包含在SUS里。


多数syslogd实现在短期把消息排队。如果一个复制的消息在这段时间内到达,那么syslog守护进程将不会把它写入到记录里。相反,守护进程会写一个类似于“上次消息重复N次”的消息。


(syslog写的消息可以在/var/log/syslog里找到。)
阅读(1487) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~