Monit 语法指南

名称

Monit : 监控Unix系统服务的辅助软件

总览

monit [options]

说明

Monit是Unix系统上管理和监控进程、程序、文件、目录和文件系统的辅助软件。
Monit可以启动、重启、关闭进程。monit也可以监控目录、文件和文件系统的变化,比如文件的时间戳、校验和以及文件大小的变化。
Monit通过可配置的 控制文件 进行监控。控制文件格式自由。
Monit可以将log写入syslog(系统log)或自己的log文件,也可以自定义警告信息来提醒你发生的错误。Monit提供一个HTTP的交互界面供你接入Monit程序。

监控什么

  1. 监控本地后台进程(process)
  2. 监控本地文件、目录和文件系统
  3. 监控网络连接
  4. 测试程序(programs)和脚本(scripts)
    • 测试一个程序的退出值,如果退出值表明错误发生可以采取一些行动或发出警告
  5. 监控本地系统资源,比如CPU利用率和系统负载

一般操作

Monit由控制行命令和控制文件(monitrc)控制。monitrc的优先级比控制行命令低。
monitrc的默认位置为~/.monitic或/etc/monitrc等。你也可以通过以下命令指定monitrc的位置
经排查packetfence的控制文件为/etc/monit.conf

1
$ monit -c /var/monit/monitrc

在Monit启动之前,你可以检查控制文件的语法错误

1
$ monit -t

启动命令是:

1
$ monit

Monit 会作为后台进程周期运行。

选项

所有选项和用法可通过以下命令查看:

1
$ monit -h

这些命令都可以在控制文件monitrc中直接设置,建议采用直接写入monitrc文件的做法。

参数

Monit启动后可以调用以下命令(以下命令省略前缀monit):

  1. start all
    • 启动控制文件中的所有服务并监控
  2. start
    • 启动特定服务
  3. stop all
    • 停止控制文件中的所有服务并取消监控
  4. stop
    -停止特定服务并取消监控
  5. restart all
    • 关闭后再启动所有服务
  6. restart
    • 重启特定服务
  7. monitor all
    • 监控控制文件中的所有服务
  8. monitor
    • 监控特定服务
  9. unmonitor
  10. status
    -打印特定服务的信息
  11. reload
    重新读入控制文件,关闭后重开log文件,初始化 Monit进程
  12. quit
    关闭Monit进程

Monit控制文件

控制文件默认位置在 ~/.monitrc。如果不存在,会依次查找/etc/monitrc,@sysconfdir@/monitrc 最后是 ./monitrc。
@sysconfdir@ 在安装monit的configure阶段时确定由./configure —sysconfdir后面的参数确定。 例如: ./configure —sysconfdir /var/monit/etc 会让 Monit 在 /var/monit/etc 目录下查找monitrc文件。
Monit采用自己的控制语言(DSL)。
注释以#开头
你可以在入口处添加 ‘if’, ‘and’, ‘with(in)’, ‘has’, ‘us(ing|e)’, ‘on(ly)’, ‘then’, ‘for’, ‘of’等噪声关键字,这些关键字会被忽略,但可以让控制语言更易读。
DSL语言中有三种符号:

- 语法
- 数字
- 字符串
    - 字符串可以加引用或不加引用
    - 不加引号的字符串由字符和数字组成,不含空格
    - 字符串可以嵌套,外层为双引号内层为单引号
    - 加引号的数字当做字符串

在语法层面上,控制文件中包含三种类型的入口:

  1. set
  2. include
  3. 服务入口

Service checks

所有的服务入口以check关键字开头,后接服务类型。每个入口都要一个唯一的名字,用来作为该服务的标识。
Monit支持9种类型

  1. process

    CHECK PROCESS | MATCHING >

  2. file

    CHECK FILE PATH

  3. fifo

    CHECK FIFO PATH

  4. filesystem

    CHECK FILESYSTEM PATH

  5. directory

    CHECK DIRECTORY PATH

  6. remote host

    CHECK HOST ADDRESS

  7. system

    CHECK SYSTEM

  8. program

    CHECK PROGRAM PATH [TIMEOUT SECONDS]
    包含程序或脚本的绝对路径,如果程序没有在number时间内运行完毕,Monit会关闭它。

  9. network

    CHECK NETWORK

    | INTERFACE >

LOGGING

Moint会记录运行状态和错误信息到文件中或系统的syslog中,在monitrc控制文件中用“set log”声明来进行log设置。
为了让monit将log输出到指定文件,使用“set log /var/log/monit log”语法,该语句会覆盖先前的log设置,也可以选择二选一的做法。
如果通过命令行 的 -l 参数设定syslog或控制文件中有“set log syslog”声明。monit会使用系统后台的syslog进程根据优先级分配信息来记录信息。
为了关闭log设置,可以在控制文件中不设置“set log”语法并且不在命令行使用 -l 参数。
log的文件格式如下

1
[date] priority : message

例如:

1
[CET Jan  5 18:49:29] info : 'localhost' Monit started

终端输出

1
set terminal batch

DAEMON MODE

使用

1
2
SET DAEMON <seconds>
[[WITH] START DELAY <seconds>]

设置monit运行周期

INIT SUPPORT

“set init”可以让monit作为前台服务运行

INCLUDE 文件

monitrc控制文件可以包含附件控制文件
语法为:

INCLUDE
例如:
include /etc/monit.d/*.cfg
会将monit.d文件加下所有已cfg为后缀的文件包含到控制文件中。

SSL 选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# Enable certificate verification for all SSL connections
# Self-signed certificates are not allowed by default
set ssl options {
verify: enable
}

# Verify certificate (via global setting)
# Allow self-signed certificate for this check
check host example with address example.com
if failed
port 443
protocol https
with ssl options {selfsigned: allow}
then alert

# Do not verify example2.com's certificate (override global setting)
check host example2 with address example2.com
if failed
port 443
protocol https
with ssl options {verify: disable}
then alert

MONIT HTTPD

可以在控制文件中进行设置使monit得到HTTP支持。

UNIX SOCKET支持

语法:

1
2
3
4
5
SET HTTPD UNIXSOCKET <path>
[UID <uid | username>]
[GID <gid | groupname>]
[PERMISSION <octal number>]
ALLOW <user:password>+

例子:

1
2
set httpd unixsocket /var/run/monit.sock
allow username:password

TCP PORT 支持

语法

1
2
3
4
SET HTTPD PORT <number>
[ADDRESS <hostname | IP-address>]
[[with] SSL {pemfile: <path>}]
ALLOW <user:password | IP-address | IP-range>+

例子:

1
2
set httpd port 2812
allow username:password

警告信息

monit会在以下情况产生警告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
o A service does not exist (e.g. process is not running)
o Cannot read service data (e.g. cannot get filesystem usage)
o Execution of a service related script failed (e.g. start failed)
o Invalid service type (e.g. if path points to directory instead of file)
o Custom test script returned error
o Ping test failed
o TCP/UDP connection and/or port test failed
o Resource usage test failed (e.g. cpu usage too high)
o Checksum mismatch or change (e.g. file changed)
o File size test failed (e.g. file too large)
o Timestamp test failed (e.g. file is older then expected)
o Permission test failed (e.g. file mode doesn't match)
o An UID test failed (e.g. file owned by different user)
o A GID test failed (e.g. file owned by different group)
o A process' PID changed out of Monit's control
o A process' PPID changed out of Monit control
o Too many service recovery attempts failed
o A file content test found a match
o Filesystem flags changed
o A service action was performed by administrator
o A network link failed
o A network link capacity changed
o A network link saturation failed
o A network link upload/download rate failed
o Monit was started, stopped or reloaded

为了通过邮件取得警告信息,可以设置全局“set alert” 声明,或在单个服务内使用alert关键字声明

设置警告接受者

当事件发生时,,moni会发送警告,警告有全局警告和局部警告两种。

全局警告:

1
SET ALERT mail-address [[NOT] {event, ...}] [REMINDER cycles]

例子:

1
set alert foo@bar

该语句表示对任意被监控的服务,每当发生警告是都会发送信息到foo@bar。

局部警告:
语法:

1
ALERT mail-address [[NOT] {event, ...}] [REMINDER cycles]

例子:

1
2
3
4
check host myhost with address 1.2.3.4
if failed port 3306 protocol mysql then alert
if failed port 80 protocol http then alert
alert foo@baz # Local service alert

你可以联合全局警告和局部警告,如果会发生冲突,局部警告优先级比全局警告高,会覆盖全局警告。

设置事件过滤器

如果你想只对特定事件发送警告,可以将这些事件列在一个事件块中:

set alert foo@bar only on { timeout, nonexist }
set alert foo@bar but not on { instance }
事件类型如下:

Event: | Failure state: | Success state:

action | “Action failed” | “Action done”
checksum | “Checksum failed” | “Checksum succeeded”
bytein | “Download bytes exceeded” | “Download bytes ok”
byteout | “Upload bytes exceeded” | “Upload bytes ok”
connection | “Connection failed” | “Connection succeeded”
content | “Content failed”, | “Content succeeded”
data | “Data access error” | “Data access succeeded”
exec | “Execution failed” | “Execution succeeded”
fsflags | “Filesystem flags failed” | “Filesystem flags succeeded”
gid | “GID failed” | “GID succeeded”
icmp | “Ping failed” | “Ping succeeded”
instance | “Monit instance changed” | “Monit instance changed not”
invalid | “Invalid type” | “Type succeeded”
link | “Link down” | “Link up”
nonexist | “Does not exist” | “Exists”
packetin | “Download packets exceeded” | “Download packets ok”
packetout | “Upload packets exceeded” | “Upload packets ok”
permission | “Permission failed” | “Permission succeeded”
pid | “PID failed” | “PID succeeded”
ppid | “PPID failed” | “PPID succeeded”
resource | “Resource limit matched” | “Resource limit succeeded”
saturation | “Saturation exceeded” | “Saturation ok”
size | “Size failed” | “Size succeeded”
speed | “Speed failed” | “Speed ok”
status | “Status failed” | “Status succeeded”
timeout | “Timeout” | “Timeout recovery”
timestamp | “Timestamp failed” | “Timestamp succeeded”
uid | “UID failed” | “UID succeeded”
uptime | “Uptime failed” | “Uptime succeeded”

设置error reminder

一般的警告只会提醒一次,设置reminder可以进行持续提醒:
语法:

1
SET ALERT mail-address [WITH] REMINDER [ON] number [CYCLES]

例:十个周期之后还是失败,则再次发出警告

1
alert foo@bar with reminder on 10 cycles

取消对某些服务的警告

为了取消某些服务的警告,可以在该服务中使用noalert声明。
例子:

1
2
3
4
5
6
7
8
set alert foo@bar

check process p1 with pidfile /var/run/p1.pid

check process p2 with pidfile /var/run/p2.pid

check process p3 with pidfile /var/run/p3.pid
noalert foo@bar

邮件信息格式

警告邮件格式可以通过“set mail-format”声明设置 。

1
set mail-format {mail-format}

例子:

1
2
3
4
5
6
7
8
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
}

设置邮件服务器

邮件服务器的声明采用“set mailserver”声明。

1
2
3
4
5
6
7
8
9
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]

例子:设置两个服务器来应对故障

1
set mailserver smtp.gmail.com, smtp.other.host

事件队列

如果没有可用的邮件服务器,monit会将事件放入文件系统的队列中,直到服务器联通。

SERVICIE METHODS

每个服务都有一个关联的start、stop和restart方法。这些方法可以让monit对该服务执行一些操作。
语法:

1
2
3
4
<START | STOP | RESTART> [PROGRAM] = "program"
[[AS] UID <number | string>]
[[AS] GID <number | string>]
[[WITH] TIMEOUT <number> SECOND(S)]

如果program 是一个shell脚本,shell脚本必须以#!开头,并在第一行确定程序使用的解释器,比如:

1
#!/bin/sh

program 必须是可执行文件(比如权限设置为0755)
可以通过以下方式直接在program中写脚本

1
stop = "/bin/sh -c 'kill -s SIGTERM `cat /var/run/process.pid`'"

默认情况下,program由启动monit的用户执行,如果monit在root用户下运行,你可以通过uid和gid切换执行的program的用户。
例如:

1
2
3
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"
stop program = "/usr/local/mmonit/bin/mmonit stop" as uid "mmonit" and gid "mmonit"

默认情况下,monit会在start/stop结束或报错前等待30秒,你可以通过timeout选项覆盖这个时间参数或全局设置set limits。
例子:

1
2
3
check process foobar with pidfile /var/run/foobar.pid
start program = "/etc/init.d/foobar start" with timeout 60 seconds
stop program = "/etc/init.d/foobar stop"

SERVICE POLL TIME

服务通过“set daemon n”声明确定服务检测的周期。
例一:每两个周期检测一次

1
2
check process nginx with pidfile /var/run/nginx.pid
every 2 cycles

例二:在工作日的8AM到7PM检测

1
2
3
check program checkOracleDatabase
with path /var/monit/programs/checkoracle.pl
every "* 8-19 * * 1-5"

例三:不在周日的0AM到3AM检测

1
2
check process mysqld with pidfile /var/run/mysqld.pid
not every "* 0-3 * * 0"

SERVICE GROUPS

例子:

1
monit -g <groupname> start

服务监控模式

monit提供两种服务监控模式:主动和被动。
语法:

1
MODE <ACTIVE | PASSIVE>

主动模式下一旦出现问题就发出警告并重启服务。默认模式为主动模式。
被动模式下,除非服务失败了,否则不会发出警告或重启服务。

系统重启和服务启动

monit支持3种重启模式: start,nostart,laststate
语法:

1
SET ONREBOOT <START | NOSTART | LASTSTATE>

start模式下,每次系统重启,monit都会开启,这个模式是默认模式。
nostart模式下,系统重启monit不会开启,需要手动开启。
laststate模式下,监控的服务与重启前的相同

服务 RESTART LIMIT

monit会在一个服务在经历一段较长时间拒绝启动或响应后 提供一个重启限制的机制。
例子:

1
if 5 restarts within 5 cycles then exec "/foo/bar"

1
if 7 restarts within 10 cycles then stop

服务依赖

语法:

1
DEPENDS on service[, service [,...]]

A依赖于B,则B会先于A被检测。
例子:

1
2
3
4
5
6
(1) check process apache with pidfile "/var/run/httpd.pid"
(2) depends on httpd
(3) ...
(4)
(5) check file httpd with path /usr/bin/httpd
(6) if failed checksum then stop

SERVICE TESTS

LIMITS

你可以设定许多限制来调整monit中缓存的大小和timeout值。通常情况下默认值是合适的,如果有需要,你可以修改下列的limit值

1
2
3
4
5
6
7
8
9
10
11
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是B、KB或MB,timeunit是MS(微妙)或S(秒)。
默认值如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
----------------------------------------------------------------------------------
| Option | Description | Default |
----------------------------------------------------------------------------------
| programOutput | limit for check program output (truncated after) | 512 B |
| sendExpectBuffer | limit for send/expect protocol test | 256 B |
| fileContentBuffer | limit for file content test (line) | 512 B |
| httpContentBuffer | limit for HTTP content test (response body) | 1 MB |
| networkTimeout | timeout for network I/O | 5 s |
| programTimeout | timeout for check program | 300 s |
| stopTimeout | timeout for service stop | 30 s |
| startTimeout | timeout for service start | 30 s |
| restartTimeout | timeout for service restart | 30 s |
----------------------------------------------------------------------------------

一般语法

monit 提供许多if-tests,供你在check声明中多角度测试一个服务。
语法:

1
IF <test> THEN <action> [ELSE IF SUCCEEDED THEN <action>]

action操作会在test为真的时候执行,success操作是可选操作,只会在状态由failure转到成功时执行,如果success操作不设定,monit会默认发送恢复警告。
变值测试:

1
IF CHANGED <test> THEN <action>

每当test值改变时,会执行action。

ACTION

你可以选择一下的action进行测试:

  1. alert :
    • 发送警告
  2. restart:
    • 重启服务并发送警告,restart会调用设定的restart方法,如果没有设定restart方法,会先调用stop方法再调用start方法
  3. start :
    • 通过调用服务注册的start方法来启动服务,并发送警告。
  4. stop :
    • 通过调用服务注册的stop方法来关闭服务,并发送警告。关闭的服务monit不会再监听,为了再次监听该服务,你必须再网页或命令行进行操作。
  5. exec :

    • 用来执行任意program并发送警告。你必须确保program是可执行的(如0755)。如果program需要传入参数,需要将program和参数包在一个带引号的字符串里。选择执行程序的uid和gui参数是可选的。如果测试失败program只会执行一次。如果错误在指定周期依旧存在,可以设置repeat参数让program重复执行。
      例:

      1
      2
      3
      if failed <test> then exec "/usr/local/bin/sms.sh"
      as uid "nobody" and gid "nobody"
      repeat every 5 cycles

      记住,如果monit是工作在root用户下,除非使用uid和gid关键字,所有的program会拥有超级用户权限。

  6. ummonitor:
    • 取消监控并发送警告

错误容忍

默认情况下,如果发生错误会马上发出警告,但可以利用for 语句给与错误一定的容忍度。
语法:

1
2
3
 FOR <X> CYCLES ...
or:
<X> [TIMES WITHIN] <Y> CYCLES ...

例:

1
2
3
4
if failed
port 80
for 3 cycles
then alert

1
2
3
4
if failed
port 80
for 3 times within 5 cycles
then alert
1
2
3
check filesystem rootfs with path /dev/hda1
if space usage > 80% for 5 times within 15 cycles then alert
if space usage > 90% for 5 cycles then exec '/try/to/free/the/space'

存在测试

存在测试是基于被监控对象存在与否来触发action的。它支持process、file、directory、filesystem和fifo服务。

NON-EXIST

语法:

IF [DOES] NOT EXIST THEN
例:

1
2
check filesystem disk1 with path /dev/sda1
if does not exist then exec "/sbin/mount..."

EXIST

语法:

IF [DOES] EXIST THEN
例:

1
2
check process vmware matching "vmware"
if exist then exec "/usr/bin/pkill -9 vmware"

1
2
check file x with path /some/path/x
if exist then alert

资源测试

monit可以检测一个服务的资源占用数。该测试只能在控制文件中的系统服务或process服务中使用。
语法:

1
IF <resource> <operator> <value> THEN <action>

operator是操作符,包括:

- C语言中的操作符          :"<", ">", "!=", "=="
- shell语言中的操作符  :"gt", "lt", "eq", "ne" 
- 自然语言操作符           :"greater", "less", "equal", "notequal"

value可以是整数或实数。
action可选值: “ALERT”, “RESTART”, “START”, “STOP”, “EXEC” or “UNMONITOR”
resource由服务类型决定。

系统资源测试

  1. LOADAVG([1min|5min|15min])表示系统平均负载,平均负载是在系统运行队列里指定时间内的平均进程数量,
    例;

    1
    2
    3
    if loadavg (1min) > 90 for 15 cycles then alert
    if loadavg (5min) > 80 for 10 cycles then alert
    if loadavg (15min) > 70 for 8 cycles then alert
  2. CPU([user|system|wait]) 是系统在用户空间和内核空间以及I/O所发费的时间所占百分比。
    “user/system/wait”修饰语是可选的,如果不使用这些修饰语,则测试的是系统总的CPU利用率。
    例:

    1
    if cpu usage > 95% for 10 cycles then alert
  3. MEMORY 是系统内存使用率或实际使用容量。
    例:

    1
    if memory usage > 75% for 5 cycles then alert
  4. SWAP 是系统交换交换空间使用容量的占比或实际使用容量。
    例:

    1
    if swap usage > 20% for 10 cycles then alert

进程资源测试

  1. CPU 是进程自身的CPU使用率。
    例:

    1
    if cpu > 10% for 5 cycles then restart
  2. TOTAL CPU 是进程及其子进程总的CPU占用率
    例:

    1
    if total cpu > 50% for 10 cycles then restart
  3. THREADS是进程总的线程数。
    例:

    1
    if threads > 3 then alert
  4. CHILDREN 是一个进程的子进程数。
    例:

    1
    if children > 10 then alert
  5. MEMORY 是进程自身的内存使用率或使用容量。
    例:

    1
    if memory usage > 8MB then alert
  6. TOTAL MEMORY是进程及子进程的内存使用率或使用容量。
    例:

    1
    if total memory usage > 1% for 10 cycles then alert

PROCESS DISK I/O TEST

monit可以测试进程的文件系统读写活动。该测试只能用于process的服务类型。monit需要运行在root用户下已激活该测试。

文件校验和 测试

时间戳测试

文件大小测试

文件内容测试

FILESYSTEM MOUNT FLAGS TEST

空间使用率测试

索引使用率测试

DISK I/O TEST

权限测试

UID测试

GID测试

PID测试

语法:

1
IF CHANGED PID THEN action

例:

1
2
check process sshd with pidfile /var/run/sshd.pid
if changed pid then alert

PPID 测试

运行时间测试

语法:

1
IF UPTIME [[operator] value [unit]] THEN action

例:

1
2
3
4
check process myapp with pidfile /var/run/myapp.pid
start program = "/etc/init.d/myapp start"
stop program = "/etc/init.d/myapp stop"
if uptime > 3 days then restart

安全属性测试

PROGRAM STATUS 测试

你可以测试一个program或脚本的退出值,该测试只能用于program服务类型。
语法:

1
2
IF STATUS operator value THEN action
IF CHANGED STATUS THEN action

operator是操作符,包括:

- C语言中的操作符          :"<", ">", "!=", "=="
- shell语言中的操作符  :"gt", "lt", "eq", "ne" 
- 自然语言操作符           :"greater", "less", "equal", "notequal"

action可选值: “ALERT”, “RESTART”, “START”, “STOP”, “EXEC” or “UNMONITOR”
例:

1
2
check program myscript with path /usr/local/bin/myscript.sh
if status != 0 then alert

脚本/usr/local/bin/myscript.sh 内容如下:

1
2
3
#!/bin/sh
echo test
exit $?

你可以向program中传入参数。

1
2
check program list-files with path "/bin/ls -lrt /tmp"
if status != 0 then alert

程序或脚本的参数是以空格分离的字符串序列。在上例中,字符串’-lrt’和’/tmp/‘是程序’/bin/ls’的参数。如果使用了参数,建议使用’’来包围字符串。如果不含参数,加引号不是必须的。
请注意,如果程序是一个脚本,需要在脚本的第一行指定解释器,且程序或脚本必须是可执行的。
如果monit是在超级用户下运行的,你可以在其他用户或组下运行程序。
例如,下例中’ls’程序在用户www和组staff下运行:

1
2
3
check program ls with path "/bin/ls /tmp/" as uid "www"
and gid "staff"
if status !=0 then alert

monit会周期的执行程序,如果程序的退出状态与期望值不匹配就执行一些操作。在上例中,monit会在程序退出值不为0时产生警告。通常,0意味着程序退出正常(没有异常,0 error)。

程序检测(program check)是异步的,Monit不会去等待程序退出,相反的,Monit会在后台开启程序然后继续检测控制文件中的其他服务。在下个循环中,Monit会检测程序是否结束,如果结束,就收集程序的退出状态。如果这个退出状态意味着错误发生,Monit会产生包含程序的错误输出的警告信息。若该次循环中程序没有退出,Monit会等到下次循环。若程序运行超过五分钟,Monit会杀掉该进程并产生一个超时事件,默认的超时时间可以覆盖。
程序检测的异步特性使Monit能够非阻塞的运行,但这有一个副作用:当程序已经结束运行并等待Monit来收集结果时,该进程变成了一个僵尸进程。一个僵尸进程不消耗系统资源(除了保留pid),并处在Monit的控制下,僵尸进程在Monit收集完退出状态时从系统中移除。这意味着每个”check program”都关联着一个运行的进程或者僵尸进程。
由很多状态测试都可以使用,例:

1
2
3
4
check program hwtest with path /usr/local/bin/hwtest.sh
with timeout 500 seconds
if status = 1 then alert
if status = 3 for 5 cycles then exec "/usr/local/bin/emergency.sh"

网络接口测试

网络ping测试

连接测试

管理Monit实例(M/Monit专属)

M/Monit扩展了Monit的功能,能够监控所有的Monit主机。

配置案例

start

最简单的形式是就是check声明,在本例中,我们检测服务是否在运行,如果不在运行就产生警告:

1
check process nginx with pidfile /var/run/nginx.pid

为了让Monit在该进程没有运行时启动该进程,需要添加一个start声明:

1
2
check process nginx with pidfile /var/run/nginx.pid
start program = "/etc/init.d/nginx start"

stop/failed

下面是一个更高级的例子用来监控Apache网页服务器,该服务器监听HTTP和HTTPS的默认端口。在该例中,Monit会在Apache服务器不接受端口连接的时候,重启Apache服务器。Monit重启的方法是先执行stop程序,等待进程关闭后(最多30秒),执行start程序,然后等待30秒到服务启动。stat和stop程序的等待时间可以通过“timeout”选项重写。如果你要求发送警告信息,当Monit无法start或stop服务时,会发送一条失败错误信息。

1
2
3
4
5
check process apache with pidfile /var/run/httpd.pid
start program = "/etc/init.d/httpd start" with timeout 60 seconds
stop program = "/etc/init.d/httpd stop"
if failed port 80 for 2 cycles then restart
if failed port 443 for 2 cycles then restart

uid/gid

以下实例展示你可以以指定的用户和组来运行程序。许多后台进程可以自己切换uid和gid,但对于那些没有这种能力的程序,Monit以指定用户启动程序的功能会很有帮助。在这个实例中,我们以标准的nobody用户和组开启 Tomcat Java Servlet Engine。请注意,Monit只能在超级用户下才能切换uid和gid,否则相关声明会被忽略。

1
2
3
4
5
6
7
check process tomcat with pidfile /var/run/tomcat.pid
start program = "/etc/init.d/tomcat start"
as uid "nobody" and gid "nobody"
stop program = "/etc/init.d/tomcat stop"
# You can also use id numbers instead and write:
as uid 99 and with gid 99
if failed port 8080 then alert

udp

在下例中,我们使用udp进行连接测试,检测name-server是否在运行

1
2
3
4
check process named with pidfile /var/run/named.pid
start program = "/etc/init.d/named start"
stop program = "/etc/init.d/named stop"
if failed port 53 use type udp protocol dns then restart

unix

下例展示:如果Sophie通过Unix domain socket答应连接时,如何检测

1
2
3
4
check process sophie with pidfile /var/run/sophie.pid
start program = "/etc/init.d/sophie start"
stop program = "/etc/init.d/sophie stop"
if failed unix /var/run/sophie then restart

apache

Apache服务器跑在本机,响应基于IP的虚拟主机

1
2
3
4
5
6
check process apache with pidfile /var/run/httpd.pid
start "/etc/init.d/httpd start"
stop "/etc/init.d/httpd stop"
if failed host www.sol.no port 80 then alert
if failed host shop.sol.no port 443 then alert
if failed host chat.sol.no port 80 then alert

为确保Monit和HTTP服务器通信,添加一个协议测试

1
2
3
4
5
6
check process apache with pidfile /var/run/httpd.pid
start "/etc/init.d/httpd start"
stop "/etc/init.d/httpd stop"
if failed
host www.sol.no port 80 protocol http
then alert

也可以利用send/expect 机制

1
2
3
4
5
6
7
8
check process apache with pidfile /var/run/httpd.pid
start "/etc/init.d/httpd start"
stop "/etc/init.d/httpd stop"
if failed
host www.sol.no port 80 and
send "GET / HTTP/1.1\r\nHost: www.sol.no\r\n\r\n"
expect "HTTP/[0-9\.]{3} 200.*"
then alert

ping

1
2
check host www.tildeslash.com with address www.tildeslash.com
if failed ping then alert

checksum

1
2
3
4
5
6
7
8
check process apache with pidfile /var/run/httpd.pid
start program = "/etc/init.d/httpd start"
stop program = "/etc/init.d/httpd stop"
if failed host www.tildeslash.com port 80 then restart
depends on apache_bin

check file apache_bin with path /usr/local/apache/bin/httpd
if failed checksum then unmonitor
1
2
3
4
5
6
check host mmonit.com with address mmonit.com
if failed
port 80 protocol http and
request "/monit/dist/monit-5.7.tar.gz"
with checksum f9d26b8393736b5dfad837bb13780786
then alert

sip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
check process freeswitch
with pidfile /usr/local/freeswitch/log/freeswitch.pid
start program = "/usr/local/freeswitch/bin/freeswitch -nc -hp"
stop program = "/usr/local/freeswitch/bin/freeswitch -stop"
if total memory > 1000.0 MB for 5 cycles then alert
if total memory > 1500.0 MB for 5 cycles then alert
if total memory > 2000.0 MB for 5 cycles then restart
if cpu > 60% for 5 cycles then alert
if failed
port 5060 type udp protocol SIP
target me@foo.bar and maxforward 10
then restart

check process asterisk
with pidfile /var/run/asterisk/asterisk.pid
start program = "/usr/sbin/asterisk"
stop program = "/usr/sbin/asterisk -r -x 'shutdown now'"
if total memory > 1000.0 MB for 5 cycles then alert
if total memory > 1500.0 MB for 5 cycles then alert
if total memory > 2000.0 MB for 5 cycles then restart
if cpu > 60% for 5 cycles then alert
if failed
port 5060 type udp protocol SIP
and target me@foo.bar maxforward 10
then restart

every

1
2
3
4
check process dynamo with pidfile /etc/dynamo.pid every 2 cycles
start program = "/etc/init.d/dynamo start"
stop program = "/etc/init.d/dynamo stop"
if failed port 8840 then alert

group

1
2
3
4
5
6
7
8
9
10
11
12
13
check process sybase with pidfile /var/run/sybase.pid
start = "/etc/init.d/sybase start"
stop = "/etc/init.d/sybase stop"
mode passive
group database

check process oracle with pidfile /var/run/oracle.pid
start program = "/etc/init.d/oracle start"
stop program = "/etc/init.d/oracle stop"
if failed
port 9001 protocol tns
then restart
group database

CPU

1
2
3
4
5
6
7
check process apache with pidfile /var/run/httpd.pid
start program = "/etc/init.d/httpd start"
stop program = "/etc/init.d/httpd stop"
if cpu > 40% for 2 cycles then alert
if total cpu > 60% for 2 cycles then alert
if total cpu > 80% for 5 cycles then restart
if mem > 100 MB for 5 cycles then stop

timestamp

1
2
3
check file httpd.conf with path /etc/httpd/httpd.conf
if changed timestamp
then exec "/etc/init.d/httpd graceful"

depend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
check process apache with pidfile /var/run/httpd.pid
start = "/etc/init.d/httpd start"
stop = "/etc/init.d/httpd stop"
alert admin@bar on {nonexist, timeout}
with mail-format {
from: bofh@$HOST
subject: apache $EVENT - $ACTION
message: This event occurred on $HOST at $DATE.
Your faithful employee,
monit
}
if failed host www.tildeslash.com port 80 then restart
depend httpd_bin
group apache

check file httpd_bin with path /usr/local/apache/bin/httpd
alert security@bar on {checksum, timestamp,
permission, uid, gid}
with mail-format {subject: Alaaarrm! on $HOST}
if failed checksum
and expect 8f7f419955cefa0b33a2ba316cba3659
then unmonitor
if failed permission 755 then unmonitor
if failed uid "root" then unmonitor
if failed gid "root" then unmonitor
if changed timestamp then alert
group apache

After Oracle restart, Apache restart

1
2
3
4
5
6
7
8
9
check process apache with pidfile /var/run/httpd.pid
start = "/etc/init.d/httpd start"
stop = "/etc/init.d/httpd stop"
depends on oracle

check process oracle with pidfile /var/run/oracle.pid
start = "/etc/init.d/oracle start"
stop = "/etc/init.d/oracle stop"
if failed port 9001 for 5 cycles then restart

if oracle restart oracle-import and oracle-export restart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
check process oracle with pidfile /var/run/oracle.pid
start = "/etc/init.d/oracle start"
stop = "/etc/init.d/oracle stop"
if failed port 9001 for 3 cycles then restart

check process oracle-import
with pidfile /var/run/oracle-import.pid
start = "/etc/init.d/oracle-import start"
stop = "/etc/init.d/oracle-import stop"
depends on oracle

check process oracle-export
with pidfile /var/run/oracle-export.pid
start = "/etc/init.d/oracle-export start"
stop = "/etc/init.d/oracle-export stop"
depends on oracle

文件

~/.monitrc是默认的控制文件。
/etc/monitrc:如果默认控制文件 不存在,/etc/下包含monitrc文件,则会使用该文件作为控制文件。
./monitrc:如果上述文件都不存在,而该文件存在,则使用该文件为控制文件。
~/.monit.pid :防止程序并行运行的锁文件。
/run/monit.pid:root模式下防止程序并行运行的锁文件。
/var/run/monit.pid :root模式下防止程序并行运行的锁文件。
/etc/monit.pid:root模式下防止程序并行运行的锁文件(root mode, systems without /var/run)。
~/.monit:
~/.monit.id: 保存Monit自身的ID

环境

Monit不使用环境变量,但当Monit执行一个start或stop程序时或执行操作时,会设置一些环境变量供可执行程序取得触发操作(action)的事件信息。
以下的环境变量由Monit为每个程序(including check program)设置。

MONIT_SERVICE

程序执行的服务名。

只在service start/stop/restart program 和exec action 上下文中有效的环境变量。

  1. MONIT_EVENT: 服务发送的事件
  2. MONIT_DESCRIPTION: 错误条件的描述
  3. MONIT_DATE: 事件发送时间
  4. MONIT_HOST: 事件发送主机

只在check process start/stop/restart program 和 exec action 上下文中有效的环境变量:

  1. MONIT_PROCESS_PID: 进程pid,如果进程被启动或重启,其值可能为0
  2. MONIT_PROCESS_MEMORY: 进程内存,如果进程被启动或重启,其值可能为0
  3. MONIT_PROCESS_CHILDREN: 子进程,如果进程被启动或重启,其值可能为0
  4. MONIT_PROCESS_CPU_PERCENT:进程cpu%,如果进程被启动或重启,其值可能为0

只在在check program start/stop/restart program 和 exec action上下文中有效的环境变量。

  1. MONIT_PROGRAM_STATUS: 程序状态(退出值/exit value)