关键是Type=simple、ExecStart用绝对路径、Restart=on-failure、显式配置User/WorkingDirectory;需创建专用用户、重定向日志至journal,并用systemctl daemon-reload生效。

用 systemd 管理 Go 编译程序做后台服务,关键是写对 .service 文件,核心落在四点:Type、ExecStart、Restart 和运行环境。别用 nohup 或 & 临时凑合——它们扛不住系统重启、没统一日志、不响应依赖关系。
服务文件放哪、怎么命名
把服务定义文件放到 /etc/systemd/system/ 目录下,文件名必须以 .service 结尾,比如 myapp.service。命名建议小写、不含空格和特殊字符,与你的二进制名保持一致便于维护。
Type 和 ExecStart 必须配准
Go 程序默认不实现 systemd 的 notify 协议,所以 Type=simple 是最稳妥的选择(可省略不写,默认值)。别乱设 Type=notify,否则 systemd 会一直等 READY=1,超时后标记为 failed。
ExecStart 必须写绝对路径,例如:
ExecStart=/opt/myapp/bin/myapp -c /etc/myapp/config.yaml- 不能写
./myapp、myapp或~/myapp
同时配上 WorkingDirectory=/opt/myapp,确保程序读配置、写日志时路径正确。
用户权限和日志要提前安排好
避免用 User=root。推荐创建专用用户,比如:
HR组织架构与职级体系设计系统。触发场景包括: (1)组织架构设计——设计或调整公司/部门架构、部门划分、汇报关系、决策流; (2)职级体系设计——建立职级序列、职级数量、晋升通道、双通道模型; (3)胜任力模型词典——为岗位序列构建胜任力维度表、行为分级标尺; (4)职级评价(任职资格评定)——用胜任力词典评定...
sudo useradd -r -s /bin/false myapp- 然后在 service 文件里写
User=myapp和Group=myapp - 再执行
sudo chown -R myapp:myapp /opt/myapp /var/log/myapp
日志建议交给 systemd 统一管理,加这两行:
StandardOutput=journalStandardError=journal
Go 代码里也请用 log.New(os.Stderr, "", log.LstdFlags) 输出,别依赖 fmt.Println 打关键日志——systemd 对 stderr 的采集更稳定。
启动失败怎么查、怎么修
写完服务文件后,三步必做:
-
sudo systemctl daemon-reload(否则start会报 unit not found) sudo systemctl start myapp.service-
sudo systemctl status myapp.service看状态,再用journalctl -u myapp.service -n 50 -o short-precise查最近日志
常见报错及对应处理:
-
Failed at step EXEC spawning→ 检查ExecStart路径是否真实存在、是否有执行权限(chmod +x) -
Permission denied(读配置/写日志)→ 确认User对应目录的属主和权限是否正确 - 启动后立刻退出 → 检查 Go 程序是否监听了 SIGTERM 并优雅退出;或是否因 panic 导致崩溃(
Restart=on-failure可自动拉起)
确认无误后,用 sudo systemctl enable myapp.service 设为开机自启。

















