日志排查体系:journalctl 与生产日志轮转

线上出故障时,第一步永远是翻日志。但日志查得好不好,直接决定定位问题的速度。这篇整理 systemd 生态下 journald / journalctl 的完整用法,以及生产环境怎么把日志管住、不爆盘。

一、journalctl:集中式日志查询

systemd 自带 systemd-journald 守护进程,把内核消息、系统服务、自定义服务的输出全部收集进一个二进制数据库(/run/log/journal/ 或持久化后的 /var/log/journal/)。journalctl 就是查询它的工具。

一句话说清它的定位:”journalctl 是 systemd 生态的日志查询命令,集中管理所有 systemd 单元和内核日志,支持结构化过滤和持久化存储。”

常用查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 看某个服务的日志(生产最常用)
journalctl -u nginx.service
journalctl -u nginx -f # 实时跟踪(类似 tail -f)

# 按时间过滤
journalctl --since "2023-04-01 10:00:00" --until "2023-04-01 11:00:00"
journalctl -u 服务名 --since "1 hour ago"

# 本次启动以来的日志(重启后查故障原因必备)
journalctl -b # 当前启动
journalctl -b -1 # 上一次启动
journalctl --list-boots # 列出所有启动记录

# 按优先级过滤
journalctl -p err # 只看错误及以上
# 级别:emerg, alert, crit, err, warning, notice, info, debug

# 内核日志 / 指定进程
journalctl -k
journalctl _PID=1234

踩过的坑:journald 没持久化

有段时间重启服务器后 journalctl -b -1 查不到上次的日志,一度以为是命令写错了。查了一圈才发现:CentOS 7 最小化安装时,journald 的日志默认存在内存里(/run/log/journal),一重启全清空。

解法是建持久化目录:

1
2
3
4
5
6
7
8
9
mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
systemctl restart systemd-journald

# 同时限制日志大小防爆盘(编辑 /etc/systemd/journald.conf)
# SystemMaxUse=2G 日志最多占 2G,超了自动删最老的
# SystemKeepFree=500M 至少给系统留 500M 空闲
# MaxRetentionSec=1month 最多保留 1 个月
systemctl restart systemd-journald

二、logrotate:防爆盘的根本

journald 只管自己的库,业务日志(nginx、应用自己打的日志)得靠 logrotate 管。配置在 /etc/logrotate.conf(全局)+ /etc/logrotate.d/(每个服务一个文件)。

以 nginx 为例的标准配置:

1
2
3
4
5
6
7
8
9
10
11
12
/var/log/nginx/*.log {
daily # 每天切一次
rotate 7 # 保留 7 份旧的
compress # 旧日志压缩成 .gz
delaycompress # 昨天的先不压,方便临时查
missingok # 文件不存在不报错
notifempty # 空文件不轮转
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid` # 通知 nginx 重开日志文件
endscript
}

两个验证命令先背下来:

1
2
logrotate -d /etc/logrotate.d/nginx   # 调试模式,只演练不真执行,查语法
logrotate -f /etc/logrotate.d/nginx # 强制立刻轮转一次,验证生效

三、配套排查:系统日志文件

除了 journald,传统系统日志文件依然是安全排查的一线阵地:

  • /var/log/messages:系统日志
  • /var/log/secure:系统登录和退出日志——如果 secure 里出现大量 Failed,说明有人在暴力破解密码,要立刻加固 SSH

四、一次”查不到日志”的完整复盘

现象:应用半夜崩溃,早上重启后想查崩溃时刻的日志,journalctl -b -1 只返回了启动信息,没有应用输出。

排查链路:

  1. journalctl --list-boots 确认存在上一次启动记录 → 排除命令用错;
  2. 检查 /run/log/journal vs /var/log/journal → 发现只有内存目录,持久化没做
  3. 补建目录并重启 journald,观察 /var/log/journal 开始落盘;
  4. 后续同类问题都能查到 -b -1 的完整日志。

总结:日志体系的搭建要在上线前完成,而不是故障后才想起来——持久化、轮转、保留策略这三件事,每台新机器初始化时就要一起落下。