服务每隔几小时重启一次,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 是这类问题的第一步。
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://mi-blog.cn/archives/702
共有 0 条评论