我正在寻找一种快速而简单的方法,用于正确地测试一个给定的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


当前回答

虽然这是一个老问题,但我只是处理了它的一个变体,但这里的解决方案都不适用,所以我找到了另一个,并为子孙后代添加了它。是的,我知道OP说他们知道这个选项,它不适合他们,但对于任何跟随它的人来说,它可能是有用的。

在我的例子中,我想从docker构建中测试本地apt-cache -ng服务的可用性。这意味着在测试之前绝对不能安装任何东西。无nc、nmap、expect、telnet、python。perl然而是存在的,以及核心库,所以我使用这个:

perl -MIO::Socket::INET -e 'exit(! defined( IO::Socket::INET->new("172.17.42.1:3142")))'

其他回答

虽然这是一个老问题,但我只是处理了它的一个变体,但这里的解决方案都不适用,所以我找到了另一个,并为子孙后代添加了它。是的,我知道OP说他们知道这个选项,它不适合他们,但对于任何跟随它的人来说,它可能是有用的。

在我的例子中,我想从docker构建中测试本地apt-cache -ng服务的可用性。这意味着在测试之前绝对不能安装任何东西。无nc、nmap、expect、telnet、python。perl然而是存在的,以及核心库,所以我使用这个:

perl -MIO::Socket::INET -e 'exit(! defined( IO::Socket::INET->new("172.17.42.1:3142")))'

正如B. Rhodes所指出的,nc (netcat)将完成这项工作。更紧凑的使用方法:

nc -z <host> <port>

这样,nc将只检查端口是否打开,成功时退出0,失败时退出1。

快速交互式检查(5秒超时):

nc -z -v -w5 <host> <port>

我的机器不支持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

我猜现在给答案已经太迟了,而且这个答案可能不太好,但是你可以……

把它放在一个while循环中,并在上面加一个计时器。我更喜欢Perl而不是Solaris,但是根据你所使用的shell,你应该能够做一些像这样的事情:

TIME = 'date +%s' + 15
while TIME != `date +%s'
do whatever

然后在while循环中添加一个标志,这样如果它在完成之前超时,你可以引用超时作为失败的原因。

我怀疑telnet也有一个超时开关,但就我所知,我认为上面的方法是可行的。

我需要在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,因为它不是默认安装包。