supervisord 配置 Go 服务需用绝对路径指定 command、显式设置 directory、配置日志路径及权限、合理设置 exitcodes=0,2 和 startsecs=5,并确保 Go 监听 0.0.0.0 而非 localhost。

supervisord 配置文件里怎么写 Go 服务的启动命令
Go 编译出的二进制是静态链接的可执行文件,supervisord 启动时不能直接依赖 shell 环境变量或当前工作目录。常见错误是写成 ./myapp 却没设 directory,结果报 No such file or directory——其实不是找不到程序,是找不到它依赖的配置文件或资源路径。
- 必须用绝对路径写
command,比如/opt/myapp/bin/myapp,别用./myapp或$HOME/myapp - 显式指定
directory,确保日志、配置、模板等相对路径能正确解析 - 加
autostart=true和autorestart=true,否则服务挂了不会自动拉起 - 如果 Go 程序需要环境变量(如
ENV=prod),用environment=ENV="prod",HOME="/root",注意双引号要保留
Go 程序退出码为 0 但 supervisor 还是反复重启
这是典型的行为错配:supervisord 默认把非零退出码当异常,但 Go 程序常因信号(SIGHUP、SIGTERM)或 os.Exit(0) 正常退出,而 supervisor 误判为崩溃。更麻烦的是,有些 Go HTTP 服务在收到 SIGTERM 后优雅关闭 listener,然后 os.Exit(0),结果被 supervisor 当成“意外终止”立刻重拉。
- 在
[program:myapp]段加startsecs=5(默认 1 秒),避免刚起来就退出被误判 - 加
exitcodes=0,2,明确告诉 supervisor:退出码 0 是合法的(比如主动 reload)、2 是你定义的 reload 信号码 - Go 侧建议用
signal.Notify捕获SIGTERM,做 graceful shutdown,但别在最后调os.Exit(0)—— 改成让主 goroutine 自然结束,这样进程退出更“安静”
supervisorctl status 显示 STARTING 或 FATAL,但没日志
根本原因是 stdout_logfile 和 stderr_logfile 没配,或者配了但目录不存在、权限不够。Go 程序默认输出到 stderr,supervisor 不转发到控制台,全靠这两个文件落地。
- 务必配全
stdout_logfile=/var/log/myapp/out.log和stderr_logfile=/var/log/myapp/err.log - 确保
/var/log/myapp/目录存在,且运行supervisord的用户(通常是root或supervisor)有写权限 - 加
stdout_logfile_maxbytes=10MB和stdout_logfile_backups=5,不然日志滚不动,最后只剩一个超大文件 - 调试时临时加
redirect_stderr=true,把 stderr 合并进 stdout 日志,减少排查维度
Go 服务监听 localhost:8080,但外部访问不到
不是端口冲突,也不是防火墙,而是 Go 默认绑定 127.0.0.1:8080,只响应本地回环。supervisor 不改变这个行为,它只是帮你拉进程。
立即学习“go语言免费学习笔记(深入)”;
- Go 代码里改监听地址:用
http.ListenAndServe(":8080", handler)替代http.ListenAndServe("127.0.0.1:8080", handler) - 确认
netstat -tuln | grep :8080输出里有*:8080,而不是127.0.0.1:8080 - 如果用了反向代理(Nginx),检查 proxy_pass 是否指向
http://127.0.0.1:8080—— 这个没问题;但如果 Go 绑死localhost,Nginx 从本机发请求也连不上
真正卡住人的地方往往不是 supervisor 配得多复杂,而是 Go 进程自己没跑在预期网络上下文里。配完记得 supervisorctl reread && supervisorctl update && supervisorctl restart myapp,再看日志——别跳过这三步。










