
monit 默认轮询间隔过长导致 go 应用崩溃后重启延迟、状态长期显示“does not exist”,根本原因在于 `set daemon` 未显式配置,而非启动超时参数;通过缩短轮询周期并规范 pid 管理即可彻底解决。
Monit 是一款轻量级进程监控工具,但其设计为基于轮询(polling)的被动检测机制,并非实时事件驱动。这意味着它不会在进程退出的瞬间触发响应,而是依赖固定周期的主动检查。你遇到的两个核心问题——重启慢(约 1–2 分钟)和状态长期卡在 “Does not exist”——均源于默认轮询间隔未被显式优化。
? 根本原因解析
- ✅ with timeout 5 seconds 仅控制启动命令执行的最大等待时间(即 nohup ./goSite & 启动后,Monit 最多等 5 秒确认进程是否写入 PID 文件),不决定监控频率;
- ❌ set daemon 未配置或值过大(如 Debian/Ubuntu 默认为 120,即 2 分钟一轮)才是重启延迟的主因:Monit 每次轮询才检查一次 pidfile 是否存在、进程是否存活;
- ⚠️ “Does not exist” 状态是 Monit 的中间态快照:当本轮轮询发现 PID 文件丢失/进程不存在 → 触发 restart → 但新进程 PID 尚未写入或未被下一轮轮询捕获 → 状态仍显示 “Does not exist”,直到下次成功读取到有效 PID。
✅ 正确配置方案
1. 缩短全局轮询周期(关键!)
编辑主配置文件 /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(过小可能增加系统开销,尤其服务较多时)。
2. 优化进程定义(增强健壮性)
修改 /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 文件清理,避免残留导致下一次启动失败。
3. 重启 Monit 并验证
# 重载配置(推荐,平滑生效) sudo monit reload # 或完全重启(确保无残留状态) sudo systemctl restart monit # 查看实时日志 sudo tail -f /var/log/monit.log
✅ 正常行为应为:
- 进程崩溃后,5 秒内触发 restart 日志;
- 新进程启动成功后,下一个轮询周期(≤5 秒后) 即显示 status: Running;
- uptime 和 pid 字段实时更新,不再卡在 “Does not exist”。
? 替代方案建议(进阶场景)
若业务对毫秒级故障响应或复杂依赖管理有更高要求(如多进程协同、资源限制、Web UI 管理),可评估迁移至 Supervisor 或 systemd:
- Supervisor:Python 编写,原生支持子进程状态订阅、日志流式收集、HTTP RPC 接口;
- systemd:现代 Linux 标准,支持 Restart=always、RestartSec=5、PIDFile= 原生集成,无需额外守护进程。
但对于轻量级 Go Web 服务,正确配置 set daemon + 规范化 PID 管理已完全满足生产需求。
✅ 总结
| 问题现象 | 根本原因 | 解决动作 |
|---|---|---|
| 重启延迟 ≥60 秒 | set daemon 默认过大(如 120) | 修改为 set daemon 5 |
| 状态长期 “Does not exist” | 轮询间隙中状态未刷新 | 缩短轮询 + 确保 start 写 PID 原子性 |
| 启动失败误判 | timeout 过短或 PID 写入竞争 | 增加 timeout 10 seconds + 使用 && 保证顺序 |
完成上述配置后,你的 Go 服务将实现秒级故障自愈与准确的状态可视化,真正发挥 Monit 的轻量可靠优势。










