原文:http://stackoverflow.com/questions/4922943/test-from-shell-script-if-remote-tcp-port-is-open
法一:使用nc
nc -z <host> <port>
使用nc -z +IP或域名+端口检查目标主机端口是否开启,返回0则表示开启,返回1则表示未开启。
当然,为了更快的检测目标端口的状态,可以使用-w参数指定超时时间。(下方示例设置的超时时间为5秒)
nc -z -v -w5 <host> <port> $ nc -v -z -w 5 stackoverflow.com 80; echo $? Connection to stackoverflow.com 80 port [tcp/http] succeeded! 0 $ nc -v -z -w 5 stackoverflow.com 81; echo $? nc: connect to stackoverflow.com port 81 (tcp) timed out: Operation now in progress 1 ------------------------------------------ SERVER=gitlab.com PORT=22 `nc -z -v -w5 $SERVER $PORT` result1=$? #Do whatever you want if [ "$result1" != 0 ]; then echo 'port 22 is closed' else echo 'port 22 is open' fi ------------------------------------------
法二:使用bash
以下需要使用到timeout命令,对于CentOS5.x,安装方法见下: wget ftp://ftp.pbone.net/mirror/ftp5.gwdg.de/pub/opensuse/repositories/home:/crt0solutions:/extras/CentOS_CentOS-5/x86_64/timeout-8.4-20.3.crt0.x86_64.rpm #curl ftp://ftp.pbone.net/mirror/ftp5.gwdg.de/pub/opensuse/repositories/home:/crt0solutions:/extras/CentOS_CentOS-5/x86_64/timeout-8.4-20.3.crt0.x86_64.rpm -vO rpm -ivh timeout-8.4-20.3.crt0.x86_64.rpm # Connection successful: $ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/google.com/80' $ echo $? 0 # Connection failure prior to the timeout $ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/sfsfdfdff.com/80' bash: sfsfdfdff.com: Name or service not known bash: /dev/tcp/sfsfdfdff.com/80: Invalid argument $ echo $? 1 # Connection not established by the timeout $ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/google.com/81' $ echo $? 124
在这里,timeout会运行其后的子命令,若在指定的超时时间还未完成的话,timeout会kill掉子命令对应的进程。在这种情况下,bash就是一个子命令,用"/dev/tcp"的特殊方式尝试与目标主机的指定端口建连。
如果bash可以指定的超时时间内与目标主机端口建连,cat会立即终止(由于其是从/dev/null中读取内容),bash命令接着也会执行完毕,最终返回一个0状态码。
若在超时时间范围内与目标主机端口建连失败,bash会退出并与timeout一起返回一个1的状态码
若过了超时时间后bash还是无法成功建连,timeout就会kill掉bash并返回一个124的状态码
法三:使用pseudo-device file(</dev/tcp/$SERVER/$PORT)
#!/usr/bin/env bash SERVER=example.com PORT=80 </dev/tcp/$SERVER/$PORT 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
测试:
$ ./test.sh Connection to example.com on port 80 succeeded
融合为一行(判断本机11211端口是否存活)
</dev/tcp/localhost/11211 && echo Port open. || echo Port closed.
法四:使用perl(未测试,暂时无法保证可用性)
perl -MIO::Socket::INET -e 'exit(! defined( IO::Socket::INET->new("172.17.42.1:3142")))'
法五:使用nmap
前提是保证你的机器安装有nmap
open=`nmap -p $PORT $SERVER | grep "$PORT" | grep open` if [ -z "$open" ]; then echo "Connection to $SERVER on port $PORT failed" exit 1 else echo "Connection to $SERVER on port $PORT succeeded" exit 0 fi
法六:使用telnet
其在mac与linux系统中都可以较好地工作。
使用方法:
$ is_port_open.sh 80 google.com OPEN $ is_port_open.sh 8080 google.com CLOSED
脚本内容:
PORT=$1 HOST=$2 TIMEOUT_IN_SEC=${3:-1} VALUE_IF_OPEN=${4:-"OPEN"} VALUE_IF_CLOSED=${5:-"CLOSED"} function eztern() { if [ "$1" == "$2" ] then echo $3 else echo $4 fi } # cross platform timeout util to support mac mostly # https://gist.github.com/jaytaylor/6527607 function eztimeout() { perl -e 'alarm shift; exec @ARGV' "$@"; } function testPort() { OPTS="" # find out if port is open using telnet # by saving telnet output to temporary file # and looking for "Escape character" response # from telnet FILENAME="/tmp/__port_check_$(uuidgen)" RESULT=$(eztimeout $TIMEOUT_IN_SEC telnet $HOST $PORT &> $FILENAME; cat $FILENAME | tail -n1) rm -f $FILENAME; SUCCESS=$(eztern "$RESULT" "Escape character is '^]'." "$VALUE_IF_OPEN" "$VALUE_IF_CLOSED") echo "$SUCCESS" } testPort
使用timeout重新改写脚本(安装方法见法二,用法同上)
#!/bin/bash PORT=$1 HOST=$2 TIMEOUT_IN_SEC=${3:-1} VALUE_IF_OPEN=${4:-"OPEN"} VALUE_IF_CLOSED=${5:-"CLOSED"} function eztern() { if [[ $1 = "$2" ]] then echo $3 else echo $4 fi } function eztimeout() { perl -e 'alarm shift; exec @ARGV' "$@"; } function testPort() { # find out if port is open using telnet # by saving telnet output to temporary file # and looking for "Escape character" response # from telnet FILENAME="/tmp/__port_check_$(uuidgen)" RESULT=$(timeout $TIMEOUT_IN_SEC telnet $HOST $PORT &> $FILENAME; cat $FILENAME | tail -n1|awk '{print $1$2}') rm -f $FILENAME; SUCCESS=$(eztern "$RESULT" "Escapecharacter" "$VALUE_IF_OPEN" "$VALUE_IF_CLOSED") echo "$SUCCESS" } testPort
法七:使用wget(译者注:经测试该方法并不可行)
当诸如curl、telnet、nv、nmap这些工具都无法使用时,你可以使用wget来判断端口状态。
if [[ $(wget -q -t 1 --spider --dns-timeout 3 --connect-timeout 10 host:port; echo $?) -eq 0 ]]; then echo "OK"; else echo "FAIL"; fi
转载于:https://blog.51cto.com/xoyabc/1836353