Linux 服务管理 systemd 实战教程

1次阅读

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

Linux 服务管理 systemd 实战教程

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=1Failed at step EXEC spawning

常见坑:没写 Type=,默认是 simple,要求主进程一直存活;但 Python/Node.js 脚本如果没加 while True:server.listen(),启动后立即退出,systemd 就认为它“成功结束”了。

写 service 文件时,WorkingDirectory 和 ExecStart 路径不生效

systemd 不继承 shell 的环境或当前路径,WorkingDirectoryExecStart 中的路径必须写绝对路径,且用户权限要匹配。

  • 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。

text=ZqhQzanResources