文章目录
1. 前言
The GNU C Library Reference Manual for version 2.35
2. 系统日志
Syslog
本章描述了用于发布和记录系统管理感兴趣的消息的工具。本章与向自己的用户发布消息或保留私人日志的程序无关(通常会使用输入/输出流中描述的工具来做到这一点)。
大多数系统都有一个称为“Syslog”的工具,它允许程序向系统管理员提交感兴趣的消息,并且可以配置为以各种方式传递这些消息,例如在控制台上打印、邮寄给特定的人或记录在 日志文件以供将来参考。
程序使用本章中的工具来提交此类消息。
2.1. Syslog概述
Overview of Syslog
系统管理员必须处理来自每个系统内大量子系统的大量不同类型的消息,而且通常还有很多系统。例如,FTP 服务器可能会报告它获得的每个连接。内核可能会报告磁盘驱动器上的硬件故障。DNS 服务器可能会定期报告使用情况统计信息。
其中一些消息需要立即引起系统管理员的注意。它可能不仅仅是任何系统管理员——可能有一个特定的系统管理员来处理特定类型的消息。如果出现问题,只需记录其他消息以备将来参考。还有一些人可能需要通过自动生成月度报告的过程从中提取信息。
为了处理这些消息,大多数 Unix 系统都有一个称为“Syslog”的工具。它通常基于一个名为“Syslogd”的守护进程,Syslogd 在名为 /dev/log 的 Unix 域套接字上侦听消息。根据消息中的分类信息及其配置文件(通常是 /etc/syslog.conf),Syslogd 以各种方式路由它们。一些流行的路由是:
- 写入系统控制台
- 给特定用户的邮件
- 写入日志文件
- 传递给另一个守护进程
- 丢弃
Syslogd 还可以处理来自其他系统的消息。它在 syslog UDP 端口以及本地套接字上侦听消息。
Syslog 可以处理来自内核本身的消息。但是内核不写入/dev/log;相反,另一个守护进程(有时称为“Klogd”)从内核中提取消息并将它们传递给 Syslog,就像任何其他进程一样(并将它们正确识别为来自内核的消息)。
Syslog 甚至可以处理内核在 Syslogd 或 Klogd 运行之前发出的消息。例如,Linux 内核将启动消息存储在内核消息环中,并且当 Klogd 稍后启动时它们通常仍然存在。假设 Syslogd 在 Klogd 启动时正在运行,然后 Klogd 会将消息环中的所有内容传递给它。
为了对消息进行分类以进行处置,Syslog 要求任何向其提交消息的进程提供两条分类信息:
facility
这标识了谁提交了消息。定义了少量设施。内核、邮件子系统和 FTP 服务器是公认设施的示例。有关完整列表,请参阅 syslog、vsyslog。请记住,这些本质上是任意分类。“邮件子系统”没有系统管理员赋予它的任何意义。
priority
这说明了消息内容的重要性。定义的优先级值的示例有:调试、信息、警告和关键。有关完整列表,请参阅 syslog、vsyslog。除了优先级有明确的顺序之外,每个优先级的含义完全由系统管理员决定。
“facility/priority”是表示设施和优先级的数字。
警告:这个术语并不通用。有些人用“级别”来指代优先级,用“优先级”来指代设施和优先级的组合。Linux 内核有一个消息“级别”的概念,它对应于 Syslog 优先级和 Syslog 设施/优先级(这可能是因为内核的设施代码为零,这使得优先级和设施/优先级相同的值)。
GNU C 库提供了向 Syslog 提交消息的函数。他们通过写入 /dev/log 套接字来做到这一点。请参阅提交系统日志消息。
GNU C 库函数仅用于向同一系统上的 Syslog 工具提交消息。要将消息提交到另一个系统上的 Syslog 工具,请使用套接字 I/O 功能将 UDP 数据报写入该系统上的 syslog UDP 端口。请参阅套接字。
2.2. 提交系统日志消息
Submitting Syslog Messages
GNU C 库提供了将消息提交到 Syslog 工具的函数:
这些功能仅用于将消息提交到同一系统上的 Syslog 工具。要将消息提交到另一个系统上的 Syslog 工具,请使用套接字 I/O 功能将 UDP 数据报写入该系统上的 syslog UDP 端口。请参阅套接字。
2.2.1. 打开日志
openlog
本节中提到的符号在文件 syslog.h 中声明。
函数:void openlog (const char *ident, int option, int facility)
Preliminary: | MT-Safe | AS-Unsafe lock | AC-Unsafe lock fd | See POSIX Safety Concepts.
openlog 打开或重新打开到 Syslog 的连接以准备提交消息。
ident 是一个任意标识字符串,未来的系统日志调用将作为每条消息的前缀。这是为了识别消息的来源,人们通常将其设置为将提交消息的程序的名称。
如果 ident 为 NULL,或者未调用 openlog,则 Syslog 消息中使用的默认标识字符串将是程序名称,取自 argv[0]。
请注意,字符串指针 ident 将由 Syslog 例程在内部保留。您不能释放 ident 指向的内存。传递对自动变量的引用也是危险的,因为离开范围意味着结束变量的生命周期。如果要更改 ident 字符串,必须再次调用 openlog;覆盖 ident 指向的字符串不是线程安全的。
您可以通过调用 closelog 使 Syslog 例程删除对 ident 的引用并返回到默认字符串(程序名称取自 argv[0]):请参阅 closelog。
特别是,如果您正在为可能会被加载然后卸载的共享库(例如 PAM 模块)编写代码,并且您使用 openlog,则必须在库可能被卸载的任何点之前调用 closelog,如下例所示:
#include <syslog.h>
void
shared_library_function (void)
{
openlog ("mylibrary", option, priority);
syslog (LOG_INFO, "shared library has been invoked");
closelog ();
}
如果没有调用 closelog,如果库被卸载并且包含字符串“mylibrary”的内存变得未映射,则使用共享库的程序将来调用 syslog 可能会崩溃。这是 BSD syslog 接口的限制。
openlog 可能会也可能不会打开 /dev/log 套接字,具体取决于选项。如果是这样,它会尝试打开它并将其作为流套接字连接。如果这不起作用,它会尝试打开它并将其作为数据报套接字连接。套接字具有“Close on Exec”属性,因此如果进程执行 exec,内核将关闭它。
您不必使用 openlog。如果您在没有调用 openlog 的情况下调用 syslog,则 syslog 只会隐式打开连接并使用 ident 和 options 中的信息的默认值。
options 是一个位字符串,位由以下单个位掩码定义:
LOG_PERROR
如果打开,openlog 会设置连接,以便此连接上的任何 syslog 除了将其提交到 Syslog 之外,还将其消息写入调用进程的标准错误流。如果关闭,系统日志不会将消息写入标准错误。
LOG_CONS
如果打开,openlog 会设置连接,以便此连接上的 syslog 无法向 Syslog 提交消息,而是将消息写入系统控制台。如果关闭,syslog 不会写入系统控制台(当然 Syslog 可能会将收到的消息写入控制台)。
LOG_PID
打开时,openlog 会建立连接,以便此连接上的 syslog 将调用进程的进程 ID (PID) 插入到消息中。关闭时,openlog 不会插入 PID。
LOG_NDELAY
打开时,openlog 打开并连接 /dev/log 套接字。关闭时,未来的系统日志调用必须打开并连接套接字。
可移植性说明:在早期的系统中,这个位的意义正好相反。
LOG_ODELAY
这一点什么都不做。它的存在是为了向后兼容。
如果选项中的任何其他位打开,则结果未定义。
设施是此连接的默认设施代码。此连接上指定默认设施的系统日志会导致此设施与消息相关联。有关可能的值,请参见 syslog。零值表示默认值,即 LOG_USER。
如果在调用 openlog 时 Syslog 连接已经打开,openlog 会“重新打开”连接。重新打开就像打开一样,除了如果您将默认设施代码指定为零,则默认设施代码将保持不变,如果您指定 LOG_NDELAY 并且套接字已经打开并连接,openlog 就会保持这种状态。
2.2.2. 系统日志
syslog、vsyslog
本节中提到的符号在文件 syslog.h 中声明。
函数:void syslog (int facility_priority, const char *format, ...)
Preliminary: | MT-Safe env locale | AS-Unsafe corrupt heap lock dlopen | AC-Unsafe corrupt lock mem fd | See POSIX Safety Concepts.
syslog 向 Syslog 工具提交消息。它通过写入 Unix 域套接字 /dev/log 来做到这一点。
syslog 使用 facility_priority 指示的设施和优先级提交消息。宏 LOG_MAKEPRI 从设施和优先级生成设施/优先级,如下例所示:
LOG_MAKEPRI(LOG_USER, LOG_WARNING)
设施代码的可能值是(宏):
LOG_USER
杂项用户进程
LOG_MAIL
邮件
LOG_DAEMON
杂项系统守护进程
LOG_AUTH
安全(授权)
LOG_SYSLOG
系统日志
LOG_LPR
中央打印机
LOG_NEWS
网络新闻(例如 Usenet)
LOG_UUCP
UUCP
LOG_CRON
Cron 和 At
LOG_AUTHPRIV
私人保安(授权)
LOG_FTP
FTP服务器
LOG_LOCAL0
本地定义
LOG_LOCAL1
本地定义
LOG_LOCAL2
本地定义
LOG_LOCAL3
本地定义
LOG_LOCAL4
本地定义
LOG_LOCAL5
本地定义
LOG_LOCAL6
本地定义
LOG_LOCAL7
本地定义
如果设施代码是其他任何内容,则结果未定义。
注意:syslog 识别另一种设施代码:内核代码。但是您不能使用这些函数指定该设施代码。如果您尝试,它看起来与 syslog 相同,就好像您正在请求默认工具一样。但无论如何你都不想这样做,因为任何使用 GNU C 库的程序都不是内核。
您可以只使用优先级代码作为 facility_priority。在这种情况下,syslog 假定打开 Syslog 连接时建立的默认设施。请参阅系统日志示例。
优先级代码的可能值是(宏):
LOG_EMERG
消息说系统无法使用。
LOG_ALERT
必须立即对消息采取行动。
LOG_CRIT
该消息表明情况危急。
LOG_ERR
该消息描述了一个错误。
LOG_WARNING
该消息是一个警告。
LOG_NOTICE
该消息描述了一个正常但重要的事件。
LOG_INFO
该消息纯粹是信息性的。
LOG_DEBUG
该消息仅用于调试目的。
如果优先级代码是其他代码,则结果未定义。
如果该进程当前没有打开 Syslog 连接(即,它没有调用 openlog),则 syslog 会像 openlog 一样隐式打开连接,对于否则将包含在 openlog 调用中的信息具有以下默认值: 默认值标识字符串是程序名称。默认的默认设施是 LOG_USER。options 中所有连接选项的默认设置就像这些位关闭一样。syslog 使 Syslog 连接保持打开状态。
如果 /dev/log 套接字未打开并连接,则 syslog 打开并连接它,与带有 LOG_NDELAY 选项的 openlog 相同。
syslog 使 /dev/log 保持打开并连接,除非它尝试发送消息失败,在这种情况下 syslog 将其关闭(希望未来的隐式打开会将 Syslog 连接恢复到可用状态)。
例子:
#include <syslog.h>
syslog (LOG_MAKEPRI(LOG_LOCAL1, LOG_ERROR),
"Unable to make network connection to %s. Error=%m", host);
函数:void vsyslog (int facility_priority, const char *format, va_list arglist)
Preliminary: | MT-Safe env locale | AS-Unsafe corrupt heap lock dlopen | AC-Unsafe corrupt lock mem fd | See POSIX Safety Concepts.
这在功能上与 syslog 相同,带有 BSD 样式的可变长度参数。
2.2.3. 关闭日志
closelog
本节中提到的符号在文件 syslog.h 中声明。
函数:void closelog (void)
Preliminary: | MT-Safe | AS-Unsafe lock | AC-Unsafe lock fd | See POSIX Safety Concepts.
closelog 关闭当前的 Syslog 连接,如果有的话。这包括关闭 /dev/log 套接字(如果它是打开的)。如果使用 ident 的非 NULL 参数调用 openlog,则 closelog 还将 Syslog 消息的标识字符串设置回默认值。默认标识字符串是取自 argv[0] 的程序名称。
如果您正在编写使用 openlog 生成自定义 syslog 输出的共享库代码,您应该在完成后使用 closelog 删除 GNU C 库对 ident 指针的内部引用。请阅读有关 openlog 的部分以获取更多信息:请参阅 openlog。
closelog 不会刷新任何缓冲区。在使用 openlog 重新打开 Syslog 连接之前,您不必调用 closelog。系统日志连接在执行或退出时自动关闭。
2.2.4. 设置日志掩码
setlogmask
本节中提到的符号在文件 syslog.h 中声明。
函数:int setlogmask (int mask)
Preliminary: | MT-Unsafe race:LogMask | AS-Unsafe | AC-Safe | See POSIX Safety Concepts.
setlogmask 设置一个掩码(“logmask”),用于确定哪些未来的系统日志调用应被忽略。如果程序没有调用 setlogmask,syslog 不会忽略任何调用。您可以使用 setlogmask 指定将来应忽略特定优先级的消息。
setlogmask 调用会覆盖任何先前的 setlogmask 调用。
请注意,日志掩码的存在完全独立于 Syslog 连接的打开和关闭。
设置日志掩码与配置 Syslog 的效果相似,但又不同。Syslog 配置可能会导致 Syslog 丢弃它收到的某些消息,但 logmask 会导致某些消息一开始就永远不会提交给 Syslog。
掩码是一个位串,其中一个位对应于每个可能的消息优先级。如果该位打开,syslog 会正常处理该优先级的消息。如果它关闭,syslog 会丢弃该优先级的消息。使用 syslog、vsyslog 和 LOG_MASK 中描述的消息优先级宏来构造适当的掩码值,如下例所示:
LOG_MASK(LOG_EMERG) | LOG_MASK(LOG_ERROR)
或者
~(LOG_MASK(LOG_INFO))
还有一个 LOG_UPTO 宏,它为某个优先级和高于它的所有优先级生成一个掩码:
LOG_UPTO(LOG_ERROR)
宏的不幸命名是因为在内部,较大的数字用于较低的消息优先级。
2.2.5. 系统日志示例
以下是 openlog、syslog 和 closelog 的示例:
此示例设置日志掩码,以便调试和信息性消息被丢弃,而不会到达 Syslog。所以示例中的第二个系统日志什么都不做。
#include <syslog.h>
setlogmask (LOG_UPTO (LOG_NOTICE));
openlog ("exampleprog", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
syslog (LOG_NOTICE, "Program started by User %d", getuid ());
syslog (LOG_INFO, "A tree falls in a forest");
closelog ();