这类问题我又碰上了一次。CentOS 7.9 上把原来 nohup 启动的 jar 包改成 systemd 管理,ExecStart 直接照抄了 shell 命令末尾的 &,systemctl start 之后服务立刻 inactive (dead),status 显示 code=exited status=0,java 进程根本没留下。

第一反应是「程序自己 fork 到后台,前台进程直接返回」,验证下来不成立。

排查方向其实有限,先把可能性排一排。ExecStart 末尾的 & 被当成参数传给程序,systemd 不经过 shell 解析;Type=simple 下主进程退出就认为服务已经结束;没有设 RemainAfterExit,退出后 unit 马上变成 inactive。

第一件事是看 unit 的实际退出状态

systemctl status app --no-pager -l

去掉 & 让进程在前台运行

grep -n ExecStart /etc/systemd/system/app.service

接着确实要后台化就用 forking 并配 PIDFile

printf 'Type=forking\nPIDFile=/run/app.pid\n' >> /etc/systemd/system/app.service

剩下的就是重载后确认进程还在

systemctl daemon-reload && systemctl restart app && pgrep -af 'java -jar'

隔了一天再看,现象没变,说明不是偶发。

那几天正好在做别的变更,先把时间线对齐才敢动手。

恢复的判定其实很直接。服务状态 active (running),java 进程 PID 稳定,重启机器后也能自动拉起。

提醒一点。systemd 不经过 shell,管道、重定向、&& 都不会生效,复杂启动逻辑应该包一层脚本。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189