基于SHELL脚本批量PING工具

背景:本人就职于业务导向型的传统企业,技术部门虽有划分开发部和运行部,但运维实力仍属于基础运维。平时工作除了解决用户报障、监控服务可用性、监控服务器性能指标外,偶尔帮公司写写运维脚本,提高运维效率。

今早领导脑子一拍,说要对公司提供的互联网IP进行可用性监控,我想互联网IP可用性确实是得监控起来,一激灵写出代码如下,供大家参考。脚本巡检160个IP耗时8s。

先进行需求分析:

  • 从列表内获取IP,抽象出获取IP方法,后续修改为从CMDB获取IP序列;
  • 可调节ping IP的成功率阈值,减少误报;
  • 调节PING的频率及包数;
  • 使用ping命令同时ping多个IP,返回每个IP ping成功率;
  • 可调节巡检窗口大小,例如执行任务3次都失败才进行告警,减少误报;
  • 输出统计结果,输出巡检成功个数,巡检失败个数。

环境准备:

  • 一台可以连互联网的linux服务器
  • 一组发布在公网的IP
  • 一个爱动脑筋的领导
  • 一位踏实肯干的码农

原理图和输出结果: 

 

流程图:

代码部分:

0、定义日志输出Log(),将需要输入到变量$buffer的字符都使用Log()函数来输入。

  • 代码简洁,减少重复。
  • 便于后续修改日志格式。
  • 缺点:要使用echo -e $buffer 才能看到变量内容
#定义Log()函数,将单次PING巡检的日志存放到$buffer中,使用\t保持每次输入数据格式一致
使用echo -e输出$buffer内日志
Log() {
buffer="$buffer\t$1"
}

#存取日志方式如下:
Log(this is log 1)
Log(this is log 2)
echo -e $buffer
> this is log 1    this is log 2 

初始化变量 

PackNum=1 #共100个包
interval=1 #几秒发1个包 默认1秒1个 1秒1次 1/1=1
alarmThreshold=100 #告警阈值,大于等于50为巡检成功

echo "Starting Pinging Script with >=$alarmThreshold% sucRate to success, Each IP Pinging in $PackNum package(s) in `awk 'BEGIN{printf("%.1f",'$PackNum' * '$interval')}'` s."
filepath=/home/test/ping_test/list.txt
echo "reading pathfile at $filepath"

1、定义输入IP函数readip(),从文件读取IP列表,定义读取读取IP函数。

  • 便于修改输入源
  • 便于调试代码 自定义输入
  • 后续巡检每个过程均会记录日志,便于确保脚本运行。
#定义读取IP函数 readip()
filepath=/home/test/ping_test/list.txt
echo "reading pathfile at $filepath"
cat $filepath
> 14.215.177.39
> 14.215.177.40
> 14.215.177.41
> 2001:df0:1003::f

readip(){
if [[ -f $filepath ]] ; then
    cat $filepath | sort -n | uniq 
    return 0
else
    echo "Pinging Test Failed. Not match IP_list." 
    exit 1
fi

#可以使用以下方式获取IP
cat /tmp/ping_test/list.txt | sort -n | uniq    
echo "qwerqwer"  #干扰项
echo "127.0.0.1" #本机IP
echo "::1"       #本机v6IP
}

2、定义IP合法性检查函数testv4() 和 testv6()

  • 如后续使用外部输入,会要求对输入源做校验。
#v4IP检查
testv4() {
if [[ "$1" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]; then
  Log "is ipv4."
  return 0
else
  #Log "is not ipv4."
  return 4
fi
}

#v6IP检查
testv6() {
if [[ "$1" =~ ^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$ ]]; then
  #---skip ipv6 test
  Log "is ipv6."
  return 0
else
  #Log "is not ipv6."
  return 6
fi
}

#ip合法性检查操作方式如下:
testv4(14.215.177.39)
echo -e $buffer
> 14.215.177.39   is ipv4
testv6(qwerqwer)
#> qwerqwer  is not ipv6

 3、分别定义v4和v6的ping巡检函数,并记录巡检结果。取ping成功百分比做巡检结果。

定义函数输出 printResult()函数

root@linux1-x:~$ ping -c 1 192.168.1.101 

PING 192.168.1.101 (192.168.1.101) 56(84) bytes of data.

64 bytes from 192.168.1.101: icmp_req=1 ttl=64 time=0.168 ms

--- 192.168.1.101 ping statistics ---

1 packets transmitted, 1 received, 0% packet loss, time 0ms

rtt min/avg/max/mdev = 0.168/0.168/0.168/0.000 ms  

############PING TEST
ipv4check() {
Log "Pinging..."
local ping
ping=`ping -c $PackNum -i $interval $1 2> /dev/null |grep loss |awk '{print $6}' | awk -F "%" '{print $1}' `

printResult
}

ipv6check() {
Log "Pinging..."
local ping
ping=`ping -6 -c $PackNum -i $interval $1%2 2> /dev/null |grep loss |awk '{print $6}' | awk -F "%" '{print $1}'`

printResult
}

printResult() {
local SuccessRate
SuccessRate=$[100-$ping]
Log "SuccessRate $SuccessRate%."
if [[ $SuccessRate -ge $alarmThreshold ]]; then
     WriteSuc
     return 0
else
     WriteFail
     return 3
fi
}

4、定义巡检过程dotest(),将上面定义的函数串起来。

输入IP

-->检测IP是V4-->V4 PING检测,

-->检测IP是V6-->V6 PING检测,

-->如都不是,则输出IP非法。

############TEST ROUTINE
dotest() {
## test ipv4
testv4 $ip
if [[ $? -eq 0 ]]; then
  ipv4check $ip  #test and Pinging IPv4
  if [[ $? -eq 0 ]]; then
     #echo "$ip Yes."
     Log "Yes."
     echo -e $buffer
     continue
  else
     #echo "ipv4 check finished, finish code = $?."
     #Log "IPv4_Check finished, code = $?."
     Log "No."
     echo -e $buffer
     continue
  fi
fi

## test ipv6
testv6 $ip
if [[ $? -eq 0 ]]; then
  ipv6check $ip
  if [[ $? -eq 0 ]]; then
     #echo "$ip Yes."
     Log "Yes."
     echo -e $buffer
     continue
  else
     #echo "ipv6_check finished, finish code = $?."
     #Log "IPv6_Check finished, code = $?."
     Log "No."
     echo -e $buffer
     continue
  fi
fi
#sleep 1
#echo "$ip is not a vaildate ip."
Log " is not a vaildate ip."
WriteFail
echo -e $buffer  #按行输出
continue
}

5、定义主函数,主函数使用readip()输入需要巡检的IP,使用dotest执行巡检任务。

经检验使用次方法可以串行执行巡检任务。

#定义主函数,使用readip()获取并输入IP,
for ip in `readip`
do
  buffer=""
  buffer="$ip"
  dotest #& #<---调用巡检任务
  #sleep 0.01
#echo -e $buffer
done

5.1修改巡检任务执行方法,增加&,使巡检任务放在后台执行,异步执行多个巡检任务。

  dotest & #<---调用巡检任务
  sleep 0.01

5.2加上&异步执行任务后,发现多个子进程共用变量,如都输出到同一变量会导致格式串行。

如要分别输出巡检结果,需要对使用的变量落盘处理,对代码进行以下处理。


sucNum=/dev/shm/PT_sucNum
failNum=/dev/shm/PT_failNum
failIP=/dev/shm/PT_failIP

WriteSuc() {
echo $(($(<$sucNum) +1 )) > $sucNum
}

WriteFail() {
echo $(($(<$failNum) +1 )) > $failNum
echo -e "$ip" >> $failIP
}

并输出巡检结果

####output  --> cannot use WriteLog in a  function
echo -e "Pinging Test Finish. SuccessTest:$(<$sucNum) FailedTest:$(<$failNum)."

思考:

  1. 当前数据原为静态资产清单,后续等cmdb就绪可以使用调接口的方式获取实时IP数据。
  2. 告警容错度太差,巡检失败即产生告警;理想的巡检应可以增加容错考虑。例如:执行三次巡检任务,均失败才告警。 --->更新线 :该问题已得到解决,将在另外一篇文章进行讲解:跳转入口:CSDN
  3. 可以添加告警恢复机制。
  4. 巡检机器存在单点故障的问题,可以在多台服务器上配置巡检脚本。
  5. 现在监控工具越来越多,但没能集中管理、集中展示,后续是否有考虑使用统一的监控工具?

现在配置策略如下:

公网IP PING巡检                      应用组 互联网出口IP           161个      每5分钟执行1次 PING 3次

巡检结果输出如下:

Starting Pinging Script with >=100% sucRate to success, Each IP Pinging in 1 package(s) in 1.0 s.
reading pathfile at /home/test/ping_test/list.txt
a.b.c.d                            is ipv4.    Pinging...    SuccessRate 100%.    Yes.
aa.bb.cc.dd                    is ipv4.    Pinging...    SuccessRate 100%.    Yes.

...
aaa:bbb:ccc:ddd::eee    is ipv6.    Pinging...    SuccessRate 100%.    Yes.
aaaa:bbbb:cccc:dddd::eeee    is ipv6.    Pinging...    SuccessRate 100%.    Yes.
Pinging Test Finish. SuccessTest:161 FailedTest:0.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只晨兴夜不得寐的运维人

你的打赏,是我今晚餐桌上的鸡腿

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值