Skip to content

在 systemd 中使用 journalctl 进行日志记录

在这篇文章中

在现代 Linux 发行版(Ubuntu ≥ 16.04、Debian ≥ 8、RHEL/CentOS ≥ 7、Alma/Rocky ≥ 8)中,systemd 不仅管理服务的启动和停止,还通过 journald 和实用工具 journalctl 提供集中式日志记录功能。

systemd 日志收集以下内容: - 内核消息(dmesg), - 来自服务的日志(如 nginxsshddocker 等), - 守护进程的标准 stdout/stderr 流, - 审计事件(如果与 auditd 集成)。

备注

journald 可以**与 syslog 并行运行**(例如 rsyslogsyslog-ng)——日志可能会重复。然而,journald 通常完全取代传统的 syslog。

快速入门:核心命令

任务 命令
查看所有日志(带分页器) journalctl
最后 10 条条目 journalctl -n
实时尾部日志 journalctl -f (相当于 tail -f)
自上次启动以来的日志 journalctl -b
特定服务的日志 journalctl -u nginx
内核日志 journalctl -k
日志使用的磁盘空间 journalctl --disk-usage

时间和时区

默认情况下,journalctl 显示**本地时间**。请验证其配置是否正确:

timedatectl status

检查输出中是否包含类似以下行:

Local time: Thu 2025-11-07 15:32:11 
Time zone: Europe/Paris (PAR, +0100)

管理时区

# 列出所有可用时区
timedatectl list-timezones


# 设置(例如,设置为柏林)
sudo timedatectl set-timezone Europe/Berlin

以 UTC 查看日志

journalctl --utc           # 始终为 UTC
journalctl -b --utc        # 当前启动,以 UTC 显示

启动历史

默认情况下,不会保留之前启动的日志(它们仅存储在 /run/log/journal/ 中,重启时会被清除)。要保留它们,请启用**持久化存储**:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

或者手动编辑配置:

sudo nano /etc/systemd/journald.conf

取消注释并修改:

[Journal]
Storage=persistent

处理启动记录

# 列出所有保存的启动记录
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-DDYYYY-MM-DD HH:MM:SStodayyesterday1 hour ago5min 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


输出格式

核心选项

--no-pager       # 输出到 stdout(用于 grep、tee、重定向)
--no-full        # 不截断长行(默认截断)
-n 50            # 最后 50 条条目
-f               # 跟随(实时查看新条目)

格式化输出

格式(-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

管理日志大小

当前大小

# --vacuum-size=100M
journalctl --vacuum-size=100M

日志清理

按大小

# --vacuum-files=5
journalctl --vacuum-files=5

按时间

# --vacuum-time=1d
journalctl --vacuum-time=1d

备注

支持的后缀: s, m, h, days, weeks, months, years。

持久化限制(在配置中)

编辑 /etc/systemd/journald.conf:

- SystemMaxUse=1G
+ SystemMaxUse=500M

更改后:

systemctl restart systemd-journald

备注

journald.conf 的更改不会影响已累积的日志——请使用 --vacuum-* 进行清理。

高级技巧

按内容搜索(使用 grep)

journalctl -u nginx | grep "error"

事件频率分析

journalctl --since "2023-01-01" --until "2023-01-31" | grep "error" | wc -l

导出和备份

journalctl -b -u docker --no-pager > docker_boot.log

常见问题解答 (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)。

question_mark
Is there anything I can help you with?
question_mark
AI Assistant ×