我正在尝试自动telnet,使用这个命令可以很好地进行
echo -e "x1dclosex0d" |
telnet abc.gc.ca 100 |
grep Connected>/dev/null && printf "PASSEDn" || printf "FAILEDn"
但如果我把它放在剧本里,它就会挂起来,我不知道为什么。
#!/bin/bash
SERVERS=(
"abc.gc.ca 100"
"defg.gc.ca 101"
"123.gc.ca 102"
"xyz.gc.ca 103"
)
for host in ${SERVERS[@]}; do
echo -e "x1dclosex0d" |
telnet $host |
grep Connected > /dev/null && printf "PASSEDn" || printf "FAILEDn"
done
最大的问题是数组取消引用:使用不带引号的${SERVERS[@]}
将端口视为单独的主机名。
#!/bin/bash
servers=(
abc.gc.ca:100
defg.gc.ca:101
123.gc.ca:102
xyz.gc.ca:103
)
for host_port in "${servers[@]}"; do
host=${host_port%:*} # put everything before the last : into host
port=${host_port##*:} # put everything after the last : into port
if printf 'x1dclosex0d' | telnet "$host" "$port" | grep -q Connected; then
printf "PASSEDn"
else
printf "FAILEDn"
fi
done
其他注意事项:
- 所有caps变量名称都用于对shell或操作系统有意义的名称;其他名称是保留给应用程序使用的(比如您的脚本!(,所以您应该尽可能使用小写名称
- CCD_ 2与CCD_ 3不相同。对于可靠的代码,当您想要
if
的行为时,请使用if
,而不是短路三进制 - 使用
grep -q
会导致grep
不发出任何输出,因此不需要重定向该输出 echo -e
是不可靠的:即使shell 100%肯定是bash,如果在运行时编译或配置shell以提供与XPG兼容的echo
(可以通过环境变量进行配置(,echo -e
也可能在输出中打印-e
,而不是将其视为参数
尽管如此,如果要用于任何类型的真实世界用例,请考虑使用专用端口扫描工具。这样的工具(nmap&c(可以并行扫描大量主机,而不需要为每个主机运行一个子流程,更不用说这里使用的几个子流程了。
您可以尝试使用"/dev/tcp"文件。
SERVERS=(
"abc.gc.ca/100"
"defg.gc.ca/101"
"123.gc.ca/102"
"xyz.gc.ca/103"
)
for host in ${SERVERS[@]}; do
timeout 3 bash -c "cat < /dev/null > /dev/tcp/$host" &&
echo "PASSED" || echo "FAILED"
done