Ubuntu下使用monit
这是一个在类UNIX系统中进行服务监控的工具。 可以用来管理、监控进程、程序、文件、目录、文件系统。使用它可以简化运维工作,例如:
- 如果某个进程没有启动,则启动之
- 如果某个进程没有响应,自动重启
- 如果某个进程消耗过多资源,关闭之
执行下面的命令安装
1 2 3 4 |
sudo apt install monit # 启动服务 sudo service monit start |
所有配置可以在控制文件中完成。monit的行为也可以受到命令行参数的控制。默认控制文件是~/.monitrc,如果此文件找不到,则使用/etc/monitrc。
下面是一些基本配置:
1 2 3 4 5 6 7 8 9 |
# 每10秒检查被监控服务的状态 set daemon 10 # 启用内置的Web服务器 set httpd port 2812 and use address localhost allow localhost allow admin:monit allow @monit allow @users readonly |
调用格式: monit [options] {arguments}
选项 | 说明 |
-c file | 指定配置文件 |
-d n | 每隔n秒,以守护进程的方式运行monit一次 |
-g name | 设置启动、停止、监控、重启、解除监控的组名 |
-l logfile | 指定日在文件路径 |
-p pidfile | 指定守护模式的PID(锁)文件 |
-s statefile | 指定状态存储文件 |
-t | 对控制文件进行语法检查 |
参数 | 说明 |
start all | 启动控制文件中所有列出的服务,并监控它们。如果指定-g,仅仅针对目标组中的服务 |
start name | 启动指定的服务并监控,name是控制文件中服务条目的名称 |
stop all | 停止控制文件中所有列出的服务,并不再监控它们 |
stop name | 停止指定的服务并不再监控 |
restart all restart name |
重启操作 |
monitor all monitor name unmonitor all unmonitor name |
启用/禁用监控 |
status | 打印每个服务的状态 |
summary | 打印简要的状态信息 |
reload | 重新初始化守护程序,配置文件被重新读取 |
quit | 退出守护程序 |
validate | 检查控制文件中所有服务的有效性。守护模式下自动 |
procmatch regex | 用于方便的测试进程匹配检查Pattern,接受正则式为输入,打印所有匹配的进程 |
当Monit执行某个脚本或程序时,下表列出的环境变量被自动注入:
环境变量 | 说明 |
MONIT_EVENT | 在服务条目上发生的事件 |
MONIT_DESCRIPTION | 错误条件的描述 |
MONIT_SERVICE | 服务条目的名称 |
MONIT_DATE | 事件发生的日期时间(RFC 822格式) |
MONIT_HOST | 事件发生所在的主机 |
下面的环境变量仅仅对进程类的服务条目可用 | |
MONIT_PROCESS_PID | 进程的PID |
MONIT_PROCESS_MEMORY | 进程占用的内存 |
MONIT_PROCESS_CHILDREN | 子进程数量 |
MONIT_PROCESS_CPU_PERCENT | 进程CPU占用率 |
控制文件基于自己的DSL,包含三类内容:
- 全局的set语句,用于配置monit
- 全局的include语句,用于包含其它配置文件
- 1-N个服务条目
你可以在控制文件的任何服务条目中使用if、and、with、within、has、use、using、only、on、then、for、of等噪声关键字,以便符合英语语法。
这些关键字会自动被忽略,仅仅用于增强可读性。
每个服务条目以check关键字开始,后面是服务的类型。每个条目必须具有一个唯一性的名字,此名字被monit在内部使用。
目前支持的服务条目形式有:
CHECK PROCESS <unique name> <PIDFILE <path> | MATCHING <regex>>
对进程进行监控。两种变体: PIDFILE path:程序的锁(PID)文件路径,PID文件中存放进程的标识符。 如果PID文件不存在或者不包含某个运行中进程的PID,monit会自动调用服务条目的start方法 MATCHING regex:使用进程名称进行正则式匹配 |
CHECK FILE <unique name> PATH <path> 对普通文件进行监控 PATH path:文件的绝对路径。如果文件不存在,调用start方法; 如果文件不是普通文件,禁用此条目的监控 |
CHECK FIFO <unique name> PATH <path> 对FIFO文件进行监控 PATH path:文件的绝对路径。如果文件不存在,调用start方法; 如果文件不是FIFO文件,禁用此条目的监控 |
CHECK FILESYSTEM <unique name> PATH <path> 对文件系统进行监控 PATH path:文件系统的路径。如果文件系统变得不可用,调用start方法;如果目标路径不是文件系统,禁用此条目的监控 |
CHECK DIRECTORY <unique name> PATH <path> 对目录进行监控 PATH path:目录的绝对路径。如果目录不存在,调用start方法; 如果path不是目录,禁用此条目的监控 |
CHECK HOST <unique name> ADDRESS <host address> 对目标主机进行监控,依赖于ICMP(ping)报文 ADDRESS host address:目标主机的主机名或者IP地址 |
CHECK SYSTEM <unique name> 允许对系统资源,例如CPU用量、内存用量、平均负载进行监控 SYSTEM unique name:通常指定为主机名 |
CHECK PROGRAM <unique name> PATH <executable file> [TIMEOUT <number> SECONDS] 调用一个应用程序,检查其退出码 PATH executable file:可执行文件或者脚本的绝对路径 |
CHECK NETWORK <unique name> <ADDRESS <ipaddress> | INTERFACE <name>> 检查网络接口的状态 ADDRESS ipaddress:接口IP地址 |
在上述CHECK执行完毕后,服务条目的start/stop/restart方法可能被调用,执行对应的逻辑。
服务方法的语法格式:
1 2 3 4 |
<START | STOP | RESTART> [PROGRAM] = "program" [[AS] UID <number | string>] [[AS] GID <number | string>] [[WITH] TIMEOUT <number> SECOND(S)] |
特别注意:
- Monit使用系统调用execv来执行程序或脚本,因此你不能在start program里面执行写Shell命令,参考下面的变通方式:
1start program = "/bin/bash -c '/opt/gitea/start.sh'" - start program后面的命令,执行时的环境变量,和你登陆到Shell时的环境变量不同,如果出现failed to start,一定要注意检查
- 被执行的命令可以维持在前台运行,没有问题
全局的服务状态轮询间隔由 set daemon n语句确定。你可以为每一个服务条目定制轮巡间隔、是否进行轮巡:
1 2 3 4 5 6 7 8 9 10 11 12 |
# 每隔默认轮巡间隔的倍数 EVERY [number] CYCLES # 基于CRON表达式 EVERY [cron] # 示例 every "* 8-19 * * 1-5" # 工作日8-19点监控 # 基于CRON表达式指定什么时候不进行轮询调度 NOT EVERY [cron] # 示例 not every "* 0-3 * * 0" # 周日0-3点不监控 |
可以声明服务条目属于某个组,monit支持基于组进行服务控制:
1 |
GROUP groupname |
Monit支持三种服务监控模式:
1 |
MODE <ACTIVE | PASSIVE | MANUAL> |
说明如下:
- 主动模式:默认,主动监控服务,当出现问题时发出警告或者重启
- 被动模式:被动监控服务,出现问题时发出警情,但是不会尝试start/stop/restart
- 手工模式:仅仅服务是通过 monit start servicename启动的情况下,才进入主动模式
Monit支持设置服务重启次数的限制,防止无必要的无限重启。
重启次数限制机制基于服务重启次数、轮询周期数量。当在y个轮询周期内重启了x次,可以执行特定的动作:
1 2 3 4 5 6 7 |
# action可以是某个通用的动作,或者TIMEOUT(等价于UNMONITOR) IF <number> RESTART <number> CYCLE(S) THEN <action> # 示例: if 5 restarts within 5 cycles then exec "/foo/bar if 2 restarts within 3 cycles then unmonitor if 7 restarts within 10 cycles then stop |
Monit支持在start/stop/monitoring/unmonitoring之前,进行依赖项的检查。声明依赖服务条目的语法:
1 |
DEPENDS on service[, service [,...]] |
Monit内置了多种测试机制,基本语法格式:
1 2 3 4 5 6 |
# 如果测试失败,执行指定的动作 # 测试成功的动作是可选的,仅仅在测试结果从失败变为成功时执行 IF <TEST> THEN ACTION [ELSE IF SUCCEEDED THEN ACTION] # 如果测试结果变化,执行指定的动作 IF CHANGED <TEST> THEN ACTION |
所有支持的服务测试参考MAN手册。示例:
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 |
# 存在性测试,这类测试对于process, file, directory, fifo服务条目总是激活,默认行为是重启 # 语法格式: IF [DOES] NOT EXIST THEN action # 示例: check file with path /cifs/mydata if does not exist then exec "/usr/bin/mount_cifs.sh" # 资源测试,用于服务占用的资源量 # 语法格式: IF resource operator value THEN action # 示例: if cpu is greater than 50% for 5 cycles then restart # 连接测试,通过网络端口或者UNIX套接字进行,仅仅支持process,host 服务条目 # 语法格式: IF FAILED [host] <port> [ipversion] [type] [protocol | {send/expect}+] [timeout] [retry] THEN action # 示例: if failed port 53 type udp protocol dns then alert if failed port 80 then alert |
默认情况下,测试失败一次即可触发相应的动作。你可以指定,仅仅当测试失败指定的次数后,才认定失败。语法格式:
1 2 3 4 |
# 连续X次失败才认定 FOR <X> CYCLES ... # 在Y个周期(每个周期一次检查)内,X次失败才认定 <X> [TIMES WITHIN] <Y> CYCLES ... |
1 2 3 4 5 6 7 8 |
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" # 也可以指定数字 as uid 99 and with gid 99 if failed port 8080 then restart |
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# 监控Nginx,如果Nginx没有运行,记录一条日志 check process nginx with pidfile /var/run/nginx.pid # 监控Nginx,如果Nginx没有运行,启动它 check process nginx with pidfile /var/run/nginx.pid start program = "/etc/init.d/nginx start" # 复杂的逻辑 check process nginx with pidfile /var/run/nginx.pid group www start program = "/etc/init.d/nginx start" stop program = "/etc/init.d/nginx stop" if children > 250 then restart if loadavg(5min) greater than 10 for 8 cycles then stop if 3 restarts within 5 cycles then timeout # 监控Apache check process apache with pidfile /var/run/httpd.pid # 启动方法,等待超时60秒(默认30) 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 # 监控MySQL check process mysql with pidfile /var/run/mysqld/mysqld.pid group database start program = "/etc/init.d/mysql start" stop program = "/etc/init.d/mysql stop" if failed host localhost port 3306 protocol mysql then restart if 5 restarts within 5 cycles then timeout # 监控Redis check process redis with pidfile /var/run/redis/redis-server.pid start program = "/etc/init.d/redis-server start" stop program = "/etc/init.d/redis-server stop" if failed host 127.0.0.1 port 6379 then restart if 5 restarts within 5 cycles then timeout group redis_workers # 监控Tomcat 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 |
执行monit status命令时报错:monit: error connecting to the monit daemon
解决办法:编辑配置文件,添加如下内容:
1 2 3 4 |
set httpd port 2812 use address localhost allow localhost allow admin:monit |
然后执行monit reload即可解决此问题。
查看monit日志报错:Program timed out
原因:如果通过monit直接启动的那个程序,一直阻塞的话,monit就会杀死它,而且它会变为僵尸进程(也就是说monit没有适当的调用wait)
解决:使用一个包装器脚本,调用目标程序,并使用nohup解除和目标程序的关系
Leave a Reply