journalctl查不到日志需先确认服务是否由systemd管理;非systemd启动的服务日志不进journal,应查对应文件;配置storage=persistent并重启journald才能持久化日志。

journalctl 查不到服务日志?先确认服务是否用 systemd 管理
很多新手直接 journalctl -u nginx 却返回“no entries”,不是命令错了,而是 nginx 根本没被 systemd 启动——比如你手动跑的 /usr/sbin/nginx,它压根不进 journal。
- 用
systemctl list-units --type=service | grep nginx看服务是否注册且状态为loaded - 如果服务存在但
Active:是inactive (dead),先sudo systemctl start nginx再查 - 非 systemd 启动的服务(如用 screen 或 nohup 跑的),日志默认写到文件(如
/var/log/nginx/access.log),journalctl天然看不到 - 某些发行版(如 centos 7)默认关闭
ForwardToJournal=yes,需在/etc/systemd/system.conf中显式开启并sudo systemctl daemon-reload
grep 日志时匹配不到关键词?注意 journalctl 的输出格式和缓冲行为
journalctl -u sshd | grep "Failed password" 经常漏掉内容,因为 journalctl 默认按分页器输出,且部分字段(如 MESSAGE)可能被截断或转义;更关键的是,未加 -o short-precise 或 -o json 时,时间戳和优先级字段干扰匹配。
- 优先用
journalctl -u sshd -o cat | grep "Failed password"——-o cat去掉元数据,只留纯消息体 - 想精确匹配某字段(如
SYSLOG_IDENTIFIER),用journalctl _SYSTEMD_UNIT=sshd SYSLOG_IDENTIFIER=sshd | grep ... - 实时跟踪时别用管道接
grep,而用journalctl -u sshd -f -o cat | grep --line-buffered "Failed",否则grep缓冲会导致延迟 - 注意大小写:默认
grep区分大小写,失败登录日志里可能是failed或Failed,加-i更稳妥
日志刷屏太快撑爆磁盘?控制 journald 存储策略不能只靠 /var/log/journal
/var/log/journal 目录存在 ≠ 日志就一定存那儿——journald 默认启用 Storage=auto,若该目录不可写或权限不对,会自动 fallback 到 /run/log/journal(内存临时目录),重启即丢,根本起不到归档作用。
- 先运行
journalctl --disk-usage看实际用了多少空间,再查配置位置:journalctl --all --no-pager | head -n 10看第一行提示的 storage 路径 - 编辑
/etc/systemd/journald.conf,设Storage=persistent(强制落盘),并配SystemMaxUse=500M、MaxRetentionSec=2week - 改完必须执行
sudo systemctl restart systemd-journald,否则配置不生效;旧日志不会自动清理,要手动sudo journalctl --vacuum-size=400M - 注意 SElinux:CentOS/RHEL 上若启用了 enforcing 模式,
/var/log/journal目录需有system_u:object_r:var_log_t:s0上下文,否则 journald 拒绝写入
想导出结构化日志做分析?别直接 parse journalctl 文本输出
用 journalctl -o json 导出 JSON 是对的,但直接用 shell 脚本 jq '.MESSAGE | select(contains("timeout"))' 容易崩——因为 journal 的 JSON 输出是每行一个 JSON 对象(JSONL),但某些字段(如 MESSAGE)含换行符或双引号,jq 默认解析会报错。
- 安全做法是加
--all和--no-hostname减少干扰字段:journalctl -u app --since "2024-01-01" -o json --all --no-hostname - 用
jq -r 'select(.MESSAGE and (.PRIORITY | tonumber 过滤错误级日志,注意 <code>.PRIORITY是字符串,得转数字比对 - 批量处理大日志时,避免
journalctl -o json | jq管道阻塞,改用journalctl -o json --output-fields=MESSAGE,PRIORITY,_PID --since "1 hour ago" > logs.jsonl,再用 Python 或 awk 处理 - 不要依赖
_HOSTNAME字段做机器识别——容器环境里它常是容器 ID,不如用_MACHINE_ID或自定义SYSTEMD_LOG_LEVEL=debug注入标识
真正麻烦的从来不是查哪条日志,而是日志源头没打全字段、服务启动方式绕过 systemd、或者磁盘快满时 journald 默默切到内存模式却没人发现。这些点不在文档首页,但一出问题就卡半天。