# 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 through 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] [信号号]
/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)。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/hanbook/di-14-zhang-pei-zhi-yu-you-hua/14.5.-pei-zhi-xi-tong-ri-zhi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
