运维工具monit的配置与使用

"monit的配置与使用"

Posted by Simon on July 9, 2020

“Better code, better life. ”

Monit介绍

Monit是一个管理和监视进程,程序,文件,目录和Unix系统上的文件系统的工具。使用Monit我们可以很方便的进行自动运维,并可以在程序发生错误的情况下执行一些自定义的操作。Monit可以启动一个不运行的进程,重启一个没有响应的进程,停止一个使用了太多资源的进程。可以使用Monit来监视文件、执行各种TCP/IP网络检查、SSL协议检查、目录和文件系统的变化,比如时间戳的变化、校验和的变化化等等,可谓功能丰富。

安装与配置

安装与测试

#centos/redhat
sudo yum install monit -y
#ubuntu
sudo apt-get install monit

monit服务需要配置文件monitrc来运行,monit安装后有一个默认的配置文件在/var/monit/monitrc目录下。

测试运行
$monit -t
$Control file syntax OK
运行
$monit -c /var/monit/monitrc

start-stop-daemon安装

我这边部署的monit服务底层是依赖于start-stop-daemon这个工具的,当然也可以用其他的守护进程工具替代

#CentOS 6.5
wget http://ftp.de.debian.org/debian/pool/main/d/dpkg
tar -xf dpkg_1.16.18.tar.xz && cd dpkg_1.16.18
./configure
# configure: error: no curses library found 
yum install ncurses-devel -y
./configure && make
sudo make install  

which start-stop-daemon # 查看start-stop-daemon位置

启动选项

monit可以通过加载monitrc文件里的配置信息运行,也可以直接通过命令行参数运行

[-c] monitrc文件目录

[-d] n 每多少秒检查一次;等于在monitrc文件中加set daemon

[-g] name 对某个分组进行统一操作

[-i] file 设置日志输出文件;等于在monitrc文件中加set log

[-p] pidfile 在守护进程模式下使用此锁文件;等于在monitrc文件中加set pidfile

[-s] statefile monit状态信息文件;等于在monitrc文件中加set statefile

[-B] 批量命令行指令;等于在monitrc文件中加set terminal batch

[-I] 禁用后台运行模式;等于在monitrc文件中加set init

[-t]monitrc文件做语法检查

monit控制文件

monit通过写控制文件设置监控什么服务?如何监控?等内容,其中监控的对象包括进程、文件、磁盘、目录、远程主机、系统、网络等九种类型,本文我们的重点是对进程的监控。

控制文件格式

监控进程的控制文件一定要有的一行命令是这样的:

CHECK PROCESS <unique name> <PIDFILE <path> | MATCHING <regex>>

path是进程pidfile的绝对路径,如果pidfile不存在,或者pidfile内不包含process id,monit会执行控制文件的START语句。

regex是使用PID文件的替代方案,可以使用进程名模式匹配来查找要监视的进程。

示例

下面是一个简单的控制文件quote_monitor.monitrc,它命名了一个服务名quote_monitor,以及该服务的pidfile路径

CHECK PROCESS quote_monitor PIDFILE /data/monit_daemon/pidfile.d/quote_monitor.pid
    START = "/data/monit_daemon/bin/monit_start_daemon.sh /home/quote_monitor/quote_monitor"
	STOP = "/data/monit_daemon/bin/monit_stop_daemon.sh"
	GROUP svc
	GROUP svc.quote_monitor
# 若进程不存在, `告警`并`重启`
	IF NOT EXIST THEN EXEC "/data/monit_daemon/bin/monit_wechat_notify.sh" ELSE IF SUCCEEDED THEN EXEC "/data/monit_daemon/bin/monit_wechat_notify.sh"
	IF NOT EXIST THEN RESTART
# 连续5次都重启失败, `告警`
#	IF 5 RESTART 5 CYCLES THEN EXEC "/data/monit_daemon/bin/monit_alert_to_dingtalk.sh"

第一行是标准格式CHECK PROCESS段,下面定义了一些动作。

START 当monit检查不到该进程的pid时会执行

STOP当执行monit stop或者monit stop all时会执行

GROUP指定当前进程的分组,monit [option] -g [group name]

在下面是一个简单的IF exp THEN statment逻辑判断,指定服务异常停止后的动作。

其他脚本

monitrc配置文件
# 每10秒检测一次
set daemon 10

# 日志
set log /var/log/monit.log

# pid文件
set pidfile /var/run/monit.pid

# state数据文件
# set statefile ~/.monit.state

# MODE:
# ACTIVE    (默认) // 主动监控 (挂了后重启恢复)
# PASSIVE         // 被动监控 (挂了不重启)
#
# 为了避免每次reload带来批量重启进程的影响
# 在发布过程中, 更新完monit目录的代码后
# 手工将PASSIVE模式打开, 然后再做reload (这样的话短暂时间内monit只是会触发告警但是并不会重启程序)
#
#MODE PASSIVE

# ONREBOOT:
# START     (默认) // monit重启后监控项也重启
# NOSTART         // monit重启后监控项不重启
# LASTSTATE       // monit重启后进程的启动状态同monit重启前一致
SET ONREBOOT LASTSTATE

set httpd port 2812
     allow localhost

set eventqueue basedir /var/monit slots 1000

#包含所有子配置项
include /data/monit_daemon/enabled__conf.d/*.monitrc
include /data/monit_daemon/enabled__conf.d/*/*.monitrc
admin.sh
#!/bin/bash

_CUR_DIR=$(cd $(dirname "${BASH_SOURCE[0]}" ) >/dev/null && pwd )

# 保证是root用户在执行
user_name=$(id -un) #whoami
if [ "$user_name" != "root"  -a  "$1" != "force_stop"  -a  "$1" != "status"  -a  "$1" != "ps" ] ; then #如果是force_stop/status/ps, 则不一定是root用户
  echo "Error: You should use root user!"
  exit 100
fi

_RC_FILE=/root/.monitrc
_PIDFILE=/var/run/monit.pid

# 修正配置文件的权限, 保证 _RC_FILE 有效
chown root. ${_CUR_DIR}/monitrc
chmod 600 ${_CUR_DIR}/monitrc
ln -sf ${_CUR_DIR}/monitrc ${_RC_FILE}

# 保证 pidfile.d/ 目录有效
mkdir -m 1777  -p /data/monit_daemon/pidfile.d/
chmod 1777 /data/monit_daemon/pidfile.d/

#操作start,stop
case "$1" in
	start)
		monit -c ${_RC_FILE}
		;;
	reload)
		monit reload
		;;
	status)
		ps -ef | grep -v -w grep | grep -w monit || echo 'monit not found!!!'
		lsof -i -Pn -Tqs -a -c monit | grep -E 'LISTEN|$'
		netstat -tlpnee | grep -F ":2812"   || echo 'listen 2812 not found!!!'
		echo
		monit summary
		;;
	stop)
		start-stop-daemon -v --oknodo --pidfile ${_PIDFILE} --stop
		;;
	force_stop)
		start-stop-daemon -v --oknodo --pidfile ${_PIDFILE} --retry 'TERM/5/KILL/3' --stop
		;;
	restart)
		start-stop-daemon -v --oknodo --pidfile ${_PIDFILE} --stop   && sleep 2
		monit -c ${_RC_FILE}
		;;
	*)
	echo $"Usage: $0 {start|reload|status|stop|force_stop|restart} "
	exit 2
esac

上面是monit服务的启停脚本,注意脚本中加载*.monitrc文件的目录。

monit_start_daemon.sh
#!/bin/bash

_CUR_DIR=$(cd $(dirname "${BASH_SOURCE[0]}" ) >/dev/null && pwd )
source ${_CUR_DIR}/../export_dot_env.sh

if [ -z "${MONIT_SERVICE}" ] ; then
	echo "MONIT_SERVICE empty!"
	exit 99
fi

# MONIT_SERVICE=<unique_name> monit_start_daemon.sh <executable> ...arguments
_UNIQUE_NAME=${MONIT_SERVICE}
_STARTAS=$1
shift 1

_PIDFILE=/data/monit_daemon/pidfile.d/${_UNIQUE_NAME}.pid

_LOG_DIR=/data/logs/_console_/${_UNIQUE_NAME}/$(/bin/date '+%Y%m%d_') #%H%M%S
mkdir -m 775 -p -v ${_LOG_DIR}   || exit 106 #664权限保证同一group的用户可以写

# 允许生成任意大小的coredump文件
ulimit -c unlimited

# 启动进程
/usr/local/bin/start-stop-daemon -v --oknodo --pidfile ${_PIDFILE} --chdir ${PWD:-/} --background --no-close --make-pidfile --startas ${_STARTAS} --start -- "$@" >> ${_LOG_DIR}/stdout.log     2>> ${_LOG_DIR}/stderr.log
exit $?
monit_stop_daemon.sh
#!/bin/bash

_CUR_DIR=$(cd $(dirname "${BASH_SOURCE[0]}" ) >/dev/null && pwd )
source ${_CUR_DIR}/../export_dot_env.sh

if [ -z "${MONIT_SERVICE}" ] ; then
	echo "MONIT_SERVICE empty!"
	exit 99
fi

# MONIT_SERVICE=<unique_name> monit_stop_daemon.sh
_UNIQUE_NAME=${MONIT_SERVICE}

_PIDFILE=/data/monit_daemon/pidfile.d/${_UNIQUE_NAME}.pid

/usr/local/bin/start-stop-daemon -v --oknodo --pidfile ${_PIDFILE} --remove-pidfile --stop
exit $?

有上面三个脚本以后,就可以启动一个服务了。至于monit_wechat_notify.shmonit_alert_to_dingtalk.sh这两个脚本就不贴了,可以替换成自己用的告警脚本。

目录结构

所有的监控服务的文件都放在了/data/monit_deamon目录下,下面是该目录的结构

├── admin.sh

├── bin

│ ├── monit_start_daemon.sh

│ ├── monit_stop_daemon.sh

│ └── monit_wechat_notify.sh

├── conf.d

│ └── quote_monitor.monitrc

├── enabled__conf.d

│ ├── ctp_collector.monitrc

│ └── quote_monitor.monitrc

├── monitrc

├── pidfile.d

│ ├── ctp_collector.pid

│ └── quote_monitor.pid

├── test.py

操作参数

monit服务启动以后,daemon进程会在本地开启一个TCP服务,默认监听2812端口(可自定义配置)。可以通过monit命令或者web服务来管理监控服务。

  • start all

    启动控制文件中列出的所有服务,并启用对它们的监视。

  • start [name]

    启动指定服务,并启用对它的监视。

  • stop all

    停止所有服务

  • stop [name]

    停止指定服务

  • restart all

    重启所有服务

  • restart [name]

    重启指定服务

  • unmonitor all

    取消对所有服务器的监控,取消以后进程异常终止也不会触发指定事件。

  • unmonitor [name]

    取消对指定服务的监控

  • status [name]

    查看指定服务的运行状态,如果不加参数,则查看所有服务的信息,包括一些进程的基本信息、运行时间等

  • summary [name]

    查看运行信息摘要,如果不加参数则查看所有服务的信息。

  • report [up down initialising unmonitored total]

报告服务状态。如果没有选项,则输出Monit管理的所有服务状态的简短概述。选项up打印处于此状态的所有服务的数量,down同样打印,依此类推。

  • reload

    重新加载monitrc文件,重启deamon进程。

  • quit

    结束deamon进程

  • validate

    检查控制文件中列出的所有服务。这个动作也是Monit在守护进程模式下运行时的默认行为。

  • procmatch [regex]

    允许对进程匹配检查的模式进行简单的测试。该命令接受正则表达式作为参数,并显示与模式匹配的所有运行进程。