必须将合法.service文件置于/etc/systemd/system/,含unit[install]三段;execstart须用绝对路径,type需匹配脚本行为(oneshot/simple/forking),after建议设network.target,user应显式指定,修改后须先daemon-reload再enable。

直接用 systemctl enable 就行,但前提是服务得有合法的 .service 文件——没这个文件,enable 命令会报错“no such file or directory”。
怎么写一个能被 systemctl 识别的 service 文件
必须放在 /etc/systemd/system/ 下,后缀是 .service,内容至少包含三段:[Unit]、[Service]、[Install]。常见漏项或错配点:
-
ExecStart=后面必须是绝对路径,比如/usr/local/bin/myscript.sh,不能写myscript.sh或./myscript.sh -
Type=要匹配脚本行为:oneshot(运行完就退出)、simple(常驻进程)、forking(后台 fork 的老式 daemon) -
After=推荐至少加network.target,否则脚本可能在网卡还没 up 时就执行,连不上数据库或 API -
User=建议显式指定,别依赖 root;如果脚本要访问用户家目录,User必须和该目录属主一致
启用前必须 reload,否则 enable 无效
systemctl enable 不会自动重读配置,它只建软链接。如果你刚新建或改过 .service 文件,不执行 daemon-reload,enable 会静默失败或启用旧版本。
- 每次改完
.service文件后,先运行:sudo systemctl daemon-reload - 再验证语法是否合法:
sudo systemd-analyze verify /etc/systemd/system/myscript.service,有报错就别往下走 - 最后才执行:
sudo systemctl enable myscript.service
为什么 start 成功但 reboot 后没起来
最常见原因是脚本内部命令用了相对路径、没等依赖就开跑、或 stdout/stderr 没重定向导致卡住。systemd 默认不会继承 shell 环境变量,$PATH 极简,很多命令找不到。
- 脚本里所有命令都写绝对路径:用
/bin/bash不用bash,用/usr/bin/python3不用python3 - 如果脚本要访问网络或远程服务,加
ExecStartPre=/bin/sleep 5或用systemd-run --scope --on-active=10s延迟启动(不推荐,应改用After=+Wants=) - 务必设
StandardOutput=journal和StandardError=journal,否则日志全丢,journalctl -u myscript.service查不到任何线索
真正麻烦的不是写 service 文件,而是脚本本身对启动环境的假设——它在终端里能跑,不代表在 systemd 的干净、无 tty、无完整 PATH 的上下文中也能跑通。每次改完,一定用 sudo systemctl start 手动试一次,再看 journalctl 输出,比等 reboot 验证快得多。











