分类: 系统运维
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函数。
调用openlog是可选的。如果它不被调用,syslog第一次调用时,openlog会自动被调用。调用closelog也是可选的--它只关闭用来与syslogd守护进程通信的文件描述符。
调用openlog让我们指明一个被加入到每个日志消息的ident。这通常是程序名(cron、inetd等)。option参数是指定各种选项的一个位掩码。下表描述了可用的选项,包括XSI列里的着重号,如果选项包含在SUS里的openlog定义里。
option | XSI | 描述 |
---|---|---|
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参数的一部分。
facility | XSI | 描述 |
---|---|---|
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系统 |
等级 | 描述 |
---|---|
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,许多平台提供了一个处理可变参数列表的变体。
本文的四个平台都提供了vsyslog,但它没有包含在SUS里。
多数syslogd实现在短期把消息排队。如果一个复制的消息在这段时间内到达,那么syslog守护进程将不会把它写入到记录里。相反,守护进程会写一个类似于“上次消息重复N次”的消息。