journalctl -u xxx.service -o json -f可实现实时、低延迟、单位粒度精准的服务状态监听,每行输出一个json对象,基于inotify+sd-journal机制,支持jq解析、可中断、易集成。

直接用 journalctl -o json 配合 _SYSTEMD_UNIT 过滤 + 解析 JSON 流,就能实现实时、低延迟(毫秒级)、单位粒度精准的服务状态监听——关键不在“多快”,而在“不漏、不卡、可中断、易集成”。
监听原理:靠 journal 的实时流式输出,不是轮询
journalctl -u xxx.service -o json -f 会持续输出符合单位条件的新日志条目,每行一个 JSON 对象。它底层复用 journal 的实时通知机制(基于 inotify + sd-journal 接口),启动延迟通常 微服务健康探测的时效要求。
注意三点:
- 必须加
-f(follow),否则只输出历史日志就退出 - 推荐加
--no-hostname --all减少干扰字段,提升解析稳定性 - 避免用
-n 0或--since等时间限定,否则可能跳过首条启动日志
解析关键:提取 _SYSTEMD_UNIT + PRIORITY + SYSLOG_IDENTIFIER + MESSAGE
每行 JSON 中,真正反映服务状态的是这四个字段:
-
_SYSTEMD_UNIT:确认来源服务(如
nginx.service) - PRIORITY:数值越小越严重(0=emerg, 6=info),常用来识别启动成功(PRIORITY=6 + MESSAGE 包含 "started")或崩溃(PRIORITY=2 + MESSAGE 含 "exited" 或 "killed")
-
SYSLOG_IDENTIFIER:常为进程名(如
nginx),辅助验证上下文 -
MESSAGE:原始日志内容,用于匹配关键词(如
"Configuration loaded","exit status=1")
建议用 jq 流式解析(不缓存整行):
Shell 脚本结构:信号安全 + 毫秒级响应 + 可退出
核心是让 journalctl -f 运行在子 shell,主脚本通过 trap 捕获 SIGINT/SIGTERM 并 clean kill 子进程:
- 用
PIPESTATUS检查journalctl | jq管道是否异常中断 - 用
read -t 0.1实现非阻塞检查,配合循环做轻量心跳(可选) - 把关键事件(start/stop/fail)echo 到 stdout,供上游(如 systemd notify、curl 上报、或 while read 消费)使用
- 示例片段:
unit="myapp.service"
cleanup() { kill "$journal_pid" 2>/dev/null; exit 0; }
trap cleanup INT TERM
journalctl -u "$unit" -o json --no-hostname -f | \
jq -r --arg u "$unit" \
'select(._SYSTEMD_UNIT == $u and (.PRIORITY == "6" or .PRIORITY == "2")) | \
"\(.PRIORITY) \(.MESSAGE | gsub("\n"; " "))"' &
journal_pid=$!
while kill -0 "$journal_pid" 2>/dev/null; do
if read -t 0.05 event; then
case "$event" in
"6 "* ) echo "[OK] $(date +%s.%3N): service up" ;;
"2 "* ) echo "[FAIL] $(date +%s.%3N): $event" ;;
esac
fi
done
进阶技巧:降低误报、适配容器与多实例
真实微服务场景需应对日志混杂、重启抖动、多副本等问题:
- 加
--grep或jq 'select(.MESSAGE | test("myapp:.*ready|shutdown"))'锁定业务日志,避开内核/audit 日志干扰 - 对同一 unit 多实例(如
myapp@1.service),用journalctl -u 'myapp@*.service'或正则匹配_SYSTEMD_UNIT - 在容器中运行时,确保宿主机 journal 可读(
--cap-add=SYS_ADMIN或挂载/run/log/journal) - 若需毫秒级精确时间戳,优先用
__REALTIME_TIMESTAMP(微秒级 Unix 时间)而非MONOTONIC_TIMESTAMP(仅本机启动后计时)
不复杂但容易忽略:journal 默认保留日志有限(/etc/systemd/journald.conf 中 SystemMaxUse=),高频监听建议设为 1G 以上,避免因日志轮转导致状态断连。











