AI Infra 训练营
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub

journalctl —— systemd 日志查询

一句话定义

journalctl 是 systemd-journald(systemd 的日志收集器)的查询工具。所有用 systemd unit 跑的服务,它们的 stdout/stderr 都被 journald 收集起来,结构化存储、统一查询。

典型场景

  • 服务 status 显示 failed:journalctl -u <service> -n 100
  • 看 kubelet / containerd / sshd 实时日志:journalctl -u kubelet -f
  • 排查"昨晚某个时刻发生了什么":journalctl --since "2026-05-27 02:00" --until "2026-05-27 03:00"
  • 启动失败排查:journalctl -b -p err(看本次启动的所有 err 级日志)
  • 节点磁盘满了:journalctl --vacuum-size=500M(限制日志总大小)

和老式 syslog/rsyslog 的区别

维度传统 /var/log/*.logjournald
存储纯文本,一文件一服务二进制索引文件(/var/log/journal/...)
查询grep、tail -f、lessjournalctl 各种过滤
结构化没有(一行一行 grep)每条日志带 unit、PID、UID、boot ID、timestamp
跨服务关联难(多个文件)容易(单一查询接口)
持久化默认持久默认可能只在内存 / /run(重启丢)

K8s 节点上几乎所有系统服务(kubelet / containerd / kube-proxy)都跑在 systemd 下,日志全在 journald。学会 journalctl 是 K8s 运维基本功。


核心 6 个用法(90% 够用)

journalctl -u sshd                        # 看某个服务的日志
journalctl -u kubelet -f                  # 跟随实时日志(类似 tail -f)
journalctl -u kubelet -n 100              # 最近 100 行
journalctl -u kubelet --since "10 min ago"   # 时间过滤
journalctl -u kubelet -p err              # 按级别过滤(err 及以上)
journalctl -b                             # 只看本次启动(reboot 后的)

时间过滤(最常用)

journalctl --since "10 min ago"
journalctl --since today
journalctl --since yesterday --until today
journalctl --since "2026-05-27 10:00:00" --until "2026-05-27 12:00:00"
journalctl --since "1 hour ago" --until "30 min ago"

时间格式宽容:

  • 自然语言:yesterday、today、tomorrow、now
  • 相对:"10 min ago"、"1 hour ago"、"2 days ago"
  • 绝对:"2026-05-27 10:00:00" 或 "2026-05-27"

按 unit 过滤

journalctl -u sshd                # 单个 unit
journalctl -u sshd -u kubelet     # 多个 unit
journalctl --user-unit foo        # 用户级 unit

-u 可以多次出现。

通配:

journalctl -u 'kube*'             # 所有 kube 开头的

加引号保护 shell 不展开。


按级别过滤

journald 用 syslog 级别(数字越小越紧急):

级别数字含义
emerg0系统不可用
alert1必须立即处理
crit2严重错误
err3错误
warning4警告
notice5提示
info6信息(默认显示这个及以下)
debug7调试
journalctl -p err                 # err 及更紧急(err, crit, alert, emerg)
journalctl -p warning             # warning 及更紧急
journalctl -p 3                   # 数字写法等价 -p err
journalctl -p err..crit           # 范围(err 到 crit)

排查节点故障常用:

journalctl -b -p err              # 本次启动的所有 err
journalctl --since today -p err   # 今天的所有 err

跟随实时日志

journalctl -u kubelet -f          # 类似 tail -f
journalctl -u kubelet -f -n 50    # 先显示最近 50 行,再跟随

-f 持续输出新日志,Ctrl-C 退出。


启动 / boot 视角

journalctl -b                     # 本次启动的全部日志
journalctl -b -1                  # 上一次启动(-1 = 倒数第一次)
journalctl -b -2                  # 倒数第二次启动
journalctl --list-boots           # 列出所有可查的 boot ID

排查"机器昨晚重启过吗、重启前/后日志":

journalctl --list-boots
# IDX  BOOT ID            FIRST ENTRY                LAST ENTRY
#  -2  abc123...          2026-05-25 09:00:00 UTC    2026-05-26 23:59:30 UTC
#  -1  def456...          2026-05-27 00:00:10 UTC    2026-05-27 14:00:00 UTC   ← 重启
#   0  ghi789...          2026-05-27 14:00:15 UTC    (now)

journalctl -b -1 -p err --since "23:00"   # 重启前最后那段时间的 err
journalctl -b 0 -p err -n 50              # 重启后的 err

结构化字段过滤

journald 把每条日志拆成多个字段(_SYSTEMD_UNIT、_PID、_HOSTNAME 等):

journalctl _PID=1234                      # 某个 PID 的日志
journalctl _UID=1000                      # 某用户的
journalctl _COMM=sshd                     # 进程名(命令)
journalctl _SYSTEMD_UNIT=kubelet.service  # 等价于 -u kubelet
journalctl _TRANSPORT=kernel              # 内核日志

看可用字段:

journalctl -F _SYSTEMD_UNIT       # 列出所有 unit
journalctl -F _PID                # 列出所有 PID

输出格式

journalctl -u sshd -o short       # 默认,人类可读
journalctl -u sshd -o short-iso   # ISO 8601 时间戳
journalctl -u sshd -o json        # JSON(脚本用)
journalctl -u sshd -o json-pretty # 人类可读 JSON
journalctl -u sshd -o cat         # 只输出消息,不带 timestamp / unit 前缀

-o cat 在 grep / 二次处理时很有用:

journalctl -u kubelet --since today -o cat | grep -c "out of memory"

-o json 配 jq 用:

journalctl -u kubelet --since "1 hour ago" -o json \
  | jq -r 'select(.PRIORITY|tonumber < 4) | .MESSAGE'

kernel 日志(dmesg 的替代)

journalctl -k                     # 等价 dmesg
journalctl -k -b                  # 本次启动的内核日志
journalctl -k -b -p err           # 本次启动的内核错误

内核 OOM kill / 磁盘错误 / 网卡 link 状态变化等都在这里。K8s 节点 OOM 杀 pod 常见:

journalctl -k -b | grep -i 'oom\|killed process'

journald 持久化

默认行为根据发行版不同:

  • 有 /var/log/journal/ 目录 → 持久化(重启后日志保留)
  • 没这个目录 → 只在 /run/log/journal/(重启后丢)

排查重启前的问题时如果发现 journalctl -b -1 空,多半是没持久化。

启用持久化:

mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
systemctl restart systemd-journald

或者在 /etc/systemd/journald.conf 里:

[Journal]
Storage=persistent

限制 journal 大小(防磁盘爆)

journald 默认占根分区的 10%(最多 4G)。但有时还是会满:

journalctl --disk-usage                          # 看当前用了多少
# Archived and active journals take up 3.4G in the file system.

journalctl --vacuum-size=500M                    # 限制总大小 500M(删旧的直到达标)
journalctl --vacuum-time=7d                      # 只保留 7 天
journalctl --vacuum-files=10                     # 最多保留 10 个文件

永久限制在 /etc/systemd/journald.conf:

[Journal]
SystemMaxUse=500M
SystemMaxFileSize=50M
MaxRetentionSec=1week

改完 systemctl restart systemd-journald。


实战:服务挂了,怎么排查

# 1. 看状态(systemctl status 自带最近 10 行日志)
systemctl status myapp -l

# 2. 看完整日志
journalctl -u myapp -n 200 --no-pager

# 3. 看错误
journalctl -u myapp -p err

# 4. 看一段时间
journalctl -u myapp --since "30 min ago"

# 5. 看重启前后
journalctl -u myapp -b 0 --since "10 min ago"   # 重启后
journalctl -u myapp -b -1 --since "10 min ago"  # 重启前 10 分钟

实战:K8s 节点排错

# kubelet 状态
journalctl -u kubelet -f                # 跟随
journalctl -u kubelet --since today -p err

# 容器运行时
journalctl -u containerd --since "1 hour ago"
journalctl -u docker --since "1 hour ago"

# 网络组件(CNI)
journalctl -u kube-proxy --since today

# 内核(OOM、磁盘、丢包等)
journalctl -k -b | grep -iE 'oom|drop|fail|error' | head

常见踩坑

坑 1:分页器卡死

journalctl -u kubelet
# 卡在 less 界面,按 q 退出,但很烦

加 --no-pager 直接输出到终端:

journalctl -u kubelet --no-pager
journalctl -u kubelet -n 100 --no-pager      # 推荐套路

或者通过管道(自动 no-pager):

journalctl -u kubelet | head -100

或者一劳永逸:

export SYSTEMD_PAGER=cat                     # 全局禁用 pager

坑 2:找不到 -u 指定的 unit

journalctl -u ssh
# -- No entries --

unit 名拼错。可能是:

  • ssh vs sshd:Ubuntu 22 是 ssh.service
  • 加 .service 后缀更稳:journalctl -u ssh.service

可用 unit 列表:

journalctl -F _SYSTEMD_UNIT | sort -u | head

坑 3:重启后 -b -1 啥也没有

journald 没持久化。看 /var/log/journal/ 目录在不在。详见上面"journald 持久化"段。

坑 4:日志显示有截断([truncated])

journald 默认每条日志最大 64K。容器日志一行特别长会被截断。修改:

# /etc/systemd/journald.conf
[Journal]
LineMax=1M

但通常更好的是改应用 —— 单行日志超过 64K 通常是 JSON 一坨 stack trace,应该拆成多行或者结构化。

坑 5:journalctl 拒绝服务

hint: You are currently not seeing messages from other users.

普通用户默认只看自己的日志。要看全部:

sudo journalctl -u kubelet

或者把用户加入 systemd-journal 组:

sudo usermod -aG systemd-journal $USER

退出登录重进。

坑 6:磁盘满才发现 journal 撑爆

容器化负载长期跑、节点上没人清 → journal 爬到几个 G。直到 df -h 报满。

预防:

# /etc/systemd/journald.conf
[Journal]
SystemMaxUse=1G
MaxRetentionSec=2week

事后清理:

journalctl --vacuum-size=200M

关联命令

  • systemctl —— 服务管理;status 自带日志尾巴
  • dmesg —— 内核环形缓冲(等价 journalctl -k)
  • tail -f /var/log/... —— 老式日志文件查看(K8s 之前的世界)
  • grep —— 配合 journalctl --no-pager 做二次过滤
  • jq —— 配合 journalctl -o json 做结构化查询
在 GitHub 上编辑此页