> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/di-18-zhang-xi-tong-guan-li/di-18.6-jie-xi-tong-ri-zhi-guan-li.md).

# 18.6 系统日志管理

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

## 配置本地日志记录

配置文件 **/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.warning`、`auth.notice` 和 `mail.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** 文件。

## 日志记录设施

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

**表 syslog 设施**

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

## 日志记录级别

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

**表 syslog 级别**

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

## 阅读日志消息

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

* **BSD/RFC 3164 格式**（默认格式，`-O bsd` 或 `-O rfc3164`）：传统 BSD syslog 格式。
* **Syslog/RFC 5424 格式**（`-O syslog` 或 `-O rfc5424`）：较新的标准格式，采用 [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) 时间戳（含微秒精度），并在每条消息中包含结构化的设施与严重级别字段。

**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 [结构化数据] 日志信息
```

## 日志管理与轮替

日志文件增长迅速，占用磁盘空间，且增加查找有效信息的难度。为此，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 文件名以及在轮替文件时发送给该进程的信号编号。

### 手动轮替日志

虽然 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
```

## 配置远程日志记录

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

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

本节的示例配置中，主机 `A`（**192.168.5.18**）作为日志客户端，命名为 `logclient.example.com`。

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

### 设置 DNS 解析

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

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

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

> **技巧**
>
> 上述示例中的 **192.168.5.18**、**192.168.5.17**、`logclient.example.com`、`logserv.example.com` 为占位符，须替换为实际的值。

其中主机 `B` 作为日志服务器（**192.168.5.17**），命名为 `logserv.example.com`，将收集本地网络的日志信息。

### 日志客户端配置

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

在日志客户端 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
```

### 日志服务器配置

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

配置好日志客户端 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.
```

### 调试日志服务器

如果日志服务器和日志客户端之间有防火墙，请确保防火墙规则集放行客户端和服务器之间的 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
```

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

### 安全考量

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

**网络安全**：

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

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

**接收端安全**：

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

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

**本地安全**：

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

## 参考文献

* FreeBSD Project. syslog.conf(5)\[EB/OL]. \[2025-05-17]. <https://man.freebsd.org/cgi/man.cgi?query=syslog.conf&sektion=5>. syslog 配置文件手册页。
* FreeBSD Project. syslogd(8)\[EB/OL]. \[2025-05-17]. <https://man.freebsd.org/cgi/man.cgi?query=syslogd&sektion=8>. syslog 守护进程手册页。
* FreeBSD Project. newsyslog.conf(5)\[EB/OL]. \[2025-05-17]. <https://man.freebsd.org/cgi/man.cgi?query=newsyslog.conf&sektion=5>. newsyslog 配置文件手册页。
* FreeBSD Project. logger(1)\[EB/OL]. \[2025-05-17]. <https://man.freebsd.org/cgi/man.cgi?query=logger&sektion=1>. 命令行日志发送工具手册页。

## 课后习题

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** 文件，观察轮替结果。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/di-18-zhang-xi-tong-guan-li/di-18.6-jie-xi-tong-ri-zhi-guan-li.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
