在 systemd 中使用 journalctl 进行日志记录¶
在这篇文章中
在现代 Linux 发行版(Ubuntu ≥ 16.04、Debian ≥ 8、RHEL/CentOS ≥ 7、Alma/Rocky ≥ 8)中,systemd 不仅管理服务的启动和停止,还通过 journald 和实用工具 journalctl 提供集中式日志记录功能。
systemd 日志收集以下内容: - 内核消息(dmesg), - 来自服务的日志(如 nginx、sshd、docker 等), - 守护进程的标准 stdout/stderr 流, - 审计事件(如果与 auditd 集成)。
备注
journald 可以**与 syslog 并行运行**(例如 rsyslog 或 syslog-ng)——日志可能会重复。然而,journald 通常完全取代传统的 syslog。
快速入门:核心命令¶
| 任务 | 命令 |
|---|---|
| 查看所有日志(带分页器) | journalctl |
| 最后 10 条条目 | journalctl -n |
| 实时尾部日志 | journalctl -f (相当于 tail -f) |
| 自上次启动以来的日志 | journalctl -b |
| 特定服务的日志 | journalctl -u nginx |
| 内核日志 | journalctl -k |
| 日志使用的磁盘空间 | journalctl --disk-usage |
时间和时区¶
默认情况下,journalctl 显示**本地时间**。请验证其配置是否正确:
检查输出中是否包含类似以下行:
管理时区¶
以 UTC 查看日志¶
启动历史¶
默认情况下,不会保留之前启动的日志(它们仅存储在 /run/log/journal/ 中,重启时会被清除)。要保留它们,请启用**持久化存储**:
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
或者手动编辑配置:
取消注释并修改:
处理启动记录¶
# 列出所有保存的启动记录
journalctl --list-boots
# 输出示例:
# -2 abc123... Wed 2025-11-05 10:00:00 MSK—Wed 12:30:45 MSK
# -1 def456... Thu 2025-11-06 09:15:22 MSK—Thu 18:44:10 MSK
# 0 xyz789... Fri 2025-11-07 08:20:05 MSK—running
# 上一次启动的日志
journalctl -b -1
# 按启动 ID 查看日志
journalctl -b xyz789...
日志过滤¶
按时间¶
# 从指定时间点到现在
journalctl --since "2025-11-07 14:00:00"
# 指定时间段
journalctl --since "2025-11-06" --until "2025-11-07 09:00:00"
# 便捷关键字
journalctl --since today
journalctl --since yesterday
journalctl --since "2 hours ago"
journalctl --until now
备注
支持的格式:YYYY-MM-DD、YYYY-MM-DD HH:MM:SS、today、yesterday、1 hour ago、5min ago。
按服务(单元)¶
# Nginx 日志
journalctl -u nginx
# 带 .service 扩展名(可选但正确)
journalctl -u nginx.service
# 同时查看多个服务
journalctl -u nginx -u php-fpm --since today
# 仅查看过去 2 小时的 nginx 错误
journalctl -u nginx -p err --since "2 hours ago"
按进程、用户、组¶
# 按 PID(例如,nginx 主进程)
journalctl _PID=12345
# 按用户的 UID
journalctl _UID=33 # 例如,www-data
journalctl _UID=$(id -u nginx)
# 列出所有有日志条目的 UID
journalctl -F _UID
# 同样适用于 GID
journalctl -F _GID
按优先级级别(严重性)¶
| 级别 | 代码 | 描述 |
|---|---|---|
emerg | 0 | 系统不可用 |
alert | 1 | 需要立即采取行动 |
crit | 2 | 严重错误 |
err | 3 | 错误 |
warning | 4 | 警告 |
notice | 5 | 重要事件 |
info | 6 | 信息性消息 |
debug | 7 | 调试 |
示例:
# 仅错误及更高级别(err, crit, alert, emerg)
journalctl -p err
# 通过数字代码实现相同效果
journalctl -p 3
# 当前启动的 nginx 错误
journalctl -u nginx -p err -b
输出格式¶
核心选项¶
格式化输出¶
格式(-o)**¶
| 格式 | 用法 |
|---|---|
short(默认) | 经典 syslog 风格 |
short-iso | ISO 8601 时间:2025-01-07T15:30:45+03:00 |
short-precise | 带微秒的时间 |
cat | 仅消息文本(无元数据)——脚本中很有用 |
json | JSON,每行一条条目(机器可读) |
json-pretty | 人类可读的 JSON(用于调试/分析) |
verbose | 所有字段,包括隐藏的 _SOURCE_REALTIME_TIMESTAMP、_BOOT_ID 等 |
示例:
# 人类可读的 nginx JSON
journalctl -u nginx -o json-pretty --since today
# 仅消息文本
journalctl -u nginx -p err -o cat
# 导出到文件进行分析
journalctl -b -u docker --no-pager > docker_boot.log
管理日志大小¶
当前大小¶
日志清理¶
按大小¶
按时间¶
备注
支持的后缀: s, m, h, days, weeks, months, years。
持久化限制(在配置中)¶
编辑 /etc/systemd/journald.conf:
更改后:
备注
对 journald.conf 的更改不会影响已累积的日志——请使用 --vacuum-* 进行清理。
高级技巧¶
按内容搜索(使用 grep)¶
事件频率分析¶
导出和备份¶
常见问题解答 (FAQ)¶
问:为什么 journalctl 不显示之前重启的日志? 答:检查是否启用了 Storage=persistent 以及 /var/log/journal/ 是否存在。如果没有,日志仅保存在内存 /run 中。
问:如何禁用 journald 并恢复为 rsyslog? 答:您无法完全禁用 journald(它是 systemd 的一部分),但您可以: - 通过 /etc/systemd/journald.conf 将日志重定向到 rsyslog,或使用 SystemMaxUse=0 禁用 journald 的日志记录功能。 - 或者禁用 journald 作为 rsyslog 的来源,仅保留 rsyslog。
问:日志可以加密吗? 答:journald 默认不支持加密。为此,请使用: - logrotate + gpg, - 或第三方 SIEM 系统(Graylog、ELK、Loki + Promtail)。