1.创建目录"Services-monitor",并在该目录中创建目录"FileFromRemoteServices"、文件"main.sh"、文件"downloadFileFromRemoteServices.sh"、文件"sshAndPortTest.sh"、文件"ServicesList.txt"、文件"crontabStart.sh"、文件"crontabQuery.sh"、文件"crontabStop.sh"、文件"userStart.sh"。
2."main.sh"文件内容如下:
#!/bin/bash
#脚本每次运行时,清空ProgramResult.txt文件和ServicesError.txt文件的内容
cat /dev/null > /LinuxScript/Services-monitor/ProgramResult.txt
cat /dev/null > /LinuxScript/Services-monitor/ServicesError.txt
startTime=`date`
echo"" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "脚本开始运行,运行时间:$startTime" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo"" >> /LinuxScript/Services-monitor/ProgramResult.txt
#servicesList_line变量用于存储read命令从文件(servicesList.txt)中读取出的数据(read命令逐行读取数据)
while read servicesList_line
do
#for语句以"空格"为分隔符,逐个读取行中的参数。
#ip_or_port变量用于存储IP地址或端口号
for ip_or_port in $servicesList_line
then
#如果读取到的是IP地址,赋给变量"ip"。
ip=$ip_or_port
#通过PING命令测试目标主机网络连通性,并通过黑洞文件处理命令返回信息。
echo "正在测试主机与服务器$ip的连通性..." >> /LinuxScript/Services-monitor/ProgramResult.txt
ping -c 2 $ip > /dev/null
then
echo "服务器$ip网络正常。" >> /LinuxScript/Services-monitor/ProgramResult.txt
else
fi
elif [[ $ip_or_port =~ ^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$ ]]
then
#如果读取到的是端口号,赋给数组"port"。
let portNum++
port[$portNum]=$ip_or_port
else
cat /dev/null > /LinuxScript/Services-monitor/ProgramResult.txt
echo "ServicesList.txt文件中存在错误的IP地址或端口号,错误参数为\"$ip_or_port\"。" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "错误,程序已退出" >> /LinuxScript/Services-monitor/ProgramResult.txt
exit
fi
done
echo "正在测试服务器$ip的端口连通性..." >> /LinuxScript/Services-monitor/ProgramResult.txt
#调用sshAndPortTest脚本,登录目标服务器检测服务器端口状态,并生成状态文件(于目标服务器)。该脚本执行时间:4s-7s。
expect /LinuxScript/Services-monitor/sshAndPortTest.sh $ip ${port[*]}
#调用downloadFileFromRemoteServices脚本,将目标服务器生成的状态文件下载到本地,本地存储路径为"/LinuxScript/Services-monitor/FileFromRemoteServices"。
expect /LinuxScript/Services-monitor/downloadFileFromRemoteServices.sh $ip
if [ -e /LinuxScript/Services-monitor/FileFromRemoteServices/PortStatuBuffer.txt ] #判断PortStatuBuffer文件是否存在
#如果PortStatuBuffer文件存在,将"port"数组中的端口号与文件中的内容进行匹配。
then
for portCheck in ${port[*]}
do
cat /LinuxScript/Services-monitor/FileFromRemoteServices/PortStatuBuffer.txt | awk '{print $4}' | grep -w "0\.0\.0\.0\:$portCheck$\|$ip\:$portCheck$\|\:\:\:$portCheck$" >> /dev/null
if [ $? -eq 0 ]
then
echo "服务器$ip端口$portCheck正常。" >> /LinuxScript/Services-monitor/ProgramResult.txt
else
echo "服务器$ip端口$portCheck异常。异常原因:$portCheck端口未开放或端口意外关闭。" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "服务器$ip端口$portCheck异常。异常原因:$portCheck端口未开放或端口意外关闭,未在该服务器生成的PortStatuBuffer文件中检测到端口$portCheck" >> /LinuxScript/Services-monitor/ServicesError.txt
fi
done
else
echo "服务器$ip端口检测异常。异常原因:服务器$ip网络异常或密码错误,也可能是该服务器不存在。" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "服务器$ip端口检测异常。异常原因:服务器$ip网络异常或密码错误,也可能是该服务器不存在。无法下载该服务器生成的PortStatuBuffer文件。" >> /LinuxScript/Services-monitor/ServicesError.txt
fi
#删除port数组,避免数组中残留的数据影响下一次循环的结果。
unset port
#删除本次服务器检测生成的状态文件,避免对下一次检测产生影响。
rm -f /LinuxScript/Services-monitor/FileFromRemoteServices/PortStatuBuffer.txt
done < /LinuxScript/Services-monitor/ServicesList.txt
endTime=`date`
echo "脚本结束运行,结束时间:$endTime" >> /LinuxScript/Services-monitor/ProgramResult.txt
#判断ServicesError文件是否为空。如果ServicesError文件为空,说明指定的远端主机均具备连通性,远端主机指定的端口也均已开放,在屏幕上输出指定信息;如果ServicesError文件不为空,说明存在远端主机不具备连通性或远端主机指定端口未开放/意外关闭的情况,在屏幕输出文件中的信息。
if [ -s /LinuxScript/Services-monitor/ServicesError.txt ]
then
cat /dev/null > /LinuxScript/Services-monitor/ProgramResult.txt
echo"" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "脚本开始时间:$startTime" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "脚本结束时间:$endTime" >> /LinuxScript/Services-monitor/ProgramResult.txt
cat /LinuxScript/Services-monitor/ServicesError.txt >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "按ctrl+c退出" >> /LinuxScript/Services-monitor/ProgramResult.txt
else
cat /dev/null > /LinuxScript/Services-monitor/ProgramResult.txt
echo"" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "脚本开始时间:$startTime" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "脚本结束时间:$endTime" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "所有服务器、服务器端口正常" >> /LinuxScript/Services-monitor/ProgramResult.txt
echo "按ctrl+c退出" >> /LinuxScript/Services-monitor/ProgramResult.txt
fi
3."sshAndPortTest.sh"文件内容如下:
#!/bin/expect
#执行该脚本需要传入两个参数:IP地址和端口号
#定义ipAddress变量,用于接收外层脚本传递的IP地址。
set ipAddress [lindex $argv 0]
#定义ipAddress变量,用于记录外层脚本传递参数的个数。
set portNum [lindex $argc]
#定义变量i,用作循环参数
set i 1
#开启一个交互进程,用于实现ssh登录远端主机。
spawn ssh "root@$ipAddress"
#为timeout变量赋值,重新指定expect命令匹配字符串的超时时间。
#将超时时间设为4s,避免在ssh返回重验证消息前,expect命令就已经匹配超时。
set timeout 4
#匹配远端主机的ssh验证消息,并发送相应指令,从而实现ssh自动验证登录。注:如果匹配超时,不发送任何指令。
expect {
"connecting" { send "yes\r";exp_continue }
"password:" { send "密码\r";exp_continue }
"again" { send "密码\r"; }
timeout { }
}
#休眠2s,避免之后的命令在登录到远端主机前就已经被执行。
sleep 2
#在目标主机创建PortStatuBuffer.txt文件,用于临时存储netstat命令执行的结果。
send "mkdir -p /root/Services-monitor_client\r"
send "touch /root/Services-monitor_client/PortStatuBuffer.txt\r"
send "cat /dev/null > /root/Services-monitor_client/PortStatuBuffer.txt\r"
#对外层脚本传递的端口号进行端口状态的查询,并将查询结果放入PortStatuBuffer.txt文件。
while { $i < $portNum } {
send "netstat -anl | grep -w \"0\.0\.0\.0\:\*\\\|\:\:\:\*\" | grep -w \"0\.0\.0\.0\:[lindex $argv $i]\\\|$ipAddress\:[lindex $argv $i]\\\|\:\:\:[lindex $argv $i]\" >> /root/Services-monitor_client/PortStatuBuffer.tx
t\r"
incr i
}
#休眠1s,避免命令还未执行完,脚本就已经退出
sleep 1
exit
#命令解释:
#休眠2s,避免之后的命令在连接到远端主机前就已经被执行。
#sleep 2
#在远端主机执行命令。
#检测远端主机端口是否对外开放,将netstat查询到的记录写入PortStatuBuffer文件(文件目录为/Services-monitor_client/PortStatuBuffer.txt)。
#send "mkdir -p /root/Services-monitor_client\r" 注:通过"-p"参数可以实现文件夹的递归创建,且即便目标文件夹存在,也不会报错。
#send "touch /root/services-monitor_client/PortStatuBuffer.txt\r" 注:如果文件不存在,创建该文件;如果文件存在,刷新该文件的mtime,且不会清空文件中已有的内容。
4."downloadFileFromRemoteServices.sh"文件内容如下:
#!/bin/expect
#执行该脚本需要传入一个参数:IP地址
#定义ipAddress变量,用于接收外层脚本传递的IP地址。
set ipAddress [lindex $argv 0]
#开启一个交互进程,用于实现scp下载远端主机文件,并将其存放至本地文件夹/root/Services-monitor/FileFromRemoteServices。
spawn scp "$ipAddress:/root/Services-monitor_client/PortStatuBuffer.txt" "/LinuxScript/Services-monitor/FileFromRemoteServices"
#将超时时间设为4s,避免在ssh返回重验证消息前,expect命令就已经匹配超时。
set timeout 4
#匹配远端主机的ssh验证消息,并发送相应指令,从而实现scp自动验证。注:如果匹配超时,不发送任何指令。
expect {
"password:" { send "密码\r";exp_continue }
"again" { send "密码\r"; }
timeout { }
}
#休眠1s,避免文件还没下载脚本就已经退出。
sleep 1
exit
#注:
#如果远端服务器找不到对应的文件,脚本不会报错,且不会在本地主机产生文件。
#如果远端服务器连接不上(不存在或密码不正确),脚本不会报错,且不会在本地主机产生文件。
5."crontabStart.sh"文件内容如下:
#!/bin/bash
echo "0 */1 * * * /bin/bash /LinuxScript/Services-monitor/main.sh" > /var/spool/cron/root
6."crontabQuery.sh"文件内容如下:
#!/bin/bash
crontab -l
7."crontabStop.sh"文件内容如下:
#!/bin/bash
crontab -r
8."userStart.sh"文件内容如下:
#!/bin/bash
clear
tail -f ProgramResult.txt