systemd 服务排查与 journal 日志管理

太阳作者太阳
原创内容采用 CC-4.0 协议发布,转载请注明出处

原笔记只留下了日志和服务命令,没有留下测试输出。原记录用 aria2cd 作为用户 service 示例,下面保留这个 unit 名称。systemd 排障先要确定两个范围:日志属于哪个启动批次,服务属于系统 manager 还是当前用户 manager。systemctl --userjournalctl --user 只看用户服务;系统服务则使用不带 --user 的命令,必要时加 sudo。用户日志还受 per-user manager、日志持久化设置和当前用户权限影响。journalctl 官方手册源码说明,--user 用于当前用户的服务日志,并要求启用持久化日志才能读取对应历史。

先定位启动批次和时间

journalctl --list-boots
journalctl -b
journalctl -b -1
journalctl --since "2026-09-06 09:00:00" --until "2026-09-06 10:00:00"

-b 是当前启动,-b -1 是上一次启动。--list-boots 会列出批次编号、启动 ID 和首尾时间;如果只记得故障发生的大致时段,用 --since--until 缩小范围。时间字符串要按目标主机的时区理解。

按服务和优先级查看

系统 service:

sudo systemctl status UNIT.service --no-pager
sudo journalctl -u UNIT.service -b --no-pager
sudo journalctl -u UNIT.service -n 100 -f

当前用户 service:

systemctl --user status UNIT.service --no-pager
journalctl --user -u UNIT.service -b --no-pager
journalctl --user -u UNIT.service -n 100 -f

按严重级别筛选:

journalctl -p err..alert -b --no-pager
journalctl -p warning..alert --since "1 hour ago" --no-pager

-f 会跟随新日志,适合重启 unit 后观察首次失败;-p err..alert 只筛选 error 到 alert,不包含更严重的 emerg。若要包含 error 及以上的所有级别,使用 -p err。查看 unit 名称和失败原因时,先执行 systemctl list-units --failed,再对具体 unit 查状态和日志。

用户服务为何退出登录后停止

用户 service 由 per-user manager 管理。若目标是无人登录时也运行,先确认用户 manager 状态,再检查 linger:

systemctl --user is-system-running
loginctl show-user TARGET_USER -p Linger
loginctl enable-linger TARGET_USER

loginctl 官方手册源码说明,启用 linger 后,用户 manager 会在开机时启动,并在用户退出登录后继续存在。enable-linger 需要系统授予的权限;输出为 Linger=no 时,不能假定用户 service 会在下次开机自动运行。

让 journal 跨重启保留

journald.conf 官方手册源码说明,Storage=persistent 优先把日志写入 /var/log/journal;目录不可用时仍可能回退到 /run/log/journal。可以用 drop-in 保存本机策略:

sudo install -d -m 755 /etc/systemd/journald.conf.d
sudoedit /etc/systemd/journald.conf.d/60-local-storage.conf

内容示例:

[Journal]
Storage=persistent
SystemMaxUse=1G
SystemKeepFree=2G
MaxRetentionSec=30day

保存后重启 journald,并把当前运行时日志刷新到持久目录:

sudo systemctl restart systemd-journald.service
sudo journalctl --flush
sudo journalctl --disk-usage

这些数值是配置示例,不代表所有主机都适用。要保留更长审计历史,应结合磁盘容量、备份和组织的留存要求调整。

轮转和清理日志

先查看占用,再执行清理:

journalctl --disk-usage
sudo journalctl --rotate
sudo journalctl --vacuum-time=30days
sudo journalctl --vacuum-size=1G
sudo journalctl --disk-usage

--vacuum-time 删除早于指定时长的归档文件,--vacuum-size 删除最旧归档文件直到低于目标大小。journalctl 官方手册源码特别说明,--disk-usage 还包含 active 文件,而 vacuum 只处理 archived 文件,所以清理后占用不一定立刻等于目标值。--rotate 先把当前文件标记为归档,适合需要立刻回收旧日志的场景。旧笔记中的 --vacuum-size=128M 只是当时的清理示例,不是 systemd 的通用默认值。

清理会删除历史排障证据。执行前确认已保存仍在调查的批次;不要把 vacuum 命令放进无人审核的定时任务,除非留存窗口已经确定。

一个可重复的排障顺序

systemctl list-units --failed
systemctl status UNIT.service --no-pager
journalctl -u UNIT.service -b -n 200 --no-pager
journalctl -u UNIT.service --since "15 minutes ago" -f

如果服务属于当前用户,把以上命令分别改成 systemctl --userjournalctl --user。若服务刚在重启后失败,先查 -b;若怀疑是上一轮启动遗留的问题,再查 -b -1。把状态中的 ExecStart、退出码、依赖失败和端口错误与同一时间窗口的 journal 对照,通常比只看最后一行更容易定位原因。