monit 默认轮询间隔过长导致 go 应用崩溃后重启延迟、状态长期显示“does not exist”,根本原因在于 `set daemon` 未显式配置,而非启动超时参数;通过缩短轮询周期并规范 pid 管理即可彻底解决。
Monit 是一款轻量级进程监控工具,但其设计为基于轮询(polling)的被动检测机制,并非实时事件驱动。这意味着它不会在进程退出的瞬间触发响应,而是依赖固定周期的主动检查。你遇到的两个核心问题——重启慢(约 1–2 分钟)和状态长期卡在 “Does not exist”——均源于默认轮询间隔未被显式优化。
编辑主配置文件 /etc/monit/monitrc 或 /etc/monit.conf,确保 set daemon 在全局生效(通常位于文件顶部附近):
# 设置每 5 秒轮询一次(推荐 5–10 秒,避免过度负载) set daemon 5 # 可选:启用日志便于调试 set logfile /var/log/monit.log
? 提示:set daemon N 中 N 单位为秒,最小建议值为 5(过小可能增加系统开销,尤其服务较多时)。
修改 /etc/monit/conf.d/checkSite,修复 PID 写入可靠性与停止逻辑:
check process site with pidfile /root/go/path/to/goSitePath/run.pid
# ✅ 使用绝对路径 + 显式重定向,确保 PID 写入稳定
start program = "/bin/bash -c 'cd /root/go/path/to/goSitePath && ./goSite > /dev/null 2>&1 & echo $! > run.pid'"
with timeout 10 seconds # 启动超时适当放宽至 10s,适应 Go 初始化
# ✅ 改用更安全的停止方式:先尝试优雅终止(SIGTERM),再强制(SIGKILL)
stop program = "/bin/bash -c 'if [ -f /root/go/path/to/goSitePath/run.pid ]; then kill $(cat /root/go/path/to/goSitePath/run.pid) 2>/dev/null; sleep 2; kill -9 $(cat /root/go/path/to/goSitePath/run.pid) 2>/dev/null; rm -f /root/go/path/to/goSitePath/run.pid; fi'"
# ✅ 添加健康检查(可选但强烈推荐)
if failed host 127.0.0.1 port 3000 protocol http then restart
if 3 restarts within 5 cycles then timeout? 注意事项:
- Go 程序需监听 127.0.0.1:3000(或按实际端口调整),protocol http 会发送 HEAD / 请求验证服务可达性;
- if 3 restarts within 5 cycles then timeout 防止崩溃循环导致无限重启;
- stop program 中 rm -f run.pid 确保 PID 文件清理,避免残留导致下一次启动失败。
# 重载配置(推荐,平滑生效) sudo monit reload # 或完全重启(确保无残留状态) sudo systemctl restart monit # 查看实时日志 sudo tail -f /var/log/monit.log
✅ 正常行为应为:
若业务对毫秒级故障响应或复杂依赖管理有更高要求(如多进程协同、资源限制、Web UI 管理),可评估迁移至 Supervisor 或 systemd:

但对于轻量级 Go Web 服务,正确配置 set daemon + 规范化 PID 管理已完全满足生产需求。
| 问题现象 | 根本原因 | 解决动作 |
|---|---|---|
| 重启延迟 ≥60 秒 | set daemon 默认过大(如 120) | 修改为 set daemon 5 |
| 状态长期 “Does not exist” | 轮询间隙中状态未刷新 | 缩短轮询 + 确保 start 写 PID 原子性 |
| 启动失败误判 | timeout 过短或 PID 写入竞争 | 增加 timeout 10 seconds + 使用 && 保证顺序 |
完成上述配置后,你的 Go 服务将实现秒级故障自愈与准确的状态可视化,真正发挥 Monit 的轻量可靠优势。