Monit 笔记

文章已经放到我的 github

0. 开始之前

  • 本文主要基于 Monit 官方文档, 因此跟偏向于速查手册
  • 整理 Monit 相关知识用于公司内部技术分享
  • 生产环境上主要用于进程监控和系统资源监控, 报警使用 邮件shell + bearychat
  • 个人能力有限, 如有错误欢迎指出

1. Monit 是什么

  • Monit 是一个管理和监控 Unix 系统的小型开源组件.
  • Monit 可以在出现错误的情况下, 自动维护, 修复和做一些有意义的行为

2. 为什么选择 Monit

除了 Monit 还有一些其他的第三方监控方案(eg. Supervisor), 我们考虑选择额 Monit 作为监控的原因有

  • 超轻量, 稳定, 高可用
  • 依赖少, 安装配置方便, 尽量减少运维及学习成本(即使没有任何 Monit 基础的人, 都能轻易的读懂大部分监控文件)
  • 非侵入式, 被监控的程序可以不用知道监控程序的存在(如果使用 Supervisor 监控, 则服务必须从 Supervisor 启动)
  • 基本功能完备(9 种类型监控, 邮件报警, 支持用户自定义 shell 扩展)

3. Monit 使用

3.1 概述

想要让 Monit 可靠的为我们工作, 学习成本非常低, 只需要学习一些 Monit 命令行和配置文件写法

3.2 命令行

3.2.1 常用命令
# options - 选项
- monit
- monit -t
- monit -c /var/monit/monitrc  # 指定配置文件
- monit -g <groupname> start/stop # Monit 可以对各个监控分组, 如果需要对某个分组统一操作, 可以用这个命令

# arguments - 参数
- monit reload
- monit quit
- monit start/stop/restart/monitor/unmonitor <name>/all  # <name>: 每个监控都有一个独一无二的名字, 具体后面会提到; all: 所有监控服务
3.2.2 全部命令文档

3.3 配置文件

3.3.1 概述
1. 配置文件 monitrc 优先级
# Monit 查找配置文件的优先级按如下顺序

# 命令行指定
command-line

# 配置文件
~/.monitrc
/etc/monitrc
@sysconfdir@/monitrc  # 编译安装指定配置文件路径  eg: ./configure --sysconfdir /var/monit/etc
./monitrc
2. 配置文件权限
  • 不能超过 0700 (u=xrw,g=,o=) 权限, 否则 Monit 会警告并退出
3. 配置文件支持字符
  • 关键字不区分大小写
  • 3 种: 语法字段, 十进制数字, 字符串
  • 字符串: 可以用双引号(可以包含空格)或者不用引号, 由字符和数字构成
4. 配置文件分层
  • 全局的 set 段
  • 全局的 include 段
  • 一个或多个 具体服务配置 段
3.3.2 服务监控配置文件格式

详细配置, 共计 9 种, 所有配置中, 都符合以下规则

  • 如果指定的 path 不存在, 而且配置块里包含 start 方法, 会调用这个 start 方法
  • 如果 path 指定的文件类型不对, Monit 不能监控这个项目
1. Process
CHECK PROCESS <unique name> <PIDFILE <path> | MATCHING <regex>>

<path> pid-file 的绝对路径. 不存在 pid-file 文件或者 pid-file 文件没有对应的正在运行的程序, Monit 会执行 start 方法

<regex> 进程名称的正则表达来监控进程, 可以通过命令行测试正则是否写对了: monit procmatch "regex-pattern"
2. File
CHECK FILE <unique name> PATH <path>

<path> file 的绝对路径.
3. Fifo
CHECK FIFO <unique name> PATH <path>
<path> fifo 的绝对路径.
4. Filesystem
CHECK FILESYSTEM <unique name> PATH <path>
<path> 设备/磁盘, 挂载点的路径 或 NFS/CIFS/FUSE 链接字符串. 如果文件系统不可用, Monit 会执行 start 方法
5. Directory
CHECK DIRECTORY <unique name> PATH <path>

<path> 目录问价的绝对路径
6. Remote host
CHECK HOST <unique name> ADDRESS <host>

<host> 可以是域名或者 IP 地址. eg: "tildeslash.com" or "64.87.72.95".
7. System
CHECK SYSTEM <unique name>

<unique name> 通常来说是本机名称(可以用 $HOST), 也可以是其他名称. 用于邮件报警或者 M/Monit 的初始化名称
这类配置可以监控系统资源(CPU, memory, load average...)
8. Program
CHECK PROGRAM <unique name> PATH <executable file> [TIMEOUT <number> SECONDS]

<path> 可执行程序或脚本的绝对路径. 允许检查程序退出状态.如果程序没能在 <number> 秒内执行完成, Monit 会终结这个程序, 默认是 300s
程序的输出会被记录, 用于用户界面或者报警, 默认 512 bytes(可以通过 set limits 修改)
9. Network
CHECK NETWORK <unique name> <ADDRESS <ipaddress> | INTERFACE <name>>

# <ipaddress> 是被监控的 IPv4/IPv6 网卡地址. 用 eth0 也是可以的
3.3.3 全局配置
1. 设置日志路径:
SET LOGFILE
2. 守护进程模式:
SET DAEMON <seconds>
    [[WITH] START DELAY <seconds>]

第一个 <seconds> 监控周期
第二个 <seconds> 多少时间后开始监控 - 开机启动时候比较有用

命令行:
    monit - 如果已经有后台守护 Monit 进程, 发送唤醒信号给守护进程的 Monit, 立刻开始检查
    monit quit - 关闭后台守护 Monit 进程
3. HTTPD
- 可以通过过页面做一些操作(查看状态/控制监控服务)
    默认: http://localhost:2812/

- 如果关闭可能影响某些功能
    monit status

- 强烈建议开启
    如果安全敏感性比较高, 绑定本机访问
    可以设定只读账号 `read-only`
4. 报警

Monit 提供邮件报警, 如果有其他报警方案, 可以通过自己实现 shell 脚本来扩展功能, 比如我们就通过 shell 脚本向第三方实时通讯软件 bearychat 发消息, 实现手机端的推送, 这里主要描述邮件报警的相关配置

  • 设定/取消报警
set alert foo@bar  # 默认报警邮箱, 如果有多个, 可以写多个
set alert foo1@bar

check ....
    noalert foo@bar
  • 自定义邮件格式
set mail-format {
    from: Monit Support <monit@foo.bar>
    reply-to: support@domain.com
    subject: $SERVICE $EVENT at $DATE
    message: Monit $ACTION $SERVICE at $DATE on $HOST: $DESCRIPTION.
             Yours sincerely,
             monit
}

可用变量

$EVENT
$SERVICE
$DATE
$HOST
$ACTION
$DESCRIPTION
  • 配置邮件服务器和队列
需要配置邮件服务器和队列

SET MAILSERVER
<hostname|ip-address>
[PORT number]
[USERNAME string] [PASSWORD string]
[using SSL [with options {...}]
[CERTIFICATE CHECKSUM [MD5|SHA1] <hash>],
...
[with TIMEOUT X SECONDS]
[using HOSTNAME hostname]

多个服务器可以用逗号隔开, Monit 会依次尝试, 直到找到可用的
如果没有可用的邮件服务器, 会存在本地文件系统的队列里, 等待下一次尝试(队列内部信息是持久化的)

SET EVENTQUEUE BASEDIR <path> [SLOTS <number>]

<path> 存储队列的目录
<number> 限定队列的长度

如果一台机器上运行多个 Monit 实例, 请确保队列使用不同的文件目录

5. 服务内 start/stop 方法
<START | STOP | RESTART> [PROGRAM] = "program"
    [[AS] UID <number | string>]
    [[AS] GID <number | string>]
    [[WITH] TIMEOUT <number> SECOND(S)]

check process mmonit with pidfile /usr/local/mmonit/mmonit/logs/mmonit.pid
    start program = "/usr/local/mmonit/bin/mmonit" as uid "mmonit" and gid "mmonit" with timeout 60 seconds

默认是 30s 的尝试 start/stop, 失败后会放弃尝试并打印错误信息, 全局设定是通过 SET LIMITS

6. 监控分组
monit -g <groupname> start/stop/restart

check process mmonit with pidfile /usr/local/mmonit/mmonit/logs/mmonit.pid
    GROUP groupname
    GROUP groupname1
7. 报警模式
MODE <ACTIVE | PASSIVE>

ACTIVE: 默认, 尝试重启服务, 发报警
PASSIVE: 不会尝试重启服务, 只会发报警

8. 开机行为
ONREBOOT <START | NOSTART | LASTSTATE>

START: Monit 总是启动所有监控, 不论服务在重启前是否是停止的状态
NOSTART: 永远不会自动启动监控服务. 用于一些高可用场景(XXX)

这块理解描述可能不准, 原文:

In nostart mode, the service is never started automatically after reboot. This mode is intended for a high-availability solutions with active/passive clusters. For example, a service group HA, consisting of e.g. a mobile IP alias and an application server, is started on host H1, host H2 is backup and heartbeat is in place between both hosts. The service group HA must be started on one node only. If H1 dies, H2 takes over the HA group. If H1 reboots, it is important that it won't try to start the HA group also. Even though the group was active on H1 before it crashed, as HA is running on H2 now.

LASTSTATE: 保持之前状态

9. 尝试服务重启重试次数
IF <number> RESTART <number> CYCLE(S) THEN <action>

if 2 restarts within 3 cycles then unmonitor
if 5 restarts within 5 cycles then exec "/foo/bar"
10. 依赖
DEPENDS on service[, service [,...]]

WEB-SERVER(a) -> APPLICATION-SERVER(b) -> DATABASE(c) -> FILESYSTEM(d)

当前没有服务启动
    启动顺序: d, c, b, a

当前所有服务都启动
    (monit stop all) 停止顺序: a, b, c, d;
    (monit stop d) a, b, c 也会被停止, 因为依赖 d

如果 a 没有启动
    Monit 会启动 a

如果 b 没有启动
    Monit 会停止 a, 启动 b, 最后启动 a

如果依赖包含循环或者不包含被依赖的服务, 会通告并退出

可以同时依赖多个服务
在 stop/start/monitor/unmonitor 的时候会检查 DEPENDS 语句里的服务

如果服务 stop/unmonitor, 则会 stop/unmonitor 任何依赖这个服务的服务
如果服务 start, 所有该服务依赖的服务都会先 started, 然后在 start 这个服务
如果服务 restart, 关闭依赖该服务的所有服务, 在这个服务正常启动后, 会启动 restart 之前是活跃状态的服务

11. Monit 本身相关的配置 LIMITS
SET LIMITS {
    PROGRAMOUTPUT:     <number> <unit>,
    SENDEXPECTBUFFER:  <number> <unit>,
    FILECONTENTBUFFER: <number> <unit>,
    HTTPCONTENTBUFFER: <number> <unit>,
    NETWORKTIMEOUT:    <number> <timeunit>
    PROGRAMTIMEOUT:    <number> <timeunit>
    STOPTIMEOUT:       <number> <timeunit>
    STARTTIMEOUT:      <number> <timeunit>
    RESTARTTIMEOUT:    <number> <timeunit>
}

unit is "B" (byte), "kB" (kilobyte) or "MB" (megabyte) timeunit is "MS" (millisecond) or "S" (second)
12. ACTION

Monit 监控之后可以做的行为

ALERT: 发报警
RESTART: 重启并发报警(注册的 restart 方法, 如果没有, 则先 stop 再 start)
START: 启动并发报警(注册的 start 方法)
STOP: 关闭服务并发报警, 关闭之后不会再被 Monit 检查, 重启 Monit 也不会监控这个服务, 只能从网页或者控制台再次开启 (注册的 stop 方法)
EXEC: 执行指定的脚本并报警, 可以指定用户(需要以 root 权限启动), 可以设定多次检查周期作为一个周期
    if failed <test> then exec "/usr/local/bin/sms.sh"
        as uid nobody and gid nobody
        repeat every 5 cycles
UNMONITOR: 不再监控并发报警, 关闭之后不会再被 Monit 检查, 重启 Monit 也不会监控这个服务, 只能从网页或者控制台再次开启
13.允许一定的监控公差
FOR

<X> CYCLES ...
or
<Y> [TIMES WITHIN] <Z> CYCLES ...


if failed
    port 80
    for 3 cycles
then alert

if failed
    port 80
    for 3 times within 5 cycles
then alert

<X> X 个周期连续符合条件
<Y/Z> Z 个周期内有 Y 次符合条件

cycles 最大值为 64

14. 一些判断条件的语法, 写在 CHECK 中
# process/file/directory/filesystem/fifo
IF [DOES] NOT EXIST THEN <action>
IF [DOES] EXIST THEN <action>

# system/process
IF <resource> <operator> <value> THEN <action>
    <resource>:  "CPU", "TOTAL CPU", "CPU([user|system|wait])", "MEMORY", "SWAP", "THREADS", "CHILDREN", "TOTAL MEMORY", "LOADAVG([1min|5min|15min])"
    <operator>:  "<", ">", "!=", "==" in C notation, "gt", "lt", "eq", "ne" in shell sh notation and "greater", "less", "equal", "notequal" in human readable form (if not specified, default is EQUAL)

# process
IF DISK READ [RATE] <operator> <number> <unit>/S THEN action
IF DISK READ <operator> <number> operations/S THEN action
IF DISK WRITE <operator> <number> <unit>/S THEN action
IF DISK WRITE <operator> <number> operations/S THEN action

# file
IF FAILED [MD5|SHA1] CHECKSUM [EXPECT checksum] THEN action
IF CHANGED [MD5|SHA1] CHECKSUM THEN action
# test the content of a text file
IF CONTENT <operator> <regex|path> THEN action  # 默认只有 511 字符被监控, 可以用 limit 设置该值的大小
IGNORE CONTENT <operator> <regex|path>  # 被 IGNORE 命中的行不被监控

# file/fifo/directory
IF TIMESTAMP [[operator] value [unit]] THEN action
IF CHANGED TIMESTAMP THEN action

# file
IF SIZE [[operator] value [unit]] THEN action
IF CHANGED SIZE THEN action

# filesystem
IF CHANGED FSFLAGS THEN action
IF SPACE operator value unit THEN action
IF SPACE FREE operator value unit THEN action

# filesystem
IF INODE(S) operator value [unit] THEN action
IF INODE(S) FREE operator value [unit] THEN action

# filesystem
IF READ [RATE] <operator> <number> <unit>/S THEN action
IF READ [RATE] <operator> <number> operations/S THEN action
IF WRITE [RATE] <operator> <number> <unit>/S THEN action
IF WRITE [RATE] <operator> <number> operations/S THEN action

# Service Time is the time taken to complete a read or a write operation
IF SERVICE TIME <operator> <number> <unit> THEN action

# file/fifo/directory/filesystem
IF FAILED PERM(ISSION) octalnumber THEN action
IF CHANGED PERM(ISSION) THEN action

IF FAILED [E]UID user THEN action
IF FAILED GID group THEN action
IF CHANGED PID THEN action
IF CHANGED PPID THEN action

# process/system
IF UPTIME [[operator] value [unit]] THEN action

# program
IF STATUS operator value THEN action
IF CHANGED STATUS THEN action

# network
IF FAILED LINK THEN action
IF CHANGED LINK [CAPACITY] THEN action
IF SATURATION operator value% THEN action
IF UPLOAD operator value unit/S THEN action
IF DOWNLOAD operator value unit/S THEN action
IF TOTAL UPLOADED operator value unit IN LAST number time-unit THEN action
IF TOTAL DOWNLOADED operator value unit IN LAST number time-unit THEN action
IF UPLOAD operator value PACKETS/S THEN action
IF DOWNLOAD operator value PACKETS/S THEN action
IF TOTAL UPLOADED operator value PACKETS IN LAST number time-unit THEN action
IF TOTAL DOWNLOADED operator value PACKETS IN LAST number time-unit THEN action
IF FAILED PING[4|6]
    [COUNT number]
    [SIZE number]
    [TIMEOUT number SECONDS]
    [ADDRESS string]
THEN action

# process/host
## TCP/UDP
    IF FAILED
    [HOST string]
    <PORT number>
    [ADDRESS string]
    [IPV4 | IPV6]
    [TYPE <TCP|UDP>]
    [<SSL|TLS> [with options {...}]
    [CERTIFICATE CHECKSUM [MD5|SHA1] string]
    [CERTIFICATE VALID for number DAYS]
    [PROTOCOL protocol | <SEND|EXPECT> "string",...]
    [TIMEOUT number SECONDS]
    [RETRY number]
THEN action
## SOCKET
IF FAILED
    <UNIXSOCKET path>
    [TYPE <TCP|UDP>]
    [PROTOCOL protocol | <SEND|EXPECT> "string",...]
    [TIMEOUT number SECONDS]
    [RETRY number]
THEN action
## Specific protocol test options
[<SEND|EXPECT> "string"]+
PROTO(COL) HTTP
    [USERNAME "string"]
    [PASSWORD "string"]
    [REQUEST "string"]
    [STATUS operator number]
    [CHECKSUM checksum]
    [HTTP HEADERS list of headers]
    [CONTENT < "=" | "!=" > STRING]
## MySQL
PROTOCOL MYSQL [USERNAME string PASSWORD string]
## SIP
PROTOCOL SIP [TARGET valid@uri] [MAXFORWARD n]
## SMTP
PROTOCOL SMTP[S] [USERNAME string PASSWORD string]
PROTOCOL WEBSOCKET
[REQUEST string]
    [HOST string]
    [ORIGIN string]
    [VERSION number]
3.3.4 include 配置
INCLUDE <globstring>

<globstring> 按照 glob(7) 规范, 如果匹配到目录而不是文件, 会忽略
被 include 的文件也可以 include 其他文件
如果 <globstring> 能匹配到多个, 引入没有特定的顺序, 如果你真的需要按照某些顺序, 请按顺序 include 每一条记录

3.4 高级用法

3.4.1 环境变量

你自己实现 shell 扩展的时候, 可以通过以下环境变量获取当前 Monit 监控到的问题的详细信息

- MONIT_SERVICE

# only available for service

- MONIT_DESCRIPTION
- MONIT_DATE
- MONIT_HOST

# only available for process

- MONIT_PROCESS_PID
- MONIT_PROCESS_MEMORY
- MONIT_PROCESS_CHILDREN
- MONIT_PROCESS_CPU_PERCENT

# only available for program

- MONIT_PROGRAM_STATUS
3.4.2 信号量
  • SIGUSR1 唤醒并检查所有检查项目
  • SIGTERM/SIGINT 平滑关闭守护进程
  • SIGHUP 重新初始化 -重新读取配置文件, 关闭并重开日志

4 更多

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,069评论 4 358
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,212评论 1 287
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 105,912评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,424评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,741评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,194评论 1 206
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,553评论 2 307
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,289评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,923评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,251评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,775评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,144评论 2 249
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,698评论 3 228
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,936评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,658评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,214评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,159评论 2 258

推荐阅读更多精彩内容