在shell中判断端口开启的几种方法


背景

平时单独检查目标主机端口是否打开,可能会用如下两种方式验证:

方式一,直接使用 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 就会 killbash 并返回一个 124 状态码。

脚本检测

根据执行状态码判断

利用 nc/dev/tcpnmap 三种方式的执行状态码判断端口通断。

#!/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.

Reference

linux shell 检查端口开放

shell中判断远程主机的某个tcp端口是否存活

Test if remote TCP port is open from a shell script


文章作者: NesTeaLin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 NesTeaLin !
  目录