> For the complete documentation index, see [llms.txt](https://handbook.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://handbook.bsdcn.org/di-14-zhang-pei-zhi-fu-wu-ri-zhi-yu-dian-yuan-guan-li/14.5.-pei-zhi-xi-tong-ri-zhi.md).

# 14.5.配置系统日志

生成和阅读系统日志是系统管理的重要方面。系统日志中的信息可用于检测硬件和软件问题，以及应用程序和系统配置错误。这些信息还在安全审计和事件响应中发挥着重要作用。大多数系统守护进程和应用程序都会生成日志条目。

FreeBSD 提供了系统日志记录器 [syslogd(8)](https://man.freebsd.org/cgi/man.cgi?query=syslogd\&sektion=8\&format=html) 来管理日志记录。默认情况下，syslogd 在系统引导时启用并启动。

本节介绍如何配置 FreeBSD 系统日志记录器以实现本地和远程日志记录，以及如何轮替和管理日志。

## 14.5.1. 配置本地日志记录

配置文件 **/etc/syslog.conf** 控制 syslogd 在接收到日志条目时的处理方式。此文件有多个参数来控制如何处理传入的事件。*facility* 说明了哪个子系统生成了消息，例如内核或守护进程，*level* 说明了事件发生的严重性。因此可根据日志消息的 *facility* 和 *level* 配置日志消息的记录位置。还可根据发送消息的应用程序采取操作，并且在远程日志记录的情况下，可根据生成日志事件的机器的主机名采取操作。

该配置文件包含每个操作一行，每一行的语法由选择器字段和操作字段组成。选择器字段的语法是 *facility.level*，它会匹配来自 *facility* 且级别为 *level* 或更高的日志消息。也可在级别之前添加可选的比较标志，以更精确地指定记录的内容。多个选择器字段可用于相同的操作，并且它们用分号 (`;`) 分隔。使用 `*` 会匹配所有内容。操作字段指定将日志消息发送到哪里，例如文件或远程日志主机。

以下是 FreeBSD 默认的 **/etc/syslog.conf** 配置示例：

```ini
#       空格在此文件中是有效的字段分隔符。然而，
#       其他 *nix-like 系统仍然坚持使用制表符作为字段
#       分隔符。如果你在系统间共享此文件，
#       你可能希望只使用制表符作为字段分隔符。
#       请参考 syslog.conf(5) 手册。
*.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
# 取消注释以记录所有写入 /dev/console 的信息到 /var/log/console.log
# touch /var/log/console.log 并将权限改为 600 后才能生效
#console.info                                   /var/log/console.log
# 取消注释以启用将所有日志消息记录到 /var/log/all.log
# touch /var/log/all.log 并将权限改为 600 后才能生效
#*.*                                            /var/log/all.log
# 取消注释以启用将日志发送到名为 loghost 的远程日志主机
#*.*                                            @loghost
# 取消注释以下内容以启用新闻服务的日志记录
# news.crit                                     /var/log/news/news.crit
# news.err                                      /var/log/news/news.err
# news.notice                                   /var/log/news/news.notice
# 取消注释以查看 devd 产生的消息
# !devd
# *.>=notice                                    /var/log/devd.log ④
!*
include                                         /etc/syslog.d
include                                         /usr/local/etc/syslog.d
```

* ① 匹配所有级别为 `err` 或更高的消息，以及 `kern.warning`、`auth.notice` 和 `mail.crit`，并将这些日志消息发送到控制台（**/dev/console**）。
* ② 匹配来自 `mail` 子系统的所有级别为 `info` 或更高的消息，并将日志记录到 **/var/log/maillog**。
* ③ 使用比较标志 (`=`) 只匹配级别为 `debug` 的消息，并将其记录到 **/var/log/debug.log**。
* ④ 示例展示了程序指定的用法。这样后续的规则只对指定的程序有效。在此例中，只有由 [devd(8)](https://man.freebsd.org/cgi/man.cgi?query=devd\&sektion=8\&format=html) 生成的消息才会记录到 **/var/log/devd.log**。

有关 **/etc/syslog.conf** 的更多信息、其语法以及更多高级用法示例，请参见 [syslog.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=syslog.conf\&sektion=5\&format=html)。

## 14.5.2. 日志记录设施

设施说明了生成消息的系统部分。设施用于区分不同的消息，以便用户更容易查阅日志。

**表 2. syslog 设施**

| 名称              | 说明                                                                                                                                                                                                                                                               |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| auth            | 授权系统： [login(1)](https://man.freebsd.org/cgi/man.cgi?query=login\&sektion=1\&format=html)、 [su(1)](https://man.freebsd.org/cgi/man.cgi?query=su\&sektion=1\&format=html)、 [getty(8)](https://man.freebsd.org/cgi/man.cgi?query=getty\&sektion=8\&format=html) 等。 |
| authpriv        | 与 auth 相同，但日志记录到只有 root 可读的文件中。                                                                                                                                                                                                                                  |
| console         | 由内核控制台输出驱动程序写入到 **/dev/console** 的消息。                                                                                                                                                                                                                            |
| cron            | 由 [cron(8)](https://man.freebsd.org/cgi/man.cgi?query=cron\&sektion=8\&format=html) 守护进程写入的消息。                                                                                                                                                                   |
| daemon          | 系统守护进程，例如 [routed(8)](https://man.freebsd.org/cgi/man.cgi?query=routed\&sektion=8\&format=html)，这些进程没有专门的设施提供日志记录。                                                                                                                                               |
| ftp             | 文件传输协议守护进程： [ftpd(8)](https://man.freebsd.org/cgi/man.cgi?query=ftpd\&sektion=8\&format=html)、 [tftpd(8)](https://man.freebsd.org/cgi/man.cgi?query=tftpd\&sektion=8\&format=html)。                                                                              |
| kern            | 由内核生成的消息。这些不能由任何用户进程生成。                                                                                                                                                                                                                                          |
| lpr             | 打印机排队系统： [lpr(1)](https://man.freebsd.org/cgi/man.cgi?query=lpr\&sektion=1\&format=html)、 [lpc(8)](https://man.freebsd.org/cgi/man.cgi?query=lpc\&sektion=8\&format=html)、 [lpd(8)](https://man.freebsd.org/cgi/man.cgi?query=lpd\&sektion=8\&format=html) 等。    |
| mail            | 邮件系统。                                                                                                                                                                                                                                                            |
| mark            | 此设施每 20 分钟添加一条记录。                                                                                                                                                                                                                                                |
| news            | 网络新闻系统。                                                                                                                                                                                                                                                          |
| ntp             | 网络时间协议系统。                                                                                                                                                                                                                                                        |
| security        | 安全子系统，例如 [ipfw(4)](https://man.freebsd.org/cgi/man.cgi?query=ipfw\&sektion=4\&format=html)。                                                                                                                                                                      |
| syslog          | syslogd(8) 内部生成的消息。                                                                                                                                                                                                                                              |
| user            | 随机用户进程生成的消息。**这是未指定时的默认设施标识符**。                                                                                                                                                                                                                                  |
| uucp            | Unix-to-Unix 复制系统。古老的协议。从此设施收到消息十分罕见。                                                                                                                                                                                                                            |
| local0 到 local7 | 保留给本地使用。                                                                                                                                                                                                                                                         |

## 14.5.3. 日志记录级别

级别描述消息的严重性，以下是按优先级从高到低的关键词列表：

**表 3. syslog 级别**

| 名称      | 说明                   |
| ------- | -------------------- |
| emerg   | 恐慌状态。通常广播给所有用户。      |
| alert   | 应立即修正的条件，例如损坏的系统数据库。 |
| crit    | 严重条件，例如硬件设备错误。       |
| err     | 错误。                  |
| warning | 警告消息。                |
| notice  | 不是错误条件，但可能需要特别处理的条件。 |
| info    | 信息性消息。               |
| debug   | 通常只有在调试程序时才有用的消息。    |
| none    | 此特殊级别禁用特定设施。         |

## 14.5.4. 阅读日志消息

默认情况下，FreeBSD 日志文件使用 [rfc3164](https://datatracker.ietf.org/doc/html/rfc3164) 格式，也称为 BSD syslog 协议。了解其他格式及如何使用它们，请参见 [syslog(8)](https://man.freebsd.org/cgi/man.cgi?query=syslog\&sektion=8\&format=html)。

日志通常具有以下语法：

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

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

```ini
[...]
Jul 16 12:40:00 FreeBSD /usr/sbin/cron[81519]: (root) CMD (/usr/libexec/atrun)
Jul 16 12:44:00 FreeBSD /usr/sbin/cron[83072]: (operator) CMD (/usr/libexec/save-entropy)
[...]
```

可通过运行以下命令在 [syslog(8)](https://man.freebsd.org/cgi/man.cgi?query=syslog\&sektion=8\&format=html) 中启用详细日志记录，这样每条消息上将添加设施和级别：

```sh
# sysrc syslogd_flags="-vv"
```

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

```ini
[...]
Jul 16 17:40:00 <cron.info> FreeBSD /usr/sbin/cron[1016]: (root) CMD (/usr/libexec/atrun)
Jul 16 17:44:00 <cron.info> FreeBSD /usr/sbin/cron[1030]: (operator) CMD (/usr/libexec/save-entropy)
[...]
```

## 14.5.5. 日志管理与轮替

日志文件可能会迅速增长，占用磁盘空间，并使查找有用信息变得更加困难。

在 FreeBSD 中，使用 [newsyslog(8)](https://man.freebsd.org/cgi/man.cgi?query=newsyslog\&sektion=8\&format=html) 来管理日志文件并尝试缓解此问题。

此内置程序会定期轮替并压缩日志文件，并可选择创建缺失的日志文件，并在日志文件移动时向程序发送信号。

> **注意**
>
> 由于 newsyslog 由 [cron(8)](https://man.freebsd.org/cgi/man.cgi?query=cron\&sektion=8\&format=html) 运行，因此它不能比计划的运行频率更频繁地轮替文件。在默认配置下，它每小时运行一次。

这是 FreeBSD 中的默认配置，更多信息请参见 [newsyslog.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=newsyslog.conf\&sektion=5\&format=html)：

```ini
# newsyslog 配置文件
#
# 未指定 '/pid_file' 字段的条目将在日志文件轮替时向 syslogd 进程发送信号。
# 此操作仅适用于由 syslogd 进程写入的日志文件（即 /etc/syslog.conf 中列出的文件）。如果没有需要在日志文件轮替时发送信号的进程，则该文件的条目应包括 'N' 标志。
#
# 注意：某些站点可能希望选择比默认值更严格的保护措施。特别是，可能希望将许多 644 条目更改为 640 或 600。例如，一些站点将认为 maillog、messages 和 lpd-errs 的内容是机密的。未来，这些默认值可能会更改为更保守的设置。
#
# 日志文件名             [所有者:组]    模式 数量 大小 时间  标志 [/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/daily.log                      640  7     *    @T00  JN
/var/log/debug.log                      600  7     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/devd.log                       644  3     1000 *     JC
/var/log/security                       600  10    1000 *     JC
/var/log/utx.log                        644  3     *    @01T05 B
/var/log/weekly.log                     640  5     *    $W6D0 JN
/var/log/daemon.log                     644  5     1000 @0101T JC

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

1. `logfilename` - 要归档的系统日志文件的名称。
2. `[owner:group]` - 这个可选字段指定归档文件的所有者和组。
3. `mode` - 指定日志文件和归档文件的文件模式。有效的模式位是 0666。（即，可为归档日志指定所有者、组和其他用户的读写权限。）
4. `count` - 指定可存在的最大归档文件数。
5. `size` - 当日志文件的大小达到指定的大小（以千字节为单位）时，将修剪日志文件。如果该字段包含星号（‘\*’），则日志文件不会按大小修剪。
6. `when` - 包含时间间隔、特定时间或两者。支持选项请参见 [newsyslog.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=newsyslog.conf\&sektion=5\&format=html)。
7. `flags` - 表示 newsyslog 接受的标志，支持选项请参见 [newsyslog.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=newsyslog.conf\&sektion=5\&format=html)。
8. `[/pid_file]` - 这个可选字段指定包含守护进程进程 ID 的文件名，或查找组进程 ID。
9. `[sig_num]` - 这个可选字段指定在轮替文件时将发送到守护进程的信号号。

> **注意**
>
> 最后两个字段是可选的，指定进程的 PID 文件名以及在轮替文件时发送给该进程的信号号。

## 14.5.6. 配置远程日志记录

随着系统数量的增加，监控多个主机的日志文件可能变得繁琐。配置集中式日志记录可以减少日志文件管理的部分负担。

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

本节展示示例配置，其中主机 `A`，命名为 `logserv.example.com`，将收集本地网络的日志信息。

主机 `B`，命名为 `logclient.example.com`，将配置为将日志信息传递给日志服务器。

### 14.5.6.1. 日志服务器配置

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

在配置日志服务器之前，检查以下内容：

* 如果日志服务器和任何日志客户端之间有防火墙，请确保防火墙规则集让客户端和服务器之间能使用 UDP 端口 514。
* 日志服务器和所有客户端机器必须在本地 DNS 中具有正向和反向条目。如果网络没有 DNS 服务器，请在每个系统的 **/etc/hosts** 中创建条目。必须正确解析名称，以确保日志服务器不会拒绝日志条目。

在日志服务器上，编辑 **/etc/syslog.conf** 来指定接收日志条目的客户端名称、要使用的日志设施和存储主机日志条目的日志文件名称。此示例添加了 `B` 的主机名，记录所有设施，并将日志条目存储在 **/var/log/logclient.log** 中。

**示例 1. 日志服务器配置示例**

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

添加多个日志客户端时，为每个客户端添加类似的两行条目。有关可用设施的更多信息，请参见 [syslog.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=syslog.conf\&sektion=5\&format=html)。

接下来，执行以下命令：

```sh
# sysrc syslogd_enable="YES"
# sysrc syslogd_flags="-a logclient.example.com -v -v"
```

第一个条目在系统启动时启动 syslogd。第二个条目用于接收来自指定客户端的日志条目。`-v -v` 增加了日志消息的详细程度，这对于调整设施非常有用，管理员可查看每个设施下记录了哪些类型的消息。

可指定多个 `-a` 选项，以接收来自多个客户端的日志记录。还可指定 IP 地址和整个网段。有关完整的选项列表，请参考 [syslogd(8)](https://man.freebsd.org/cgi/man.cgi?query=syslogd\&sektion=8\&format=html)。

最后，创建日志文件：

```sh
# touch /var/log/logclient.log
```

此时，应重新启动 syslogd 并验证：

```sh
# service syslogd restart
# pgrep syslog
```

如果返回 PID，则表示服务器已成功重新启动，可开始客户端配置。如果服务器未能重新启动，请检查 **/var/log/messages** 以获取错误信息。

### 14.5.6.2. 日志客户端配置

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

配置好日志服务器后，在日志客户端上执行以下命令：

```sh
# sysrc syslogd_enable="YES"
# sysrc syslogd_flags="-s -v -v"
```

第一个条目在系统启动时启用 syslogd。第二个条目防止此客户端接收来自其他主机的日志（`-s`），并增加了日志消息的详细程度。

接下来，在客户端的 **/etc/syslog.conf** 中定义日志服务器。在此示例中，所有记录的设施都通过 `@` 符号发送到指定的主机：

```sh
*.*  @logserv.example.com
```

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

```sh
# service syslogd restart
```

为了测试日志消息是否通过网络发送，可使用 [logger(1)](https://man.freebsd.org/cgi/man.cgi?query=logger\&sektion=1\&format=html) 在客户端发送一条消息到 syslogd：

```sh
# logger "来自 logclient 的测试消息"
```

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

### 14.5.6.3. 调试日志服务器

如果日志服务器没有接收到任何消息，最可能的原因是网络连接问题、主机名解析问题或配置文件中的拼写错误。为排查原因，确保日志服务器和日志客户端能使用 **/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"
```

```sh
# service syslogd restart
```

重启后，调试数据会立即在控制台上闪现，类似于以下内容：

```sh
logmsg: pri 56, flags 4, from logserv.example.com, msg syslogd: restart
syslogd: restarted
logmsg: pri 6, flags 4, from logserv.example.com, msg syslogd: kernel boot file is /boot/kernel/kernel
Logging to FILE /var/log/messages
syslogd: kernel boot file is /boot/kernel/kernel
cvthname(192.168.1.10)
validate: dgram from IP 192.168.1.10, port 514, name logclient.example.com;
rejected in rule 0 due to name mismatch.
```

在此示例中，因拼写错误导致主机名不匹配，日志服务器因此拒绝了日志消息。客户端的主机名应为 `logclient`，而不是 `logclien`。修正拼写错误后，执行重启并验证结果：

```sh
# service syslogd restart
```

输出应类似于以下内容：

```sh
logmsg: pri 56, flags 4, from logserv.example.com, msg syslogd: restart
syslogd: restarted
logmsg: pri 6, flags 4, from logserv.example.com, msg syslogd: kernel boot file is /boot/kernel/kernel
syslogd: kernel boot file is /boot/kernel/kernel
logmsg: pri 166, flags 17, from logserv.example.com,
msg Dec 10 20:55:02 <syslog.err> logserv.example.com syslogd: exiting on signal 2
cvthname(192.168.1.10)
validate: dgram from IP 192.168.1.10, port 514, name logclient.example.com;
accepted in rule 0.
logmsg: pri 15, flags 0, from logclient.example.com, msg Dec 11 02:01:28 trhodes: Test message 2
Logging to FILE /var/log/logclient.log
Logging to FILE /var/log/messages
```

此时，消息已正确接收并放置在正确的文件中。

### 14.5.6.4. 安全考量

与所有网络服务一样，在实施日志服务器之前应考虑安全需求。日志文件可能包含有关本地主机上启用的服务、用户账户和配置数据的敏感信息。从客户端发送到服务器的网络数据不加密，也不加密码保护。如果需要加密，请考虑使用 [security/stunnel](https://cgit.freebsd.org/ports/tree/security/stunnel/)，它将通过加密隧道传输日志数据。

本地安全也是问题。日志文件在使用过程中或日志轮替后并未加密。本地用户可能访问日志文件以获取有关系统配置的额外信息。因此，对日志文件设置适当的权限至关重要。内置的日志轮替工具 newsyslog 支持对新创建的和已轮替的日志文件设置权限。将日志文件设置为模式 `600` 应该可以防止本地用户的未授权访问。有关更多信息，请参阅 [newsyslog.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=newsyslog.conf\&sektion=5\&format=html)。
