应查 journalctl 日志:journalctl -u your-service-name -n 50 -f 或 --no-pager 查全量,重点看 process exited、failed at step exec/chdir 等错误;确认 type=、绝对路径、environment=、daemon-reload 及依赖配置。

systemctl start 失败但没报错,怎么查真实原因
服务看似启动成功,systemctl status 显示 active (running),但实际功能不可用——这往往是因为 systemd 认为“进程 fork 后退出主进程”就算启动完成,而真正的业务逻辑可能已在子进程中崩溃。
必须立刻看日志,不是看服务自己的 log 文件,而是 systemd 的 journal:
-
journalctl -u <code>your-service-name-n 50 -f(实时追最新 50 行) - 加
--since "2 minutes ago"快速定位刚发生的问题 - 如果服务刚启动就退出,
journalctl -u <code>your-service-name--no-pager 看全量,常会发现Process exited with code=exited status=1或Failed at step EXEC spawning
常见坑:没写 Type=,默认是 simple,要求主进程一直存活;但 Python/Node.js 脚本如果没加 while True: 或 server.listen(),启动后立即退出,systemd 就认为它“成功结束”了。
写 service 文件时,WorkingDirectory 和 ExecStart 路径不生效
systemd 不继承 shell 的环境或当前路径,WorkingDirectory 和 ExecStart 中的路径必须写绝对路径,且用户权限要匹配。
-
WorkingDirectory必须存在,且启动用户(User=指定的)有读+执行权限(rx),否则直接失败,journal 里只报Failed at step CHDIR spawning -
ExecStart不能写./start.sh,得写/opt/myapp/start.sh;也不能依赖$PATH,比如写python app.py可能失败,应写/usr/bin/python3 /opt/myapp/app.py - 如果要用环境变量(如
$HOME),得用Environment=HOME=/var/lib/myapp显式声明,systemd 不解析 shell 变量
重启服务时配置没更新,还是跑的老二进制或旧环境
systemd 缓存 unit 文件,改完 .service 不 reload,systemd 就继续用内存里的旧定义。
- 每次修改
/etc/systemd/system/<code>xxx.service后,必须运行:systemctl daemon-reload - 仅
systemctl restart <code>xxx不会重新读取文件,也不会触发 reload - 如果用了
systemctl edit <code>xxx,生成的覆盖片段在/etc/systemd/system/<code>xxx.service.d/,同样要daemon-reload - 验证是否生效:用
systemctl cat <code>xxx看最终合并后的完整配置,别只信自己编辑的那个文件
想让服务开机自启,enable 却提示 Unit is not loaded
说明 systemd 根本没识别到这个 unit 文件,通常因为路径错、权限错或文件名不规范。
- 确保文件放在
/etc/systemd/system/<code>xxx.service(非/lib/systemd/system/,后者是系统包管理器用的,普通用户放这里会被覆盖) - 文件名必须以
.service结尾,且中间不能有空格或大写字母(如MyApp.Service无效) - 文件权限应为
644,属主 root;如果用vim编辑时意外保存成xxx.service~,systemd 会忽略备份文件,但你可能误以为已生效 - 运行
systemctl list-unit-files | grep <code>xxx,没输出就说明没加载;再试systemctl daemon-reload,还不行就检查 journal 里有没有Failed to load xxx.service: No such file or directory
真正麻烦的是那些隐式依赖:比如服务依赖网络,但写了 After=network.target 却没写 Wants=network.target,结果 network 还没 ready 就启动,连接数据库失败——这种问题不会报 unit 加载错误,但日志里全是 timeout。










