服务莫名重启:用 journalctl 把原因挖出来

米阳 2025-10-24 4 10/24

服务每隔几小时重启一次,systemctl status 只显示 SIGKILL 或者 code=killed,看不出原因。这类问题要靠 journalctl 和历史记录。

先看 status 的关键行

systemctl status kb-web

重点看:

Active: failed (Result: signal) since ...
Process: 1234 ExecStart=... (code=killed, signal=KILL)
Main PID: 1234 (code=killed, signal=9)

signal=KILL 通常是两种原因:OOM Killer 杀的,或者有人 kill -9。

查 OOM

dmesg -T | grep -i -E "killed process|out of memory"
journalctl -k | grep -i oom

输出类似:

Out of memory: Killed process 1234 (python) total-vm:2100000kB, anon-rss:1800000kB

有这条就确定了:内存超限被杀。接下来查是代码泄漏还是 limit 设太小。

看重启前后的日志

journalctl -u kb-web --since "2025-10-23 00:00" --until "2025-10-24 00:00"

或者按 PID 过滤:

journalctl _PID=1234

_PID 这种方式能精确看到某个进程从启动到死亡的全部输出,非常适合查「为什么退出」。

按优先级筛

journalctl -u kb-web -p err -b          # 本次启动以来的错误
journalctl -u kb-web -p warning --since today

-p 的级别:0 emerg、1 alert、2 crit、3 err、4 warning、5 notice、6 info、7 debug。只看 3 及以下,能过滤掉大量噪音。

-b 是本次开机,-b -1 是上次开机。查「重启前发生了什么」很有用。

配置日志保留

默认 journald 可能只留几天,或者无上限写满磁盘。控制在 /etc/systemd/journald.conf:

SystemMaxUse=2G
SystemMaxFileSize=100M
MaxRetentionSec=30day

改完 systemctl restart systemd-journald。

服务本身没留日志怎么办

应用把日志写到文件而不是 stdout 时,journalctl 里什么都没有。要么改成输出到 stdout(推荐,systemd 会接管轮转),要么去看应用自己的日志。

Python 里记得 PYTHONUNBUFFERED=1,否则崩溃前的最后几行还在缓冲区里,看日志会缺最关键的信息。

分析重启频率

journalctl -u kb-web | grep -c "Started"
journalctl -u kb-web --since today | grep "Started\|Stopped\|Failed"

一天重启几十次的话,把时间点列出来,看看是否有规律(比如整点、流量高峰),能快速缩小范围。

我这次的原因

查下来是内存缓慢增长:每天涨 200M,四五天触发 OOM。根因是缓存字典没有上限,一直在往里塞。加了 LRU 上限之后稳定了。

如果只看 status,永远看不出这个。journalctl -k | grep oom 是这类问题的第一步。

- THE END -

米阳

10月24日09:50

最后修改:2025年10月24日
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论