如何实现base shell监控网络设备?

Debian-Like

1 前言

一个问题,一篇文章,一出故事。
笔者家里有一堆网络设备,如果使用Zabbix监控貌似有点大材小用,于是决定写一个监控脚本解决此问题。

2 最佳实践

2.1 设置邮件推送

如何设置ubuntu s-nail推送smtp邮件?

2.2 设置免密码登录路由

如何免密码ssh登录MikroTik RouterOS?

2.3 创建监视脚本

vim ~/scripts/monitorHosts.sh

加入如下配置,

#!/bin/bash

routerAddress="192.168.0.1"
routerUser="admin"
routerKey="/home/will/.ssh/id_rsa"
monitorHosts="EZVIZ"
monitorAddress="192.168.0.1 192.168.0.250"
monitorHostAlias="/etc/monitorHostAlias.conf"
monitorHistoryLog="/var/log/monitorHistory.log"
monitorStatusLog="/var/log/monitorStatus.log"
mailFrom="will@cmdschool.org"
mailTo="tanzhenchao@qq.com"
mailHost="smtp.exmail.qq.com"
mailPort="465"
mailSubject="Host Status Alert"
mailBody=""
dataTime="$(date +'%Y-%m-%d %H:%M:%S')"

autocmd() {
	cmd="$1"
	sshInfo=$(ssh -n -o ConnectTimeout=10 -o PubkeyAcceptedAlgorithms=+ssh-rsa -i "$routerKey" "$routerUser"@"$routerAddress" "$cmd")
	echo "$sshInfo"
}

getRouterHostAddress() {
	hostname="$1"
	hostAddress=$(autocmd "/ip dhcp-server lease print where host-name~\"$hostname\"" | grep -E '^[[:space:]]*[0-9]' | awk -F' ' '{print $3}')
	echo "$hostAddress"
}

isPingReachable() {
	address=$1
	if ping -c 3 -W 1 "$address" &> /dev/null; then
		return 0
	else
		return 1
	fi
}

isRouterPingReachable() {
	address=$1
	pingSum=$(autocmd "/ping count=3 $address" | grep "packet-loss=100%" | wc -l)
	if [[ $pingSum -eq 0 ]]; then
		return 0
	else
		return 1
	fi
}

isConnectionReachable() {
	address=$1
	connectionSum=$(autocmd "/ip firewall connection print where src-address~\"$address\" and (orig-rate>0 or repl-rate>0)" | grep -E '^[[:space:]]*[0-9]' | wc -l)
	if [[ $connectionSum -gt 0 ]]; then
		return 0
	else
		return 1
	fi
}

isMacReachable() {
	address=$1
	macSum=$(autocmd "/ip arp print where address=\"$address\" and complete" | grep -E '^[[:space:]]*[0-9]' | grep -E '([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})' | wc -l)
	if [[ $macSum -gt 0 ]]; then
		return 0
	else
		return 1
	fi
}

for host in $monitorHosts; do
	for address in $(getRouterHostAddress "$host"); do
		if [ "$address" == "" ]; then
			continue
		fi
		if echo "$monitorAddress" | grep -q "$address"; then
			continue
		fi
		monitorAddress="$monitorAddress $address"
	done
done

sendMail="false"
count=0
for address in $monitorAddress; do
	if isPingReachable "$address"; then
		addressStatus="online"
	elif isRouterPingReachable "$address"; then
		addressStatus="online"
	elif isConnectionReachable "$address"; then
		addressStatus="online"
	elif isMacReachable "$address"; then
		addressStatus="online"
	else
		addressStatus="offline"
	fi

	flage="K"
	hostAlias=$(grep "$address" "$monitorHostAlias" | awk -F' ' '{print $2}')
	if [[ -z "$hostAlias" ]]; then
		hostAlias="NULL"
	fi
	lastHistoryLog=$(grep -F "$address" "$monitorHistoryLog" 2>/dev/null | tail -n 1)
	lastHistoryLogMessage=$(echo "$lastHistoryLog" | awk '{$1=$2=""; print substr($0,3)}')
	lastHistoryStatus=$(echo "$lastHistoryLogMessage" | awk -F' ' '{print $2}')
	message="$address $addressStatus"
	echo "$dataTime $message" >> "$monitorHistoryLog"
	lastStatusLog=$(grep -F "$address" "$monitorStatusLog" 2>/dev/null | tail -n 1)
	if [[ "$lastStatusLog" == "" ]]; then
		echo "$lastHistoryLog" >> "$monitorStatusLog"
	fi
	last3HistoryLog=$(grep -F "$address" "$monitorHistoryLog" 2>/dev/null | tail -n 3)
	last3HistoryMessage=$(echo "$last3HistoryLog" | awk '{$1=$2=""; print substr($0,3)}')
	if [[ $(echo "$last3HistoryMessage" | wc -l) -eq 3 ]]; then
		onlineMsg=$(echo "$last3HistoryMessage" | grep online)
		offlineMsg=$(echo "$last3HistoryMessage" | grep offline)
		if [[ $(echo "$onlineMsg" | wc -l) -gt $(echo "$offlineMsg" | wc -l) ]]; then
			countStatus="online"
		else
			countStatus="offline"
		fi
		lastStatusLog=$(grep -F "$address" "$monitorStatusLog" 2>/dev/null | tail -n 1)
		lastStatusMeg=$(echo "$lastStatusLog" | awk '{$1=$2=""; print substr($0,3)}')
		lastStatus=$(echo "$lastStatusMeg" | awk -F' ' '{print $2}')
		if [[ "$countStatus" != "$lastStatus" ]]; then
			if [[ -z "$lastHistoryLogMessage" ]]; then
				flage="A"
			else
				flage="U"
			fi
			sendMail="true"
			echo "$last3HistoryLog" | grep "$countStatus" | tail -n 1  >> "$monitorStatusLog"
		fi
	fi

	if [ $count -eq 0 ]; then
		mailBody='Flags: A - Add, U - Update, K - Keep'
		mailBody="$mailBody<br>"' # ADDRESS&emsp;STATUS&nbsp;ALIAS'
	fi
	mailBody="$mailBody<br> $count $flage $address&nbsp;$addressStatus&nbsp;$hostAlias"
	((count++))
done

if [[ "$sendMail" == "true" ]]; then
	echo "$mailBody" | s-nail -s "$mailSubject $dataTime" -r "$mailFrom" -S "mta=smtp://$mailHost:$mailPort" "$mailTo"
fi

需要注意的是,
– 函数“autocmd”用于自动登录路由并执行命令
– 函数“isPingReachable”ping检查IP地址连通性,返回0表示用户ping通即在线,返回1表示用户不能ping通即不在线。
– 函数“isRouterPingReachable”通过路由ping检查IP地址连通性,返回0表示用户ping通即在线,返回1表示用户不能ping通即不在线。
– 函数“isConnectionReachable”检查IP地址的连接数,返回0表示用户有连接且即在线,返回1表示用户无连接即不在线。
– 函数“isMacReachable”检查arp列表中的MAC地址是否活跃,返回0表示用户有连接且即在线,返回1表示用户无连接即不在线。
– 函数“getRouterHostAddress”用于登录路由并获取host-name对应的IP Address
– 循环“for host in $monitorHosts; do”逐个从变量monitorHosts取得IP地址并与变量monitorAddress中的IP地址合并。
– 循环“for address in $monitorAddress; do”逐个检查变量monitorAddress中的地址状态并创建日志和生成邮件主体。
– 命令s-nail向用户推送设备变更通知的邮件

2.4 设置设备别名

cat /etc/monitorHostAlias.conf

加入如下配置,

192.168.0.1 route
192.168.0.250 ser
192.168.0.254 EZVIZ
192.168.0.253 EZVIZ
192.168.0.252 EZVIZ
192.168.0.245 EZVIZ

2.5 测试脚本

bash ~/scripts/monitorHosts.sh

2.6 设置自动执行

crontab -e

加入如下配置,

*/3 * * * * bash ~/scripts/monitorHosts.sh

参阅文档
====================

如何MikroTik RouterOS命令查询用户在线?

没有评论

发表回复

Debian-Like
如何修改Ubuntu SSSD加域用户的头像?

1 前言 一个问题,一篇文章,一出故事。 笔者的工作电脑是一部使用SSSD加域的电脑,加域的大致过程 …

Debian-Like
如何将远程主机端口经加密隧道映射到本地主机?

1 前言 一个问题,一篇文章,一出故事。 笔者最近需要将远程的一台主机“127.0.0.1:3128 …

Debian-Like
如何安装fcitx5解决Google Chrome输入法兼容问题?

1 前言 一个问题,一篇文章,一出故事。 笔者最近发现Google Chrome与当前系统的拼音输入 …