Linux 日志系统管理与分析技巧

1次阅读

journalctl查不到日志需先确认服务是否由systemd管理;若非systemd启动(如手动或docker),日志不进journald;其次检查storage配置(persistent才持久化)、过滤应优先用原生参数而非grep;时区问题需区分记录utc与显示本地时间。

Linux 日志系统管理与分析技巧

journalctl 查不到服务日志?先确认服务是否由 systemd 管理

很多用户执行 journalctl -u nginx 却返回“no entries”,不是 journalctl 坏了,而是 nginx 根本没用 systemd 启动——比如手动运行 /usr/sbin/nginx 或通过 Docker 启动,日志压根不会进 journald。

实操建议:

  • systemctl list-units --type=service --state=running 确认服务是否在 systemd 下运行
  • 检查服务单元文件是否存在:systemctl cat nginx.service;若报错“No such file”,说明该服务未被 systemd 托管
  • 若服务是手动启动的,日志通常输出到终端或配置的 Error_log 文件(如 /var/log/nginx/error.log),和 journalctl 无关

journalctl 日志滚动太快、查不到旧记录?看 Storage 配置和磁盘空间

默认情况下,journald 只保留最近 1–2 周的日志,且受磁盘空间限制。执行 journalctl --disk-usage 可能显示“Archived and active journals take up 84.0M”,但实际查不到三天前的记录,大概率是 Storage=volatileSystemMaxUse 设得太小。

实操建议:

  • 查看当前配置:cat /etc/systemd/journald.conf | grep -E "^(Storage|SystemMaxUse|MaxRetentionSec)"
  • Storage=persistent 是关键:必须创建 /var/log/journal/ 目录并重启 journald(systemctl restart systemd-journald)才生效
  • 调整保留策略示例:SystemMaxUse=500MMaxRetentionSec=3month,改完需 reload:systemctl kill --signal=SIGHUP --kill-who=main systemd-journald
  • 注意:Storage=volatile(默认值之一)表示只存内存,重启即丢,常见于容器或最小化安装系统

grep 不好使?journalctl 原生过滤比管道更准、更快

journalctl -u sshd | grep "Failed password" 看似自然,但会丢失结构化字段(如 _PID、_HOSTNAME)、跳过二进制日志项,还可能因缓冲导致截断。更糟的是,如果日志量大,管道会让 journalctl 提前退出,漏掉匹配项。

实操建议:

  • 用原生匹配:journalctl -u sshd -m "_MESSAGE=Failed password"(注意等号两边无空格)
  • 模糊匹配用 --grepjournalctl --grep="authentication failure",它支持正则且不破坏日志完整性
  • 组合条件优先用 -o json + jqjournalctl -u docker --since "2 hours ago" -o json | jq 'select(.MESSAGE | contains("pull"))'
  • 避免 | grep 的典型场景:含换行符的日志、含非 UTF-8 字节的内核消息(如某些驱动日志)

日志时间不准、时区混乱?别只改 timedatectl set-timezone

即使 timedatectl 显示时区正确,journalctl 输出仍可能显示 UTC 时间,或者不同服务日志时间戳不一致。这是因为 journald 默认以 UTC 记录时间戳,显示时才转换——而转换依赖调用方环境变量,不是全局设置。

实操建议:

  • 强制按本地时区显示:journalctl --utc=false(或设环境变量 JOURNALD_UTC=0
  • 但更稳妥的做法是统一用 UTC 查日志:journalctl --since "2024-05-20 08:00:00 UTC",避免本地时区夏令时切换带来的歧义
  • 服务自身日志(如 Python 应用 print 出的时间)若没显式设时区,会用系统默认时区,与 journald 时间戳来源不同——这意味着同一事件在 journal 和应用日志里可能差 8 小时,排查关联问题时必须注意源头
  • 检查 /etc/systemd/journald.confTimeMinSecTimeMaxSec 是否误配(极少见,但会导致时间范围查询失效)

真正麻烦的从来不是命令怎么敲,而是搞不清哪段日志归谁管、什么时候开始记、记到哪儿为止。journald 表面统一,底下却连着 systemd 启动方式、磁盘策略、时区上下文三层依赖,漏掉一层,查半天都像在猜。

text=ZqhQzanResources