如何实现base shell监控网络设备?
- By : Will
- Category : Debian-Like

1 前言
一个问题,一篇文章,一出故事。
笔者家里有一堆网络设备,如果使用Zabbix监控貌似有点大材小用,于是决定写一个监控脚本解决此问题。
2 最佳实践
2.1 设置邮件推送
2.2 设置免密码登录路由
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 STATUS ALIAS' fi mailBody="$mailBody<br> $count $flage $address $addressStatus $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
参阅文档
====================
没有评论