Linux journald 与 syslog 高级使用

1次阅读

journalctl -f 卡住常见于日志满、轮转或损坏,应先查磁盘用量、用 -n 10 -f 启动,必要时发 sigusr2 重载;rsyslog 时间乱序需开启 sendtimestamp=yes;过滤进程日志优先用 –identifier=,非 –unit;字段丢失因 syslog 协议限制,推荐 imfile 读 journal 文件。

Linux journald 与 syslog 高级使用

journalctl 查看实时日志却卡住不动?

默认 journalctl -f 会阻塞等待新日志,但若系统启用了 RateLimitIntervalSec 或日志被轮转、磁盘满、journal 文件损坏,它可能“假死”——光标停住、无输出、也不报错。

  • 先用 journalctl --disk-usage 看是否达到 SystemMaxUse 限制(常见于容器或嵌入式环境)
  • -n 10 强制读最近 10 行再接 -fjournalctl -n 10 -f,避免从头扫描大日志文件
  • 若仍卡住,临时禁用速率限制:systemctl kill --signal=SIGUSR2 systemd-journald(触发重载,不重启服务)
  • 注意:某些发行版(如 RHEL 8+)默认启用 Storage=volatile,重启后日志丢失,-f 只能看当前 boot 的流,不是“永久流”

syslog 转发到远程 rsyslog 时时间戳乱序?

systemd-journald 默认把日志按接收时间打戳,而传统 rsyslog 依赖 $!timestamp%timereported% 字段;如果 journald 没配好,转发过去的时间字段可能是空、重复或倒退的。

  • /etc/systemd/journald.conf 中确保:ForwardToSyslog=yes + MaxLevelSyslog=info(否则 debug 级别可能被截断)
  • 关键一步:启用 SendTimestamp=yes(默认是 yes,但某些定制镜像会关掉),否则 rsyslog 收到的是本地接收时间,不是原始事件时间
  • rsyslog 配置端要用 $!timereported(而非 $timestamp)取 journald 传来的原始时间字段
  • 验证方法:journalctl -o json | jq '.__REALTIME_TIMESTAMP'rsyslog 日志里对应行对比毫秒级数值

想用 journalctl 过滤特定进程的所有日志,但 --unit 不生效?

--unit 只匹配 systemd service 单元名,对普通进程(比如手动起的 python3 app.py)、容器内进程、或 fork 后 daemonize 的程序完全无效。

  • 优先用 --identifier=<code>APP_NAME:进程启动时通过 syslog(3)sd_journal_print() 主动写入标识符(推荐)
  • 次选用 _COMM=python3_EXE=/usr/bin/python3(注意路径必须精确,符号链接要展开)
  • 最暴力但有效:journalctl | grep -E "(app.py|my_worker)" ——但失去结构化优势,且无法跨字段关联(比如同时查 PID + MESSAGE)
  • 陷阱:_PID 是日志写入时的 PID,进程退出后该 PID 可能被复用,不能长期依赖

rsyslog 接收 journald 日志后,字段丢失(比如没有 HOSTNAMESYSLOG_IDENTIFIER)?

journald 转发给 rsyslog 用的是传统 udp/TCP syslog 协议,天然不带结构化字段;除非双方约定用 RFC5424 格式并开启 structured-data 支持,否则 rsyslog 默认只解析 timestamphostnamesyslogtag 三字段。

  • /etc/rsyslog.conf/etc/rsyslog.d/10-journal.conf 中启用:$ActionFileDefaultTemplate RSYSLOG_ForwardFormat(非默认!)
  • 更可靠方案:让 journald 直接写文件,rsyslog 用 imfile 模块读取 /var/log/journal/xxx/*.journal ——但需开 ReadKMsg=yes 并重启 journald
  • 如果坚持走网络转发,journald 必须设 ForwardToSyslog=yes 且 rsyslog 的 imudpimtcp 模块要配 $EscapeControlCharactersOnReceive off,否则 JSON 字段里的 n t 会被破坏

事情说清了就结束。真正难的不是命令怎么敲,而是搞懂哪一层在打时间戳、哪个组件在丢字段、以及为什么 journalctl -u nginx 查不到你用 curl 手动启的 nginx 进程。

text=ZqhQzanResources