Monit 盯着服务保持运行,并在它们倒下时把它们拉起来。第一个合情合理的问题是:既然 systemd 用一行 Restart=always 就能做同样的事,那要它干什么?
答案决定了整套安排。systemd 看到进程结束了,就把它再启动一次。但它不知道服务是否在应答请求。一个已经撞到进程数上限的 PHP-FPM,在 systemd 眼里活得好好的,而站点却在返回 502。而一个磁盘用尽的 MySQL 作为进程照样跑着,却一条查询也执行不了。而 Monit 检查的不是进程存不存在,而是它的行为:端口有没有应答、HTTP 请求返回了什么、用了多少内存。
由此得出一条规则:让 systemd 保持原样,再加上 Monit 来做功能性检查。重复去做重启已崩溃进程这件事没有意义。
配置方式
sudo apt install monit
主文件是 /etc/monit/monitrc;你自己的检查以独立文件的形式放进 /etc/monit/conf.d/。通常的开头:
set daemon 60
set logfile /var/log/monit.log
set mailserver localhost
set alert admin@example.com
每分钟轮询一次是合理的平衡。更频繁只会增加负载,并抬高因为一秒钟延迟而误重启的风险。
Web 界面:只在本地
Monit 自带一个 Web 页面,而它通常就按找到的第一份指南所示那样被打开——在所有地址上。结果就是一个可从互联网够到的服务器服务控制面板。正确的写法是:
set httpd port 2812 and
use address localhost
allow localhost
allow admin:'a-long-password'
从外部的访问走 SSH 隧道:
ssh -L 2812:localhost:2812 user@203.0.113.25
之后页面就在你自己的电脑上通过 localhost:2812 打开,而什么也不朝外。
有意义的检查
Web 服务器——不是按进程是否存在,而是按它的应答:
check process nginx with pidfile /run/nginx.pid
start program = "/bin/systemctl start nginx"
stop program = "/bin/systemctl stop nginx"
if failed host 127.0.0.1 port 80 protocol http
request "/" status = 200
for 3 cycles then restart
if 3 restarts within 10 cycles then unmonitor
这里有三行比其余的更要紧。
protocol http ... status = 200 正是这一切被配置起来的目的:服务器必须返回一个页面,而不只是把端口开着。
for 3 cycles 意思是别对单独一次失败做出反应。没有它,Monit 会因为高负载下的一次慢应答就重启服务,而那只会让事情更糟。
if 3 restarts within 10 cycles then unmonitor 是必须有的一行。如果服务因为配置错误而根本起不来,Monit 就会永远地重启它,不断加重负载并把日志填满。这一行说的是:三次失败尝试,停下来并留下一条消息。接下来需要的是人;自动化已经帮不上忙了。
磁盘空间完全不带自动化地检查,只作为一条告警:
check filesystem rootfs with path /
if space usage > 85% then alert
if inode usage > 85% then alert
关于 inode 的那一行需要单独有:它们是独立于空间耗尽的,而没有它,这种情况会悄无声息地溜过去。
检查配置
sudo monit -t
sudo systemctl reload monit
sudo monit summary
sudo monit status
monit -t 会在应用之前检查语法。而 monit summary 给出一张简短的状态表——查任何问题时都该从那里开始。
另外也请确认邮件确实发得出去。Monit 通过邮件报告事件,而如果投递没配好就不会有任何通知:服务会重启而你毫不知情——可恰恰是反复的重启才是主要信号。它们在日志里也看得到:/var/log/monit.log。
Monit 做不到的事
它不消除原因。重启是一种拖延,而一个不停被重启的服务意味着某处内存不够、或者空间在见底、或者应用在泄漏。而这个工具的价值不在重启上,而在计数器上:一天之内 nginx 重启三次,是一个否则就会悄无声息溜过去的诊断,因为站点一直都是通的。
所以该看的不是当前状态——它几乎总是绿的——而是历史:过去一周有多少次是什么东西自己爬了起来。它在一个页面上是什么样子,见下面的演示。