自定义 systemd 服务文件必须放在 /etc/systemd/system/ 下,命名为 xxx.service(如 myapp.service),不可用空格、下划线开头或大写,且仅识别纯 .service 后缀。

systemd服务文件写在哪、叫什么名
自定义服务单元必须放在 /etc/systemd/system/ 下,文件名以 .service 结尾,比如 myapp.service。不要放 /usr/lib/systemd/system/ —— 那是系统包管理器用的,手动改会被覆盖;也不要加空格或下划线开头,systemd 会直接忽略。
常见错误现象:systemctl daemon-reload 后 systemctl list-unit-files | grep myapp 找不到,八成是路径或后缀错了。
-
/etc/systemd/system/myapp.service✅ 推荐位置 -
/lib/systemd/system/myapp.service❌ 不推荐,易被 apt/dnf 覆盖 -
myapp.service.bak❌ systemd 只认.service纯后缀 -
MyApp.Service❌ 大小写敏感,且不建议用大写
最小可用 service 文件长什么样
能跑起来的最简结构只有三块:[Unit](描述和依赖)、[Service](怎么启动)、[Install](要不要开机自启)。少任意一块,systemctl start 可能报错或静默失败。
典型错误:漏掉 Type=,结果进程一启动就退出,systemctl status 显示 inactive (dead) 或反复重启。
-
Type=simple:默认值,适用于前台运行的程序(如python3 -m http.server 8000) -
Type=forking:适用于传统 daemon(如 nginx、redis-server),要配PIDFile= -
Type=notify:需程序自己调用sd_notify(),普通脚本别乱选 -
Restart=on-failure是可选项,但没加时进程崩溃后不会自动拉起
示例(保存为 /etc/systemd/system/hello.service):
[Unit] Description=Hello World Service [Service] Type=simple ExecStart=/bin/echo "hello from systemd" RemainAfterExit=yes [Install] WantedBy=multi-user.target
权限、路径、环境变量全得手动指定
systemd 启动的服务默认没有用户 shell 环境,$PATH 极其有限(通常只有 /usr/bin:/bin),当前目录是 /,HOME 是 /root(即使你用普通用户启的)。不显式写全路径,ExecStart 里用 python 就可能找不到命令。
常见错误现象:systemctl status 显示 failed to execute /usr/bin/python: No such file or directory,其实 python 在 /usr/local/bin/python3。
-
ExecStart必须用绝对路径,/home/alice/app/run.sh不能写成./run.sh - 要用环境变量?加
Environment="PATH=/usr/local/bin:/usr/bin:/bin" - 想切用户运行?加
User=alice和Group=alice,否则默认 root - 工作目录很重要:加
WorkingDirectory=/home/alice/app,否则脚本里open("config.json")会去根目录找
重载、调试、日志怎么配合着用
改完 service 文件不能直接 systemctl start,必须先 systemctl daemon-reload,否则 systemd 还在读旧缓存。调试核心就三步:看状态、看日志、手动模拟。
容易被忽略的点:日志默认只存最近几次启动,journalctl -u myapp 看不到历史记录,得加 -n 100 或 --since "2 hours ago"。
-
systemctl daemon-reload:每次改完 .service 文件必做 -
systemctl start myapp && systemctl status -l myapp:-l 展开日志行,立刻看失败原因 -
journalctl -u myapp -n 50 -f:实时跟踪最新 50 行,适合观察启动过程 - 手动执行
ExecStart那条命令(带全路径、切换到WorkingDirectory、用指定User),能复现就说明不是 systemd 配置问题
复杂点在于:有些程序依赖 socket 激活、依赖其他服务就绪、或需要 RuntimeDirectory= 创建临时目录——这些都不是基础配置能覆盖的,得按实际依赖补全 [Unit] 里的 After=、Wants= 或加 [Service] 的对应字段。










