一、monit工具是什么?

monit是一个轻量的监控工具,大小在1M左右,提供的功能很丰富,能监控本机的CPU、文件、目录、进程等基本信息,也能监控本机的网卡,包括网卡UP/Down、网络流量告警,还能监控其它主机的网络可达性,包括第4层协议、第7层协议,HTTP做为第7层协议自然也支持。发现告警之后,能定义各种告警动作,包括发送邮件,重启进程,运行特定脚本/程序。

二、说明

优点:
1)Monit是一个跨平台的用来监控Unix/linux系统(比如Linux、BSD、OSX、Solaris)的工具。
2)并且不依赖任何第三方程序、插件或者库。
3)Monit可以监控服务器进程状态、HTTP/TCP状态码、服务器资源变化、文件系统变动等等,根据这些变化,可以设定邮件报警、重启进程或服务。易于安装、轻量级的实现以及强大的功能,让Monit成为一个理想的后备监控工具。

三、官网信息

官网地址:https://mmonit.com/monit/
官方文档:https://mmonit.com/monit/documentation/monit.html
最新版本:https://mmonit.com/monit/dist/monit-5.25.2.tar.gz (截止到2019年1月22日的最新版)

四、注意事项

Monit是一个开源工具,但M/Monit是收费的。

五、monit安装

由于是一个监控开源软件,其实没必要整源码包安装,博主线上用的全是yum安装,具体如下:
[root@monit ~]# yum -y install monit
查看版本
[root@monit ~]# monit -V
This is Monit version 5.25.1
Built with ssl, with ipv6, with compression, with pam and with large files
Copyright (C) 2001-2017 Tildeslash Ltd. All Rights Reserved.
说明:yum方式安装的话,是5.25.1版本的。

六、常用命令

monit -t # 配置文件检测
monit # 启动monit daemon(源码包启动方式)
systemctl start/stop/restart monit # 启动/停止/重启monit daemon(yum安装方式)
monit -c /var/monit/monitrc # 启动monit daemon时指定配置文件 (源码包启动方式)
monit reload # 当更新了配置文件需要重载(源码包启动方式)
monit status # 查看所有服务状态
monit status nginx # 查看nginx服务状态
monit stop all # 停止所有服务
monit stop nginx # 停止nginx服务
monit start all # 启动所有服务
monit start nginx # 启动nginx服务
monit -V # 查看版本

七、监控模式

Monit支持三种监控模式,
1)active--Monitj监控一个服务,为了防止一系列问题,Monit会执行以及发送警报,停止,启动,重启,这是一个缺省的模式
2)passive--Monit监控一个服务,不会尝试去修复这个问题,但还是会发送警报
3)manual--Monit监控进入active模式,通过monit的控制,比如在控制台执行命令,比如 Monit start sybase

八、配置文件

yum方式安装的配置文件默认在:
/etc/monitrc #主配置文件
/etc/monit.d/ #单独配置各项服务
友情提示:为了保护控制文件和密码的安全性,monitrc必须具有读写权限不超过700。默认的权限就是700。简而言之就是拷贝其他服务器的monit的配置文件到本机后,不要忘修改权限,否则monit启动不了
[root@monit ~]# ls -lh /etc/monitrc
-rw------- 1 root root 13K Dec 27 2017 /etc/monitrc

九、monit的配置
基本配置:

set daemon  60       
#    with start delay 240
set logfile /var/log/monit.log
set pidfile /var/run/monit.pid
set idfile /var/.monit.id
set statefile /var/.monit.state

解析:1)set daemon 60:monit以daemon的方式在后台运行,每60秒轮询一次。
2)with start delay 240:这一行我这里默认注释掉了,意思是启动后延时240s开始检测,
3)set pidfile /var/run/monit.pid:指定log文件路径
4)set pidfile /var/run/monit.pid:指定pid文件路径
5)set idfile /var/.monit.id:指定id文件路径
6)set statefile /var/.monit.state:指定state文件路径

email告警配置:

set mailserver smtp.163.com
  username xxx@xxx.com
  password xxxx
set alert yyy1@xxx
set alert yyy2@xxx
set alert yyy3@xxx

set mail-format {
     from:    xxx@xxx
     subject: monit alert --  $EVENT $SERVICE
     message: $EVENT Service $SERVICE
                   Date:        $DATE
                   Action:      $ACTION
                   Host:        $HOST
                   Description: $DESCRIPTION
}

set eventqueue
   basedir /var/monit
   slots 1000

解析:第一组命令指定smtp服务器以及发送者和接收者信息,多个接收者,多个接收者就多个“set alert”。
第二组命令指定告警邮件的格式,可用的变量为:
$EVENT: 事件
$SERVICE: 服务名称。monit将每个监控对象定义成服务,实际上就是监控对象
$DATE: 告警日期和时间
$HOST: monit运行的主机,这在多台主机都运行monit的时候有用
$ACTION: 告警发生后,monit的动作。这个动作在定义监控服务的时候指定。
$DESCRIPTION: 告警描述
第三条命令“eventqueue”指定当monit的邮件因为SMTP或者网络故障发不出去,邮件会暂存在/var/monit,消息队列是1000,超过1000的消息被丢弃

HTTPD配置:

set httpd port 2812
            allow 127.0.0.1
            allow 0.0.0.0/0.0.0.0
            allow admin:monit   read-only

解释:1)monit内置了一个http server,开启后,可以在浏览器上查看监控状态。monit强烈建议开启http server
2)允许本地和互联网任意主机能访问
3)最后那个是web界面的账号和密码,并且只有只读权限,如果账号和密码后面不跟任何权限限制,默认是有所有权限。

引用具体的服务监控配置

include /etc/monit.d/*

九、monit监控的服务类型

monit可以定义9种类型,包括process/file/fifo/filesystem/directory/system/program/network/host
1)process: 监控指定进程是否存活
2345)file/fifo/filesystem/directory: 监控指定的文件或者目录是否存在
6)system: 监控系统资源,包括CPU、内存和负载
7)program: 监控指定程序的退出代码或者运行时间的长短
8)network: 监控系统指定interface,包括up/down,带宽,误码率,流量,ping
9)host: 监控其它主机,可以定义端口、tcp/udp、protocol(http/mysql/websocket)。protocol为http的时候,还可以进一步定义url和返回内容

十、监控的语法

check <类型> <服务名> [PATH <path>] [ADDRESS <host address>]
说明:每个服务条目由关键字组成check,后面是服务类型。每个条目需要唯一的描述性名称,可以自由选择。此名称由Monit用于在内部和与用户的所有交互中引用该服务
9种监控服务分别得语法如下:
1)process(进程
CHECK PROCESS <unique name> <PIDFILE <path> | MATCHING <regex>>
解释:<path>是程序的pid文件的绝对路径。pid文件是一个包含进程唯一ID的文件。如果pid文件不存在或不包含正在运行的进程的PID编号,则Monit将调用该条目的start方法(如果已定义)。
<regex>是使用PID文件的替代方法,并使用进程名称模式匹配来查找要监视的进程。选择具有最长正常运行时间的最顶部匹配的父级,因此如果进程名称是唯一的,则此检查形式是最有用的。应该尽可能使用Pid文件,因为它定义了预期的PID。您可以测试一个进程是否匹配来自命令行使用的模式monit procmatch "regex-pattern"。这将列出匹配或不匹配的所有进程,regex模式。
2)file(文件
CHECK FILE <unique name> PATH <path>
解释:<path>是文件的绝对路径。如果文件不存在,Monit将调用该条目的start方法(如果已定义),如果<path>不指向常规文件类型(例如目录),Monit将禁用此条目的监视。如果Monit在被动模式下运行或者没有定义start方法,Monit只会在错误时发送警报。
3)fifo
CHECK FIFO <unique name> PATH <path>
解释:<path>是fifo的绝对路径。如果fifo不存在,Monit将定义调用该条目的start方法,如果<path>没有指向fifo类型(例如目录),Monit将禁用对该条目的监视。如果Monit在被动模式下运行或者没有定义start方法,Monit只会在错误时发送警报
4)filesystem(文件系统)
CHECK FILESYSTEM <unique name> PATH <path>
解释:<path>是设备/磁盘,安装点,文件或作为文件系统一部分的目录的路径。建议直接使用块特殊文件(例如Linux上的/dev/hda1或Solaris上的/dev/dsk/c0t0d0s1等)如果使用挂载点(例如/data),请注意文件系统是卸载的测试仍然是真的,因为挂载点存在。如果文件系统不可用,Monit将调用该条目的start方法(如果已定义)。如果不指向文件系统,Monit将禁用对此条目的监视。如果Monit在被动模式下运行或者没有定义start方法,Monit只会在错误时发送警报
5)directory(目录)
CHECK DIRECTORY <unique name> PATH <path>
解释:<path>是目录的绝对路径。如果目录不存在,Monit将调用该条目的start方法(如果已定义)。如果<path>不指向目录,monit将禁用对此条目的监视。如果Monit在被动模式下运行或者没有定义启动方法,Monit只会在错误时发送警报。
6)system(系统)
CHECK SYSTEM <unique name>
解释:系统唯一的名称通常是本地主机名,而是可以使用任何描述性名称。如果使用变量$ HOST作为名称,它将扩展为主机名。此检查允许监控一般系统资源,如CPU使用率,总内存使用或负载平均。该唯一名称在邮件警报中用作系统主机名,在M/Monit中用作主机条目的初始名称
7)program(自定义)
CHECK PROGRAM <unique name> PATH <executable file> [TIMEOUT <number> SECONDS]
解释:<path>是可执行程序或脚本的绝对路径。该状态测试允许一个检查程序的退出状态。如果程序没有在<number>秒内完成执行,Monit将终止它。默认程序超时为300秒(5分钟)。程序的输出被记录并在用户界面和警报中可用,默认情况下最大为512B。您可以使用set limits语句自定义限制。
8)network()
CHECK NETWORK <unique name> <ADDRESS <ipaddress> | INTERFACE <name>>
解释:<ipaddress>是受监视网络接口的IPv4或IPv6地址。也可以在Linux上使用接口名称,例如“eth0”。
9)host(远程主机)
CHECK HOST <unique name> ADDRESS <host address>
解释:主机地址可以指定为主机名字符串或点分十进制格式的IP地址字符串。例如,tildeslash.com或“64.87.72.95”。

十一、服务检测时间

三种方式:

1)轮询周期倍数

语法:

every [number] cycles

示例:每两个周期检查一次:
check process nginx with pidfile /var/run/nginx.pid
every 2 cycles

2)Cron-style

语法:

every [cron]
# [cron]
# * * * * *
# 分 时 日 月 周

示例:在上午8点到下午7点之间检查每个工作日
check program checkOracleDatabase
with path /var/monit/programs/checkoracle.pl
every " 8-19 * 1-5"

3)do-not-check(与Cron-style相反)
语法:

not every [cron]

示例:在星期日0AM到3AM之间不要在备份窗口中运行检查,否则运行具有常规轮询周期频率的检查
check process mysqld with pidfile /var/run/mysqld.pid
not every " 0-3 * 0"
注意:不要使用特定的分钟,因为Monit可能不会在那分钟运行

十二、服务重启限制

语法:IF <number> RESTART <number> CYCLE(S) THEN <action>
示例1:如果Monit将在3个周期内重新启动服务2次,将取消监视服务
if 2 restarts within 3 cycles then unmonitor
要在禁用监视后使Monit再次检查服务,请从命令行运行monit monitor servicename。
示例2:超时设置自定义exec的示例
if 5 restarts within 5 cycles then exec "/foo/bar"
示例3:停止服务的示例
if 7 restarts within 10 cycles then stop

十三、监控服务示例
一个完整的HOST监控服务语法:

check host <service> address <address or ip>
if failed
xxx
then alert
alert xx@xxx

解释:第一行是检查类型为host的服务,需要设定服务名及服务器地址;
第二行至第四行的意思是中间的预期代码xxx如果失败,则执行then alert;
最后一行alert xx@xxx配置局部推送的邮箱,可选。可以多行,表示配置多个。

第二行至第四行也可以写成一行:
if failed xxx then alert

服务测试的另一种写法:

check host <service> address <host ip address>
if <test> then <aciton1> else if succeeded then <action2>

test有几种类型
状态失效,如网络不可达,进程丢失如果失败
参数变化,如文件权限,文件md5,文件大小,日期等
参数达到门限,如CPU>80%, 磁盘空间大于85%
当test为真时,则执行action1
当从失效状态转到正常状态,则执行action2,这一句是可选项
action有5种类型
alert: 发送告警邮件
restart/start/stop: 重启/启动/停止service。在监控进程时特别有用,先定义start、stop、restart的命令,当进程丢失时,启动相应service,恢复进程
exec: 执行用户定义的命令或者脚本

下面是一个完整的监控示例:
cat /etc/monit.d/example

## system
check system $HOST
                if loadavg (1min) > 4 then alert
                if loadavg (5min) > 2 then alert
                if cpu usage > 95% for 10 cycles then alert
                if memory usage > 75% then alert
                if swap usage > 25% then alert

##host
check host csa35 with address 10.7.83.35
        if failed port 80 protocol http then alert
        if failed port 9080 protocol http then alert
        if failed port 9081 protocol http then alert

## file
check file apache_bin with path /usr/local/apache/bin/httpd
                if failed checksum and
                expect the sum 8f7f419955cefa0b33a2ba316cba3659 then unmonitor
                if failed permission 755 then unmonitor
                if failed uid root then unmonitor
                if failed gid root then unmonitor
alert security@foo.bar on {
checksum, permission, uid, gid, unmonitor
} with the mail-format { subject: Alarm! }
group server

## process
check process apache with pidfile /usr/local/apache/logs/httpd.pid
                start program = "/etc/init.d/httpd start" with timeout 60 seconds
                stop program = "/etc/init.d/httpd stop"
                if cpu > 60% for 2 cycles then alert
                if cpu > 80% for 5 cycles then restart
                if totalmem > 200.0 MB for 5 cycles then restart
                if children > 250 then restart
                if loadavg(5min) greater than 10 for 8 cycles then stop
                if failed host www.tildeslash.com port 80 protocol http
                and request "/somefile.html"
then restart
                if failed port 443 protocol https with timeout 15 seconds then restart
                if 3 restarts within 5 cycles then unmonitor
depends on apache_bin
group server

## filesystem
check filesystem datafs with path /dev/sdb1
            start program = "/bin/mount /data"
            stop program = "/bin/umount /data"
            if failed permission 660 then unmonitor
            if failed uid root then unmonitor
            if failed gid disk then unmonitor
            if space usage > 80% for 5 times within 15 cycles then alert
            if space usage > 99% then stop
            if inode usage > 30000 then alert
            if inode usage > 99% then stop
group server

##apache
check process apache with pidfile /var/run/httpd.pid
       start program = "/etc/init.d/httpd start"
       stop program  = "/etc/init.d/httpd stop"
             #如果2次轮询,进程cpu都大于40%,则告警
       if cpu > 40% for 2 cycles then alert
             #如果2次轮询,系统cpu都大于60%,则告警
       if total cpu > 60% for 2 cycles then alert
             #如果5次轮询,系统cpu都大于80%,则重启(先stop,再start
       if total cpu > 80% for 5 cycles then restart
             #如果5次轮询,内存mem都大于100MB,则stop
       if mem > 100 MB for 5 cycles then stop
             #如果8个次轮询,5分钟平均负载都大于10,则stop
       if loadavg(5min) greater than 10.0 for 8 cycles then stop

## file's timestamp
check file database with path /data/mydatabase.db
            if failed permission 700 then alert
            if failed uid data then alert
            if failed gid data then alert
            if timestamp > 15 minutes then alert
            if size > 100 MB then exec "/my/cleanup/script" as uid dba and gid dba

## directory permission
check directory bin with path /bin
            if failed permission 755 then unmonitor
            if failed uid 0 then unmonitor
            if failed gid 0 then unmonitor

## remote host
check host myserver with address 192.168.1.1
                if failed ping then alert
                if failed port 3306 protocol mysql with timeout 15 seconds then alert
                if failed port 80 protocol http
and request /some/path with content = "a string"
then alert

## network link status
check network public with interface eth0
                if failed link then alert
                if changed link then alert
                if saturation > 90% then alert
                if download > 10 MB/s then alert
                if total upload > 1 GB in last hour then alert

## custom program status output
check program myscript with path /usr/local/bin/myscript.sh
                if status != 0 then alert

十四、控制台访问验证

说明:访问Monit Web界面主要通过ALLOW选项进行控制,ALLOW选项用于指定身份验证并仅授权特定客户端进行连接。
如果正在使用Monit命令行界面,至少需要一个明文密码(见下文),否则Monit命令行界面将无法连接到Monit Web界面。
尝试连接到Monit,但提交错误的用户名和/或密码的客户端将使用其IP地址记录。

1)主机和网络允许列表

Monit维护允许连接的主机和网络的访问控制列表。您可以添加任意数量的主机,但只允许具有有效域名或其IP地址的主机。
Monit将查询名称服务器以检查任何尝试连接的主机。如果主机(客户端)正在尝试连接,但无法在访问列表中找到或无法解决,Monit将立即关闭与客户端的连接。
配置文件示例:

set httpd port 2812
allow localhost
allow my.other.work.machine.com
allow 10.1.1.1
allow 192.168.1.0/255.255.255.0
allow 10.0.0.0/8

允许列表中未提及的客户端,尝试连接到Monit将被拒绝访问,并使用其IP地址记录。

2)明文用户和密码

如果allow语句包含用单独的“:”字符分隔的用户名和密码,Monit将使用基本认证。
注意:可以使用特殊字符,但对于非字母数字,必须引用密码。
语法:
ALLOW <username>:<password>

3)PAM

在提供PAM的平台(如Linux,Mac OS X,FreeBSD,NetBSD)上支持PAM
语法:
ALLOW @<group>
其中group是允许访问Monit的Web界面的组名称

4)只读用户

最后,可以将一些用户定义为只读。只读用户可以读取Monit网页,但无法访问按钮,并且无法从Web界面更改服务

set httpd port 2812
allow admin:password
allow hauk:password read-only
allow @admins
allow @users read-only

十五、实践

要求1:监听Nginx、php-fpm及API接口

cat /etc/monit.d/http

# check nginx process
check process nginx with pidfile /run/nginx.pid
start program = "/usr/local/nginx/sbin/nginx " with timeout 10 seconds
stop program = "/usr/local/nginx/sbin/nginx -s stop"
if changed pid then restart

# check php-fpm process
check process php-fpm with MATCHING php-fpm
start program = "/usr/local/php/sbin/php-fpm" with timeout 10 seconds
stop program = "/usr/bin/killall php-fpm" with timeout 10 seconds
if failed port 9000 for 3 cycles then restart

# check http status
check host dev_xxx_http address xxx
start program = "/usr/local/php/sbin/php-fpm ; /usr/local/nginx/sbin/nginx -s reload" with timeout 10 seconds
stop program = "/usr/bin/killall php-fpm ; /usr/local/nginx/sbin/nginx -s stop" with timeout 10 seconds
if failed
port 80
protocol http
and status = 200
for 3 cycles
then restart
#alert xxx@xxx #可以单独设置新的通知者
#alert xxx@xxx

if failed
port 80
protocol http
request "/Api/Login/Get_Userinfo/"
and status = 200
for 3 cycles
then restart

要求2:监听TCP

cat /etc/monit.d/tcp

check host dev_xxx_swoole_xxx address xxx
start program = "/usr/local/php/bin/php Server.php" with timeout 10 seconds
stop program = "/usr/bin/kill -9 $(ps -aux|grep -E 'Server|swoole_server'|grep -v grep|awk '{print $2}')" with timeout 10 seconds
if failed port xxx type tcp for 3 cycles then restart