Linux里执行一次启动命令,服务马上能用;机器重启后,服务却显示失败、没监听端口,或者过一会儿才自己出现。手动启动是在完整登录环境里进行的,开机启动则要面对网络、磁盘挂载、用户权限和环境变量尚未就绪。
以systemd为主线,从服务状态、启动日志、依赖关系、EnvironmentFile和挂载目录五处逐项排查,并给出常见的恢复方法,避免把ExecStart改成一条能跑但无法维护的长命令。
先看失败发生在什么时候

先执行 systemctl status 服务名 --no-pager 和 journalctl -b -u 服务名 --no-pager,确认是启动即失败、等待超时、找不到文件,还是服务启动了但端口没有监听。手动执行成功不能替代开机日志。
先读本次启动日志:
- 查看本次启动日志
- 记录退出码
- 看是否超时
- 确认服务名与别名
如果日志写着依赖失败,先查被依赖的服务;如果提示文件或变量不存在,转到EnvironmentFile和挂载目录,不要先改Restart=always。变量和路径之外,磁盘写满也会让服务起不来:Docker 容器没几个系统盘却满了。
网络和挂载顺序决定能不能起

服务需要数据库、NAS挂载或网络接口时,要在Unit里明确 After= 和 RequiresMountsFor= 等关系。只写一个After不等于会自动拉起对方,Requires、Wants和实际挂载单元也要匹配。
检查依赖顺序:
- 列出服务依赖关系
- 查看挂载是否已完成
- 确认网络目标
- 把依赖写在Unit里
手动启动正常、开机失败且日志出现“No such file or directory”时,常见原因是目录还没挂载;若只差网络,检查network-online.target和实际网络管理器。
手动Shell和systemd环境不是一套

登录Shell里有PATH、HOME、代理和自定义变量,systemd服务通常只有很少的默认环境。把需要的变量写进EnvironmentFile或明确的Environment项,命令使用绝对路径,工作目录用WorkingDirectory固定。
对比systemd环境:
- 对比登录Shell的env
- 查看systemctl show环境
- 使用绝对路径
- 检查EnvironmentFile权限
把变量写入服务文件后执行daemon-reload,再重启服务
权限和目录要按运行用户验证

systemd可能以专用用户运行,而你手动启动时用的是root或当前账号。用 sudo -u 服务用户 test -r 目录、test -w 和 namei -l 检查每一级目录;挂载目录的属主、ACL和SELinux/AppArmor也要一起看。
按服务用户查目录:
- 确认User与Group
- 检查目录每一级权限
- 用服务用户测试读写
- 查看SELinux/AppArmor拒绝
目录存在但服务用户没有权限,调整属主或ACL比直接chmod 777更安全;如果是安全策略拒绝,先从日志确认规则,不要先停用防护。
修完后要重启一次验证

修改Unit后运行 systemctl daemon-reload,再停止服务、重启机器,检查服务状态、监听端口和真实功能。若服务需要挂载恢复,重启后必须确认目录仍是目标文件系统,而不是空的本地目录。
重启后做真实验收:
- daemon-reload后重启
- 查看开机日志
- 确认监听端口
- 验证实际读写功能
开机后服务处于active只说明进程存在;端口、网页、队列或任务能正常工作,才算恢复。
看到什么现象,先处理哪里
| 当前表现 | 优先检查 |
|---|---|
status显示依赖失败 |
journalctl -b与被依赖单元 |
| 报找不到文件或目录 | 挂载完成时间、WorkingDirectory与路径 |
| 手动启动成功,systemd找不到命令 | EnvironmentFile、PATH与绝对路径 |
| 服务秒退但没有权限提示 | User/Group、目录ACL与安全策略 |
| 状态active但功能不可用 | 监听端口、网页、队列和真实读写 |
不要把开机失败简单归咎于systemd
手动启动时使用的账号、环境变量、网络状态和挂载目录,和systemd启动时可能完全不同。先看本次启动日志,再判断是依赖、路径、权限还是应用自身退出;不要为了“先跑起来”直接改成root、关闭安全策略或写一条无法维护的后台命令。
开机启动恢复后的最低验收
重启后确认服务状态、监听端口、网页或队列等真实功能;再检查挂载目录不是空的本地目录,服务用户可以读写目标路径。把Unit文件、EnvironmentFile和恢复命令保存一份,下次升级或迁移时仍能复用。




