我想就我编写的脚本遇到的这个特殊问题寻求您的建议。
它具有单模式(检查 1 个服务器)或多模式(您可以将其指向每行包含多行主机名和 IP 地址的文本文件)。
对于每组主机名和 IP 地址,
原始版本运行得非常好。但是,对于特定服务器,它会将运行 nmap 的函数的 IF 和 ELSE 条件评估为 true。
下面我提供了脚本以及 bash -x 的输出,其中 p 地址已被编辑。我已将令我困惑的输出加粗。
#!/usr/bin/env bash
Usage () {
echo -e "Usage Info"
}
while getopts ":H:S:T:f:p:PMN" opt;
do
case $opt in
H) # Host IP Address. Use this option if checking only single host.
HostAddr=$OPTARG
RunMode=1
;;
S) # Host Name. Use this option if checking only single host.
HostName=$OPTARG
;;
f) # absolute path to the text file containing list of IP Addresses. Use this option if checking multiple hosts.
HostFile=$OPTARG
RunMode=2
;;
P) # Ping the hostnames.
PingOn=1
;;
M) # Check using NMAP if specified port is open.
CheckPort=1
;;
p) # Specify port to be used by NMAP.
NPort=$OPTARG
;;
N) # Check if NRPE agent is installed and configured.
CheckNRPEOn=1
;;
?) # Error in option. Shows Usage guide.
Usage
;;
esac
done
cmd_Ping () {
PingResult=$(ping -c 4 "$HostIP" | grep 'transmitted' | awk -F ' ' '{ print $4 }')
if [[ "$PingResult" -eq 4 ]]; then
PingStatus='OK'
else
PingStatus='FAILED'
fi
PingOut=$(echo -e "Ping: $PingStatus")
}
cmd_NMAP () {
PortStatus=$(sudo nmap -Pn -p "$NPort" "$HostIP" | grep "$NPort" | awk -F ' ' '{ print $2 }')
if [[ "$PortStatus" = 'open' ]]; then
PortOut=$(echo -e "Port $NPort: OPEN")
elif [[ "$PortStatus" = 'filtered' ]]; then
PortOut=$(echo -e "Port $NPort: FILTERED")
elif [[ "$PortStatus" = 'closed' ]]; then
PortOut=$(echo -e "Port $NPort: CLOSED")
else
PortOut=$(echo -e "Port $NPort: ERROR")
fi
}
cmd_TNET () {
PortStatus=$(echo -e '\x1dclose\x0d' | timeout 5 sudo telnet "$HostIP" "$NPort" | grep Connected | awk -F' ' '{ print $1}')
if [[ "$PortStatus" = 'Connected' ]]; then
PortOut=$(echo -e "Port $NPort: OPEN")
else
PortOut=$(echo -e "Port $NPort: FAILED")
fi
}
cmd_NRPE () {
NRPEtmp=$(sudo /usr/local/nagios/libexec/check_nrpe -H "$HostIP")
NRPEnix=$(echo "$NRPEtmp" | awk -F ' ' '{ print $1 }')
NRPEwin=$(echo "$NRPEtmp" | cut -d ' ' -f4-)
if [[ "$NRPEnix" = 'NRPE' ]] || [[ "$NRPEwin" = 'seem to be doing fine...' ]]; then
NRPEOut=$(echo -e "NRPE: Configured")
else
NRPEOut=$(echo -e "NPRE: Not Configured")
fi
}
mode_Multi () { # Multiple IP Address Mode
while read -r HostInfo;
do
HostName=$(echo "$HostInfo" | awk -F ' ' '{ print $1 }')
HostIP=$(echo "$HostInfo" | awk -F ' ' '{ print $2 }')
if [[ $PingOn -eq 1 ]]; then
cmd_Ping
else # ($PingOn -ne 1 )
PingOut='N/A'
fi
if [[ "$CheckPort" -eq 1 ]]; then
cmd_NMAP
else # ($CheckPort -ne 1)
PortOut='N/A'
fi
if [[ "$CheckNRPEOn" -eq 1 ]]; then
cmd_NRPE
NRPEOut='N/A'
fi
echo -e " $HostName, $HostIP, $PingOut, $PortOut, $NRPEOut"
done < "$HostFile"
}
mode_Single () { # Single IP Address Mode
HostIP=$HostAddr
if [[ $PingOn -eq 1 ]]; then
cmd_Ping
else # ($PingOn -ne 1)
PingOut='N/A'
fi
if [[ "$CheckPort" -eq 1 ]]; then
cmd_NMAP
else # ($CheckPort -ne 1)
PortOut='N/A'
fi
if [[ "$CheckPort2" -eq 1 ]]; then
cmd_TNET
else
PortOut='N/A'
fi
if [[ "$CheckNRPEOn" -eq 1 ]]; then
cmd_NRPE
else
NRPEOut='N/A'
fi
echo -e "$HostName, $HostIP, $PingOut, $PortOut, $NRPEOut"
}
if [[ "$RunMode" -eq 1 ]]; then
mode_Single
else
mode_Multi
fi
这是单模式的输出:
我会像这样运行这个脚本:
./HostChecker.sh -S <HostName> -H <HostIP> -PMN -p <port number>
+ getopts :H:S:T:f:p:PMN opt
+ case $opt in
+ HostAddr=10.119.4.106
+ RunMode=1
+ getopts :H:S:T:f:p:PMN opt
+ case $opt in
+ PingOn=1
+ getopts :H:S:T:f:p:PMN opt
+ case $opt in
+ CheckNRPEOn=1
+ getopts :H:S:T:f:p:PMN opt
+ case $opt in
+ CheckPort=1
+ getopts :H:S:T:f:p:PMN opt
+ case $opt in
+ NPort=5666
+ getopts :H:S:T:f:p:PMN opt
+ [[ 1 -eq 1 ]]
+ mode_Single
+ HostIP=10.x.x.x
+ [[ 1 -eq 1 ]]
+ cmd_Ping
++ ping -c 4 10.x.x.x
++ grep transmitted
++ awk -F ' ' '{ print $4 }'
+ PingResult=0
+ [[ 0 -eq 4 ]]
+ PingStatus=FAILED
++ echo -e 'Ping: FAILED'
+ PingOut='Ping: FAILED'
+ [[ 1 -eq 1 ]]
+ cmd_NMAP
++ sudo nmap -Pn -p 5666 10.119.4.106
++ grep 5666
++ awk -F ' ' '{ print $2 }'
+ PortStatus=filtered
+ [[ filtered = \o\p\e\n ]]
+ [[ filtered = \f\i\l\t\e\r\e\d ]]
++ echo -e 'Port 5666: FILTERED'
+ PortOut='Port 5666: FILTERED'
+ [[ '' -eq 1 ]]
+ PortOut=N/A
+ [[ 1 -eq 1 ]]
+ cmd_NRPE
++ sudo /usr/local/nagios/libexec/check_nrpe -H 10.x.x.x
+ NRPEtmp='CHECK_NRPE STATE CRITICAL: Socket timeout after 10 seconds.'
++ echo 'CHECK_NRPE STATE CRITICAL: Socket timeout after 10 seconds.'
++ awk -F ' ' '{ print $1 }'
+ NRPEnix=CHECK_NRPE
++ echo 'CHECK_NRPE STATE CRITICAL: Socket timeout after 10 seconds.'
++ cut -d ' ' -f4-
+ NRPEwin='Socket timeout after 10 seconds.'
+ [[ CHECK_NRPE = \N\R\P\E ]]
+ [[ Socket timeout after 10 seconds. = \s\e\e\m\ \t\o\ \b\e\ \d\o\i\n\g\ \f\i\n\e\.\.\. ]]
++ echo -e 'NPRE: Not Configured'
+ NRPEOut='NPRE: Not Configured'
+ echo -e ', 10.x.x.x , Ping: FAILED, N/A, NPRE: Not Configured'
, 10.x.x.x , Ping: FAILED, N/A, NPRE: Not Configured
如果查看 bash -x 的输出,您会注意到函数 cmd_NMAP 以某种方式将 IF 和 ELSE 的条件评估为 true。让我困惑的是那个条件“[[''-eq 1]]”我不知道它来自哪里。
我有一种感觉,这是一些简单的事情,我不知何故忽略了,但我已经花了几个小时了,但不知何故我看不到它。我什至使用 ShellCheck 检查过,它告诉我一切都很好。
非常感谢所有帮助。预先感谢您。
我怀疑你的逻辑有问题,让我们看看:
if [[ "$CheckPort" -eq 1 ]]; then
cmd_NMAP
else # ($CheckPort -ne 1)
PortOut='N/A'
fi
if [[ "$CheckPort2" -eq 1 ]]; then
cmd_TNET
else
PortOut='N/A'
fi
如果
CheckPort
是 1
,但 ChecPort2
不是 1
,会发生什么?
第一个
if
语句将执行cmd_NMAP
,这将设置PortOut
。但紧接着,下一个 if
语句将执行其 else
并破坏 PortOut
。
如果您希望所有这些情况都是排他性的,请采用另一种方式。也许你想要这个?
if [[ "$CheckPort" -eq 1 ]]; then
cmd_NMAP
elif [[ "$CheckPort2" -eq 1 ]]; then
cmd_TNET
else
PortOut='N/A'
fi
仅当所有
CheckPort*
变量都不为 true 时,我们才会将 PortOut
设置为 N/A
。