journald 与 syslog 是上下游协作关系:journald 负责采集,rsyslog 负责分发归档;/var/log/messages 等由 rsyslog 从 journald 订阅解析生成,非 journald 直写;需启用 journald 持久化(storage=persistent)并确保 rsyslog 用户属 systemd-journal 组且 imjournal 模块启用。

journald 和 syslog 不是“二选一”,而是“上下游协作”关系:journald 是日志采集器,syslog(如 rsyslog)是分发归档器。你看到的 /var/log/messages 或 /var/log/secure 并不是 journald 直接写的,而是 rsyslog 从 journald 订阅后解析、过滤、落盘的结果。忽略这个分工,就容易配错、查不到日志、甚至重启后发现日志全丢了。
为什么 journalctl 能查到日志,但 grep /var/log/messages 却找不到?
因为默认情况下,systemd-journald 日志只存在内存或 /run/log/journal/(易失路径),重启即清空;而 rsyslog 默认通过 imjournal 模块读取 journal 流——但如果 journald 没启用持久化,它连开机前的日志都拿不到,更别说喂给 rsyslog 了。
- 检查是否持久化:
ls /var/log/journal/—— 若目录为空或不存在,说明 journal 日志没落盘 - 启用持久化只需三步:
sudo mkdir -p /var/log/journal→sudo systemd-tmpfiles --create --prefix /var/log/journal→sudo systemctl restart systemd-journald - 验证效果:
journalctl --list-boots应该显示多条启动记录(不止 “-1”,即本次启动)
rsyslog 不写 /var/log/messages?先确认 imjournal 是否真在工作
新版 rsyslog 默认加载 imjournal,但模块本身不自动启用,且依赖权限。即使配置里有 $ModLoad imjournal,如果 syslog 用户不在 systemd-journal 组里,它根本读不了 journal 文件。
- 检查模块是否加载:
grep "imjournal" /etc/rsyslog.conf,必须有且未被注释 - 确认权限:
sudo usermod -a -G systemd-journal syslog(注意:不是root或rsyslog用户,是syslog) - 重启后验证:
sudo systemctl restart rsyslog,然后journalctl -u rsyslog | grep imjournal应出现 “imjournal: started” - 常见错误现象:
rsyslog启动无报错,但/var/log/messages停更、时间戳卡在某次重启前——大概率是权限或模块未生效
journalctl 和 grep /var/log/ 的使用场景根本不同
journalctl 查的是结构化二进制日志,自带 _PID、UNIT、_COMM 等字段,适合按服务、优先级、时间范围快速定位;grep 在文本日志里搜,快但模糊,且丢失元数据。两者不是替代关系,是互补。
- 查 SSH 登录失败(含用户、IP、时间):
journalctl -u sshd --since "2 hours ago" | grep "Failed password" - 查某进程崩溃的完整上下文(含堆栈前几行):
journalctl _PID=12345 -n 20 - 审计所有 sudo 使用记录(文本日志更稳定):
grep "sudo:" /var/log/auth.log(因为 rsyslog 已按 facility 分流到此文件) - 性能影响:journalctl 查询快(索引二进制),但导出大量日志转文本会慢;直接
tail -f /var/log/messages实时性好,但无法反向查“昨天下午三点哪个服务报错”
最常被忽略的一点:journald 的 Storage= 配置(在 /etc/systemd/journald.conf)决定了日志存哪、存多久、压不压缩——哪怕你建了 /var/log/journal/,如果配置里还是 Storage=volatile,它照样只往 /run 写。改完配置必须 systemctl kill --signal=SIGUSR1 systemd-journald 或重启服务才生效。








