Linux 日志异常排查与案例

13次阅读

journalctl 查不到服务日志需依次确认 unit 名称正确、服务已启用、日志未被轮转清理;检查 journald 存储配置(storage=none 则日志仅存内存);排查终端编码与字符集匹配问题;结合 dmesg 和 coredump 定位崩溃详情;用时间范围和字段过滤高效检索。

Linux 日志异常排查与案例

journalctl 查不到服务日志?先确认 unit 名称和日志留存策略

systemd 服务日志默认由 journalctl 管理,但查不到不等于没输出——常见原因是 unit 名称写错、服务未启用、或日志已被轮转清理。

  • journalctl --list-units --type=service 看服务是否在 systemd 中注册(注意拼写,比如 nginx.service 不是 nginx
  • 刚启动的服务可能还没刷入 journal,加 -o json-pretty--since "1 minute ago" 缩小范围
  • journalctl --disk-usage 查当前日志占多少空间;若为 0 或极小,说明 Storage=none/etc/systemd/journald.conf 中被设了,日志只存在内存里,重启即丢
  • 临时启用持久化:改 Storage=persistent,再运行 sudo systemctl kill --signal=SIGUSR1 systemd-journald 重载配置

grep 出来全是乱码或空行?终端编码和 journal 字符集不匹配

日志里含中文、emoji 或特殊符号时,journalctl 默认按 UTF-8 解析,但终端 locale 或管道处理会破坏原始字节流。

  • 先检查 locale 输出是否含 UTF-8(如 LANG=en_US.UTF-8),不是就临时设:LANG=C.UTF-8 journalctl -u nginx.service
  • 避免用 grep 直接筛二进制内容:加 --all 参数确保显示所有字段(包括 _HOSTNAME、_PID),再用 awkjq 处理更稳
  • 如果日志本身含控制字符(比如某些 Python logging 配置用了 r 刷屏),加 --no-hostname --no-pager 防止终端渲染干扰

服务明明 crash 了,journalctl 却没看到 segfault 或 exit code?得看内核日志和 coredump

用户态进程崩溃时,systemd 可能只记录“main process exited, code=killed, status=11/SEGV”,但具体堆栈不在 journal 里——它被内核或 systemd-coredump 拦截了。

  • 查内核消息:dmesg -T | grep -i "segfault|killed process",注意时间戳是否比 journal 早几秒
  • 确认 coredump 是否启用:systemctl is-enabled systemd-coredump;若为 disabled,sudo systemctl enable systemd-coredump 并检查 /proc/sys/kernel/core_pattern
  • core 文件默认存于 /var/lib/systemd/coredump/,用 coredumpctl info <code>your-binary-name 直接读取上下文,比翻日志快得多
  • 某些容器化部署会禁用 coredump(如 Docker 的 --ulimit core=0),这时只能靠 strace -f -e trace=signal 提前挂载抓信号

日志量太大卡住 terminal?别硬翻,用 time-range + field filter 快速定位

线上服务跑几天后,journalctl -u xxx 可能返回几十万行,less 都卡死。关键是跳过“全量拉取”这个动作。

  • --since "2024-05-20 14:30:00"--until "2024-05-20 14:35:00" 锁定故障窗口,哪怕只差一分钟,数据量常差两个数量级
  • 过滤特定字段比 grep 更准:journalctl _PID=12345 PRIORITY=3(3 是 ERR 级别),避免正则误匹配
  • 导出结构化数据:journalctl -u nginx --output=json | jq 'select(.MESSAGE | contains("502"))',比 shell 管道稳定,且支持嵌套字段筛选
  • 如果频繁要查,把常用组合做成 alias,比如 alias jnerr='journalctl -p 3 --since "1 hour ago"'

真正难的不是查哪条日志,而是判断该信哪条——比如同一时间点,kernel 日志说 OOM killer 杀了进程,而应用日志却报“connection timeout”,这时候得看谁先发生,而不是谁声音大。

text=ZqhQzanResources