我正在寻找一种快速而简单的方法,用于正确地测试一个给定的TCP端口是否在远程服务器上打开,从Shell脚本中。

我已经设法用telnet命令做到这一点,当端口被打开时,它工作得很好,但当它没有超时时,它似乎并没有超时,只是挂在那里……

下面是一个例子:

l_TELNET=`echo "quit" | telnet $SERVER $PORT | grep "Escape character is"`
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

我要么需要一个更好的方法,或者一种方法强制telnet超时,如果它没有在8秒内连接,例如,并返回一些我可以在Shell中捕获的东西(返回代码,或stdout中的字符串)。

我知道Perl方法,它使用IO::Socket::INET模块,并编写了一个成功的测试端口的脚本,但如果可能的话,宁愿避免使用Perl。

注意:这是我的服务器正在运行(我需要从哪里运行这个)

SunOS 5.10 Generic_139556-08 i86pc i386 i86pc


当前回答

我需要一个更灵活的解决方案来处理多个git存储库,所以我根据1和2编写了下面的sh代码。你可以用你的服务器地址代替gitlab.com,用你的端口代替22。

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中,为TCP/UDP连接使用伪设备文件非常简单。以下是剧本:

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

下面是一行代码(Bash语法):

</dev/tcp/localhost/11211 && echo Port open. || echo Port closed.

请注意,有些服务器可以通过防火墙保护免受SYN flood攻击,因此您可能会遇到TCP连接超时(~75秒)。要解决超时问题,请尝试:

timeout 1 bash -c "</dev/tcp/stackoverflow.com/81" && echo Port open. || echo Port closed.

参见:如何减少TCP connect()系统调用超时?

使用netcat,你可以像这样检查端口是否打开:

nc my.example.com 80 < /dev/null

如果TCP端口被打开,nc的返回值为success,如果不能建立TCP连接,则返回值为failure(通常为返回码1)。

当你尝试这样做时,某些版本的nc会挂起,因为它们即使在从/dev/null.接收到文件结束后也不会关闭它们的套接字的发送部分在我自己的Ubuntu笔记本电脑(18.04)上,我安装的netcat-openbsd版本的netcat提供了一个变通方案:必须使用-N选项才能立即得到结果:

nc -N my.example.com 80 < /dev/null

我需要在cron中运行的短脚本,没有输出。我用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

要运行它,你应该安装nmap,因为它不是默认安装包。

我的机器不支持nc或/dev/tcp/$hostname/$port,但支持超时,所以我回到telnet,如下所示:

if echo "quit" | timeout 2 telnet $SERVER $PORT 2>&1 | grep -q 'Connected to'; then
    echo "Connection to $SERVER on port $PORT succeeded"
    exit 0
else
    echo "Connection to $SERVER on port $PORT failed"
    exit 1
fi

Nmap-ncat用于测试尚未使用的本地端口


availabletobindon() {
  port="$1"
  nc -w 2 -i 1 localhost "$port" 2>&1 | grep -v -q 'Idle timeout expired'
  return "$?"
}