背景
平时单独检查目标主机端口是否打开,可能会用如下两种方式验证:
方式一,直接使用 telnet
命令,但如果端口连通后会让窗口挂起,无法自行退出
telnet www.baidu.com 80
# >>> 终端输出
Trying 14.215.177.38...
Connected to www.a.shifen.com.
Escape character is '^]'.
^] # 需要自行执行 Command+] 进行关闭
telnet> quit # 并输入 quit 退出连接
Connection closed.
方式二,使用管道 + telnet
命令,即可实现单行执行
echo "" | telnet www.baidu.com 80
# >>> 终端输出
Trying 14.215.177.38...
Connected to www.baidu.com.
Escape character is '^]'.
Connection closed by foreign host.
但一般在 Shell 脚本中往往只需要获取其最终的状态即可,无需观察其连接过程;
所以本次我们将用多种命令分别来实现端口通断的检测,可用于单行检测与脚本检测。
最佳实践
单行检测
telnet命令单行执行
shell中需要在下一行使用
echo $?
获取上一行执行结果状态
echo "" | telnet www.baidu.com 80
nc命令单行执行与带结果输出
# 单纯执行,成功状态码0,失败状态码1
nc -z -w 5 www.baidu.com 80; echo $?
# 带结果输出
nc -z -w 5 www.baidu.com 80 && echo OK || echo Failed
bash命令单行执行与带结果输出
bash自身包含的一种方式:
/dev/tcp/host/port
和/dev/udp/host/port
# 单纯执行,成功状态码0,失败状态码1,超时状态码124
timeout 5 bash -c "echo >/dev/tcp/www.baidu.com/180" > /dev/null 2>&1 ; echo $?
# 带结果输出
# 注意: MACOS 下没有 timeout 命令
timeout 5 bash -c "echo >/dev/tcp/www.baidu.com/80" > /dev/null 2>&1 && echo "port 80 is open" || echo "port 80 is closed"
在这里,timeout
会运行其后的子命令,若在指定的超时时间还未完成的话, timeout
会 kill 掉子命令对应的进程。在这种情况下,bash
就是一个子命令,用 /dev/tcp
的特殊方式尝试与目标主机的指定端口建连。
如果 bash
可以指定的超时时间内与目标主机端口建连,cat
会立即终止 ( 由于其是从 /dev/null
中读取内容 ) ,bash
命令接着也会执行完毕,最终返回一个 0 状态码。
若在超时时间范围内与目标主机端口建连失败,bash
会退出并与 timeout
一起返回一个 1 状态码。
若过了超时时间后 bash
还是无法成功建连,timeout
就会 kill
掉 bash
并返回一个 124 状态码。
脚本检测
根据执行状态码判断
利用 nc
、/dev/tcp
、nmap
三种方式的执行状态码判断端口通断。
#!/bin/bash
SERVER=www.baidu.com
PORT=80
# 方式一
nc -w 3 -z $SERVER $PORT
# 方式二
# </dev/tcp/$SERVER/$PORT
# 方法三,需要安装nmap,yum install -y nmap
# nmap -p $PORT $SERVER
if [ "$?" -ne 0 ]; then
echo "Connection to $SERVER on port $PORT failed"
exit 1
else
echo "Connection to $SERVER on port $PORT succeeded"
exit 0
fi
封装方法
vim port_check.sh
#!/bin/bash
function check_port {
status=`nc -w 3 -z www.baidu.com 80; echo $?`
echo $status
if [ "$status" -eq 0 ]; then
echo "Success."
else
echo "Failed."
fi
}
check_port
执行 sh port_check.sh
,输出如下:
Connection to www.baidu.com port 80 [tcp/http] succeeded!
0
Success.