Skip to content

14.11 系统日志管理

本节介绍 FreeBSD 的系统日志管理。

14.11.1 配置本地日志记录

配置文件 /etc/syslog.conf 定义了 syslogd 在接收到日志条目时的处理方式。此文件通过 设施 facility级别 level 两个参数控制日志行为:

  • 设施 facility 标识消息来源的子系统(如内核或守护进程)。
  • 级别 level 表示事件的严重性。

可按 设施 facility级别 level 决定日志消息的记录位置,也可按发送消息的应用程序筛选日志消息。在远程日志记录中,还可按生成日志事件的主机名进行过滤。

该配置文件每行定义一个操作,由选择器字段和操作字段组成。

  • 选择器字段的语法是 设施.级别,匹配来自 设施 facility 且级别为 级别 level 或更高的日志消息。
    • 也可以在级别之前添加可选的比较标志,以更精确地指定记录内容。
    • 多个选择器字段可以用于同一操作
      • 以分号 (;) 分隔。
      • 使用 * 匹配所有内容。
  • 操作字段指定日志消息的发送目标,如文件或远程日志主机。

以下是 FreeBSD 默认的 /etc/syslog.conf 文件示例,其源文件为 usr.sbin/syslogd/syslog.conf

ini
#
#	Spaces ARE valid field separators in this file. However,
#	other *nix-like systems still insist on using tabs as field
#	separators. If you are sharing this file between systems, you
#	may want to use only tabs as field separators here.
#	Consult the syslog.conf(5) manpage.
*.err;kern.warning;auth.notice;mail.crit		/dev/console # ①
*.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err	/var/log/messages
security.*					/var/log/security
auth.info;authpriv.info				/var/log/auth.log
mail.info					/var/log/maillog # ②
cron.*						/var/log/cron
!-devd
*.=debug					/var/log/debug.log # ③
*.emerg						*
daemon.info					/var/log/daemon.log
# uncomment this to log all writes to /dev/console to /var/log/console.log
# touch /var/log/console.log and chmod it to mode 600 before it will work
#console.info					/var/log/console.log
# uncomment this to enable logging of all log messages to /var/log/all.log
# touch /var/log/all.log and chmod it to mode 600 before it will work
#*.*						/var/log/all.log
# uncomment this to enable logging to a remote loghost named loghost
#*.*						@loghost
# uncomment these if you're running inn
# news.crit					/var/log/news/news.crit
# news.err					/var/log/news/news.err
# news.notice					/var/log/news/news.notice
# Uncomment this if you wish to see messages produced by devd
# !devd
# *.>=notice					/var/log/devd.log # ④
!*
include						/etc/syslog.d
include						/usr/local/etc/syslog.d
  • ① 匹配所有级别为 err 及更高的消息,以及 kern.warningauth.noticemail.crit,并将这些日志消息发送到控制台(/dev/console)。

    sh
    # ls -al /dev/console
    crw-------  1 root wheel 0x8 May 16 10:09 /dev/console
  • ② 匹配来自 mail 子系统的所有级别为 info 或更高的消息,并将日志记录到 /var/log/maillog 文件。

  • ③ 使用比较标志 (=) 只匹配级别为 debug 的消息,并将其记录到 /var/log/debug.log 文件。

  • ④ 此示例演示了指定程序的用法:后续规则仅对指定程序生效。本例中,仅将 devd(8) 生成的消息记录到 /var/log/devd.log 文件。

14.11.2 日志记录设施

设施(facility)标识生成消息的子系统,用于将不同来源的消息分开,便于日志查阅。

表 syslog 设施

名称说明
auth授权系统:login(1)、su(1)、getty(8) 等。
authpriv与 auth 相同,但日志记录到只有 root 可读的文件中。
console由内核控制台输出驱动程序写入 /dev/console 的消息。
cron由 cron(8) 守护进程写入的消息。
daemon系统守护进程,例如 routed(8),此类进程没有专用的日志记录设施。
kern由内核生成的消息。此类消息不能由任何用户进程生成。
lpr打印机排队系统:lpr(1)、lpc(8)、lpd(8) 等。
mail邮件系统。
mark此设施每 20 分钟添加一条记录。
news网络新闻系统。
ntp网络时间协议系统。
security安全子系统,例如 ipfw(4)。
syslogsyslogd(8) 内部生成的消息。
user随机用户进程生成的消息。这是未指定时的默认设施标识符
local0 至 local7保留给本地使用。

14.11.3 日志记录级别

级别(level)表示消息的严重性,以下是按优先级从高到低的关键词列表:

表 syslog 级别

名称说明
emerg紧急条件。通常广播给所有用户。
alert须立即修正的条件,例如损坏的系统数据库。
crit严重条件,例如硬件设备错误。
err错误。
warning警告消息。
notice非错误条件,但可能需要特别处理的条件。
info信息性消息。
debug调试程序时方可发挥作用的消息。
none此特殊级别禁用特定设施。

14.11.4 阅读日志消息

FreeBSD 的 syslogd(8) 支持两种输出格式,通过 -O 选项切换:

  • BSD/RFC 3164 格式(默认格式,-O bsd-O rfc3164):传统 BSD syslog 格式。
  • Syslog/RFC 5424 格式-O syslog-O rfc5424):较新的标准格式,采用 RFC 3339 时间戳(含微秒精度),并在每条消息中包含结构化的设施与严重级别字段。

RFC 3164 格式的日志通常使用以下语法:

ini
日期 时间 主机名 程序[进程ID]: 信息

以下是 /var/log/cron 文件的输出示例:

ini
[此处省略其他输出]
May 15 15:30:00 ykla /usr/sbin/cron[1812]: (root) CMD (/usr/libexec/atrun)
May 15 15:33:00 ykla /usr/sbin/cron[1814]: (operator) CMD (/usr/libexec/save-entropy)
[此处省略其他输出]

可以通过运行以下命令在 syslogd(8) 中启用详细日志记录,此时每条消息将附带设施和级别:

sh
# sysrc syslogd_flags="-vv"

启用此功能后,日志中将显示设施和级别,如下所示:

ini
[此处省略其他输出]
May 17 18:55:00 <cron.info> ykla /usr/sbin/cron[1771]: (operator) CMD (/usr/libexec/save-entropy)
May 17 18:55:00 <cron.info> ykla /usr/sbin/cron[1772]: (root) CMD (/usr/libexec/atrun)
[此处省略其他输出]

若要切换到 RFC 5424 格式,可以在 /etc/rc.conf 文件中配置:

sh
# sysrc syslogd_flags="-O syslog"

以下是 RFC 5424 格式下 /var/log/cron 文件的输出示例:

sh
<78>1 2026-05-17T19:00:00.004642+08:00 ykla /usr/sbin/cron 1781 - - (root) CMD (newsyslog)
<78>1 2026-05-17T19:00:00.011902+08:00 ykla /usr/sbin/cron 1783 - - (operator) CMD (/usr/libexec/save-entropy)
<78>1 2026-05-17T19:00:00.017709+08:00 ykla /usr/sbin/cron 1785 - - (root) CMD (/usr/libexec/atrun)

RFC 5424 格式下默认启用详细日志记录,无需选项 -vv

sh
<优先级>版本号 时间戳 主机名 程序名[进程ID] 消息ID [结构化数据] 日志信息

14.11.5 日志管理与轮替

日志文件增长迅速,占用磁盘空间,且增加查找有效信息的难度。为此,FreeBSD 使用 newsyslog(8) 来管理日志文件。

newsyslog 定期轮替并压缩日志文件,可选择性地创建缺失的日志文件,并在日志文件移动时向程序发送信号。newsyslog 的默认配置源文件为 usr.sbin/newsyslog/newsyslog.conf

ini
# configuration file for newsyslog
#
# Entries which do not specify the '/pid_file' field will cause the
# syslogd process to be signalled when that log file is rotated.  This
# action is only appropriate for log files which are written to by the
# syslogd process (ie, files listed in /etc/syslog.conf).  If there
# is no process which needs to be signalled when a given log file is
# rotated, then the entry for that file should include the 'N' flag.
#
# Note: some sites will want to select more restrictive protections than the
# defaults.  In particular, it may be desirable to switch many of the 644
# entries to 640 or 600.  For example, some sites will consider the
# contents of maillog, messages, and lpd-errs to be confidential.  In the
# future, these defaults may change to more conservative ones.
#
# logfilename          [owner:group]    mode count size when  flags [/pid_file] [sig_num]
/var/log/all.log			600  7	   *	@T00  J
/var/log/auth.log			600  7	   1000 @0101T JC
/var/log/console.log			600  5	   1000	*     J
/var/log/cron				600  3	   1000	*     JC
/var/log/daemon.log			644  5	   1000	@0101T JC
/var/log/daily.log			640  7	   *	@T00  JN
/var/log/debug.log			600  7	   1000 *     JC
/var/log/devd.log			644  3	   1000	*     JC
/var/log/init.log			644  3	   1000	*     J
/var/log/kerberos.log			600  7	   1000	*     J
/var/log/maillog			640  7	   *	@T00  JC
/var/log/messages			644  5	   1000	@0101T JC
/var/log/monthly.log			640  12	   *	$M1D0 JN
/var/log/security			600  10	   1000	*     JC
/var/log/utx.log			644  3	   *	@01T05 B
/var/log/weekly.log			640  5	   *	$W6D0 JN

<include> /etc/newsyslog.conf.d/[!.]*.conf
<include> /usr/local/etc/newsyslog.conf.d/[!.]*.conf

字段说明:

  • logfilename - 要归档的系统日志文件的名称。
  • [owner:group] - 指定归档文件的所有者和组。
  • mode - 指定日志文件和归档文件的文件模式。有效模式位为 0666,即可为归档日志指定所有者、组和其他用户的读写权限。
  • count - 指定可存在的最大归档文件数。
  • size - 日志文件的大小达到指定值(以 KB 为单位)时,将轮替日志文件。如果该字段包含星号(*),则不按大小轮替。
  • when - 包含时间间隔、特定时间或两者。
  • flags - 表示 newsyslog 接受的标志。
  • [/pid_file] - 指定包含守护进程的进程 ID 的文件名,或查找组进程 ID。
  • [sig_num] - 指定在轮替文件时将发送到守护进程的信号号。

技巧

最后两个字段 [/pid_file][sig_num] 是可选的,指定进程的 PID 文件名以及在轮替文件时发送给该进程的信号编号。

14.11.5.1 手动轮替日志

虽然 newsyslog(8) 默认由 cron(8) 每小时调用一次,但也可以使用选项 -F 手动触发轮替:

sh
# newsyslog -F

强制轮替所有满足条件的日志文件。轮替后的文件示例如下:

sh
/var/log/auth.log          /var/log/devd.log          /var/log/ppp.log
/var/log/auth.log.0.bz2    /var/log/devd.log.0.bz2    /var/log/ppp.log.0.bz2

若要轮替特定文件,可指定文件路径:

sh
# newsyslog -F /var/log/auth.log

轮替结果如下:

sh
auth.log.0.bz2
auth.log
auth.log.1.bz2

14.11.6 配置远程日志记录

系统数量增多后,监控多个主机的日志文件将增加管理负担。配置集中式日志记录可以减轻此负担。

在 FreeBSD 中,可以使用 syslogd 和 newsyslog 配置集中式日志文件聚合、合并和轮替。

本节的示例配置中,主机 A192.168.5.18)作为日志客户端,命名为 logclient.example.com

主机 A 将传递日志信息给日志服务器 B

14.11.6.1 设置 DNS 解析

日志服务器和所有客户端主机必须在本地 DNS 中具有正向和反向条目。如果网络没有 DNS 服务器,请在每个系统的 /etc/hosts 中创建条目。名称解析必须正确,以确保日志条目不会被日志服务器拒绝。

分别在日志客户端 A 和日志服务器 B 中的 /etc/hosts 文件添加以下两行:

ini
192.168.5.18            logclient.example.com
192.168.5.17            logserv.example.com

其中主机 B 作为日志服务器(192.168.5.17),命名为 logserv.example.com,将收集本地网络的日志信息。

14.11.6.2 日志客户端配置

日志客户端将日志条目发送到网络上的日志服务器。客户端还会保留自己的日志副本。

在日志客户端 A 上执行以下命令,设置 syslogd 开机自启:

sh
# service syslogd enable

阻止此客户端接收来自其他主机的日志(-s),同时增加日志消息的详细程度:

sh
# sysrc syslogd_flags="-s -v -v"

然后,在客户端的 /etc/syslog.conf 文件中定义日志服务器。在此示例中,所有记录的设施都通过 @ 符号发送到指定的主机:

sh
*.*  @logserv.example.com

保存编辑后,重新启动 syslogd 以使更改生效:

sh
# service syslogd restart

14.11.6.3 日志服务器配置

日志服务器是配置为接受来自其他主机日志信息的系统。

配置好日志客户端 A 后,在日志服务器 B 上,编辑 /etc/syslog.conf 文件:

ini
+logclient.example.com
*.*     /var/log/logclient.log

以上示例在日志服务器的配置中,添加了日志客户端的主机名作为过滤条件。凡是来自主机 logclient.example.com 所有设施和级别的日志条目,都统一存储在服务器本地的 /var/log/logclient.log 文件中。

为每个客户端添加类似的两行条目便可添加多个日志客户端。

执行以下命令,设置 syslogd 开机自启:

sh
# service syslogd enable

允许来自指定客户端的日志条目:

sh
# sysrc syslogd_flags="-a logclient.example.com -v -v"
  • -v -v 提高了日志消息的详细程度,有助于管理员查看每个设施下记录的消息类型。

  • 要允许来自多个客户端的日志记录,可以指定多个 -a 选项。还可以指定 IP 地址和整个网段。

最后,创建日志文件 logclient.log

sh
# touch /var/log/logclient.log

此时,应重新启动 syslogd 并进行验证:

sh
# service syslogd restart
# pgrep syslogd

如果返回 PID,则表示服务器已成功重新启动。

sh
1958
1961
1962

如果服务器未能重新启动,请通过 /var/log/messages 文件获取错误信息。

为了测试日志消息是否通过网络发送,可以在客户端使用 logger(1) 发送一条消息到 syslogd:

sh
# logger "Test Message by logclient."

此消息应同时存在于客户端的 /var/log/messages 文件和日志服务器的 /var/log/logclient.log 文件中。

sh
May 17 21:58:08 <user.notice> logclient ykla[1881]: Test Message by logclient.

14.11.6.4 调试日志服务器

如果日志服务器和日志客户端之间有防火墙,请确保防火墙规则集放行客户端和服务器之间的 UDP 端口 514。

sh
# nc -uvz logserv.example.com 514
Connection to logserv.example.com 514 port [udp/syslog] succeeded!
sh
# nc -uvz logclient.example.com 514
Connection to logclient.example.com 514 port [udp/syslog] succeeded!

如果日志服务器没有接收到任何消息,原因通常为网络连接问题、主机名解析问题或配置文件中的拼写错误。为排除故障,请确保日志服务器和日志客户端能够使用 /etc/rc.conf 文件中指定的主机名互相 ping。如果失败,请检查网络布线、防火墙规则集,以及日志服务器和客户端中的 DNS 服务器或 /etc/hosts 中的主机名条目。反复检查直至 ping 测试成功。

如果两个主机的 ping 都成功,但服务器仍未接收到日志消息,可临时提高日志详细度以缩小配置问题的范围。在以下示例中,日志服务器上的 /var/log/logclient.log 为空,而日志客户端上的 /var/log/messages 未显示失败原因。

为增加调试输出,编辑日志服务器上的 syslogd_flags 条目并执行重启:

sh
# sysrc syslogd_flags="-d -a logclient.example.com -v -v"

警告 请首先尝试使用 IP 地址代替域名进行测试。

调试成功后必须修改回原有设置,否则将影响系统正常开机。

sh
# service syslogd restart

重启后,调试数据将立即输出到控制台,类似于以下内容:

sh
……省略部分输出……

logmsg: pri 56, flags 0, from logserv, msg restart
syslogd: restarted
logmsg: pri 6, flags 0, from logserv, msg kernel boot file is /boot/kernel/kernel
kernel boot file is /boot/kernel/kernel
received sa_len = 16
cvthname(2) len = 16
cvthname(192.168.5.18)
validate: dgram from IP 192.168.5.18, port 514, name logclient.example.com;
accepted in rule 1.
logmsg: pri 15, flags 0, from logclient, msg Test Message by logclient.
Logging to FILE /var/log/logclient.log
Logging to FILE /var/log/messages

此时,消息已正确接收并写入正确的文件。

14.11.6.5 安全考量

与所有网络服务一样,在实施日志服务器之前应考虑安全需求。日志文件可能包含有关本地主机上启用的服务、用户账户和配置数据的敏感信息。

网络安全

从客户端发送到服务器的网络数据未经加密或密码保护。如果需要加密传输,可考虑以下方案:

  • 使用 security/stunnel 创建 SSL 加密隧道传输 syslog 数据。
  • 在受信任的内部网络中部署日志服务器,配合防火墙限制访问。

接收端安全

通过 UDP 接收日志消息等效于“未经认证的远程磁盘填充服务”。因此:

  • 强烈建议使用 -a 选项明确限制允许发送日志的主机,而非接受所有来源的日志。
  • 如果不需要接收远程日志,应使用 -s 参数启用安全模式。指定两次 -ss 将完全禁用网络套接字。
  • 可在防火墙上限制 UDP 514 端口的访问来源。

本地安全

日志文件在使用过程中或日志轮替后并未加密。本地用户可能通过访问日志文件获取系统配置的额外信息。因此,对日志文件设置适当的权限十分必要。newsyslog 支持对新创建的和已轮替的日志文件设置权限。将日志文件(如 auth.log)设置为模式 600 可防止本地用户的未经授权访问。

14.11.7 参考文献

14.11.8 课后习题

  1. 配置 syslog.conf 将所有 auth 设施的日志单独记录到 /var/log/auth.log 文件中。
  2. 修改 newsyslog.conf 配置,将 /var/log/messages 的保留备份数量从 5 增加到 10。
  3. 使用 grep 命令搜索最近的 SSH 登录失败尝试记录。
  4. 手动触发 newsyslog 轮替 /var/log/auth.log 文件,观察轮替结果。