服务文件里写了ExecStartPre=,但systemctl start后主程序始终没起来。这个现象容易被误当成应用本身崩溃,实际上主程序可能根本没有执行。
先分清失败的是启动前命令还是主进程。systemd会按服务单元定义的顺序运行,前置步骤失败通常会中止启动流程。

先看启动失败的位置
运行systemctl status your.service和journalctl -u your.service -b --no-pager,查看ExecStartPre对应进程的退出码、错误输出及时间。再用systemctl cat your.service确认最终生效的单元和覆盖配置。
看到前置命令失败,不应直接修改ExecStart主程序。先确认命令路径、参数及执行环境。
理解ExecStartPre的停止规则
systemd官方服务手册规定,未带特殊忽略失败前缀的ExecStartPre=命令失败或超时,会让服务启动失败;后续ExecStart=不会照常执行。前置命令适合短时间检查,不适合长期驻留的守护进程。
有些脚本在交互式终端能运行,却依赖当前目录或用户环境变量。systemd服务环境与手动登录终端并不相同。
核对路径、账户和依赖
检查脚本是否可执行、解释器路径是否存在、User=指定账户是否有读取配置与写入目标目录的权限。需要目录或挂载先就绪时,按服务依赖和挂载关系核对,不要依赖碰巧的启动顺序。
修改单元文件后执行systemctl daemon-reload,再启动服务;排障前可先保存原配置。不要为消除报错而直接把脚本改成root运行。
不要随意忽略失败
systemd允许对特定命令使用忽略失败机制,但只有该检查结果本来就不影响主程序安全运行时才适用。数据库迁移、密钥加载、目录权限修复等前置动作失败后继续启动,可能把错误转移到业务层。
需要先判断前置步骤是可选检查,还是启动必要条件。确实可选时再调整策略,并记录业务方可接受的失败边界。
修复后的验收
重新启动后核对systemctl status中的主进程状态、前置命令退出码和journalctl新日志,再用应用本身的健康检查确认实际可用。测试环境可先在萤光云或LightNode的独立VPS上复现服务单元,避免直接改变生产启动链。
验收标准是前置步骤按预期结束,主进程稳定运行且业务健康检查通过。
FAQ
问:能直接删掉ExecStartPre吗?答:先确认它是否承担必要的准备工作。删除后服务也许能启动,但依赖文件或权限仍可能缺失。
问:为什么手动运行脚本成功,systemd里失败?答:优先检查执行用户、环境变量、工作目录与绝对路径。
温馨提示
温馨提示:修改单元前保留旧版本,并在维护窗口验证重启行为。不要把一次成功启动当成长期稳定的证明。


