查 systemd 状态和退出信号是第一反应:运行 systemctl status myservice 查看 Active 状态及 Process 行的 code/killed/signal;用 systemctl show 获取原始退出码;status=143 表示未响应 SIGTERM,137 表示被 SIGKILL 杀死;dmesg -T | grep "killed process" 可确认 OOM Killer 干预。

查 systemd 状态和退出信号是第一反应
守护进程由 systemd 托管时,异常退出不会“静默消失”,systemd 一定记录了退出码和信号——这是最直接的线索来源。别急着翻日志文件,先看 systemctl status 输出里的 code=exited 或 signal=SEGV 这类字段。
- 运行
systemctl status myservice,重点看Active:行状态(failed?)和下方Process:行的退出详情,比如code=killed, signal=9就是被kill -9干掉的 - 用
systemctl show myservice --property=ExecMainCode,ExecMainSignal,ExecMainStatus获取最后一次退出的原始数值,比肉眼读状态更可靠 - 注意:如果显示
code=exited, status=143,其实是SIGTERM(15)+128=143,说明是正常终止请求但进程没响应;而status=137= 128+9,就是SIGKILL,得立刻查谁动的手
确认是不是被 OOM Killer 杀掉的
SIGKILL 不留日志痕迹,但内核会记一笔——只在 dmesg 里,不在 journalctl 或任何用户日志中。很多运维卡在这一步,反复翻 /var/log/syslog 却漏掉最关键的内核现场。
- 执行
dmesg -T | grep -i "killed process",匹配时间戳是否与服务退出时刻一致 - 若看到类似
Out of memory: Kill process 12345 (java) score 921,基本可锁定;再查cat /proc/12345/oom_score看当前评分(越高越危险) - 注意:Docker 容器内进程被 cgroup OOM 终止,也会触发同一套内核机制,
dmesg同样有效,但容器运行时可能额外写日志到/var/log/daemon.log或journalctl -u docker
绕过 systemd 直接跟踪进程启动与退出
当 journalctl 没有 stdout/stderr、systemctl status 只显示 “exited” 而无细节,说明日志根本没进 journald——可能服务配置了 StandardOutput=null,或进程 fork 后子进程脱离了 systemd 控制。
- 临时用
strace -f -e trace=exit_group,exit -o /tmp/ms.strace /usr/bin/myservice直接运行二进制,捕获所有退出调用及返回码(注意:这会绕过 systemd,适合调试阶段) - 若服务是 Java 或 Python 类应用,加环境变量强制输出:比如改
systemctl edit myservice,插入Environment="JAVA_TOOL_OPTIONS=-XX:+PrintGCDetails -XX:+PrintGCApplicationStoppedTime"或Environment="PYTHONFAULTHANDLER=1" - 对 Go 程序,加
Environment="GODEBUG=schedtrace=1000"可暴露调度器卡死问题;Rust 则用RUST_BACKTRACE=1
检查依赖单元和 socket 激活干扰
有些守护进程不是自己“挂”的,而是被依赖服务拖垮的——比如数据库连不上、网络套接字未就绪、挂载点延迟出现,导致主进程初始化失败后立即退出,但错误只藏在依赖单元的日志里。
- 运行
systemctl list-dependencies --reverse myservice查它依赖哪些单元,再逐个systemctl status看状态 - 特别留意
.socket单元:如果服务是 socket-activated(如sshd.socket),systemctl status sshd.service可能显示 inactive,但真正的问题在 socket 是否 bind 成功,用ss -tlnp | grep :22和systemctl status sshd.socket对照看 - 若服务启动后几秒就退出,且
journalctl -u myservice几乎为空,大概率是依赖项 failed 导致 systemd 主动终止,此时要查journalctl -b --no-pager | grep -A3 -B3 "myservice.*failed\|dependency"
真正难定位的,往往是那些“没日志、没信号、没 core dump”的退出——这时候得怀疑是否被 TimeoutStopSec 触发的 fallback kill、是否父进程 fork 后子进程 exec 失败、或者 systemd 的 RestartSec 配置掩盖了首次失败。别只盯着服务本身,它的上下文(依赖、资源限制、启动时机)才是关键。










