如果远程TCP端口已打开,请从shell脚本进行测试

Yan*_*ard 287 shell port solaris tcp telnet

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

我已经设法使用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
Run Code Online (Sandbox Code Playgroud)

我要么需要一个更好的办法,还是有办法来强制远程登录超时如果它没有下8秒连接,例如,和(在标准输出返回码,或字符串)返回的东西我可以赶上壳.

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

注意:这是我的服务器运行的地方(我需要从中运行它)

SunOS 5.10 Generic_139556-08 i86pc i386 i86pc

Ale*_*eta 435

正如B. Rhodes所指出的那样,他们nc将完成这项工作.一种更紧凑的使用方式:

nc -z <host> <port>
Run Code Online (Sandbox Code Playgroud)

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

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

nc -z -v -w5 <host> <port>
Run Code Online (Sandbox Code Playgroud)

  • centos7默认使用nmap netcat并且没有-z选项. (47认同)
  • 这在RHEL/Centos中不起作用.对于那些你需要的发行版:nc -vn <host> <port> (7认同)
  • 至少在Mac上,您可能需要添加-G#来设置与-w#超时时间不同的连接超时时间(基本上是作为读取超时时间)。 (3认同)
  • FWIW,我已经完全彻底改变了[我的答案与一个例子](http://stackoverflow.com/a/14701003/832230),分别适用于RHEL 6和RHEL 7. (2认同)

onl*_*one 137

使用-z-w TIMEOUT选项很容易nc,但并非所有系统都已nc安装.如果您有最新版本的bash,这将有效:

# 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
Run Code Online (Sandbox Code Playgroud)

这里发生的是timeout运行子命令并在它未在指定的超时内退出时杀死它(在上例中为1秒).在这种情况下bash是子命令并使用其特殊的/ dev/tcp处理来尝试打开与指定的服务器和端口的连接.如果bash可以在超时内打开连接,cat将立即关闭它(因为它正在读取/dev/null)并退出,其状态代码0将传播通过bash然后timeout.如果bash在指定的超时之前获得连接失败,则将bash以退出代码1退出,退出代码也timeout将返回.如果bash无法建立连接并且指定的超时到期,那么timeout将以bash124的状态杀死并退出.

  • / dev/tcp是bash的一个特性,所以是的.然而,看起来mac没有超时...... (8认同)
  • 只是想提到`timeout`似乎是GNU coreutils的一部分,并且可以安装在带有自制软件的mac上:`brew install coreutils`.它将作为`gtimeout`提供. (3认同)
  • `/dev/tcp` 在 Linux 以外的系统上是否可用?特别是 Mac 呢? (2认同)

Acu*_*nus 100

TOC:

  • 使用bash和 timeout
    • 命令
    • 例子
  • 运用 nc
    • 命令
    • RHEL 6(nc-1.84)
      • 安装
      • 例子
    • RHEL 7(nmap-ncat-6.40)
      • 安装
      • 例子
  • 备注

使用bash和timeout:

请注意,timeout应该与RHEL 6+一起使用,或者在GNU coreutils 8.22中找到.在MacOS上,brew install coreutils使用它并将其用作gtimeout.

命令:

$ timeout $TIMEOUT_SECONDS bash -c "</dev/tcp/${HOST}/${PORT}"; echo $?
Run Code Online (Sandbox Code Playgroud)

如果参数化的主机和端口时,请务必将其指定为${HOST}${PORT}如以上.不要仅仅将其指定为$HOST$PORT,即没有括号; 在这种情况下它不起作用.

例:

成功:

$ timeout 2 bash -c "</dev/tcp/canyouseeme.org/80"; echo $?
0
Run Code Online (Sandbox Code Playgroud)

失败:

$ timeout 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?
124
Run Code Online (Sandbox Code Playgroud)

如果必须保留退出状态bash,

$ timeout --preserve-status 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?
143
Run Code Online (Sandbox Code Playgroud)

使用nc:

请注意,ncRHEL 7上安装了向后不兼容的gets 版本.

命令:

请注意,下面的命令是唯一的,因为它对于RHEL 6和7都是相同的.它只是安装和输出不同.

$ nc -w $TIMEOUT_SECONDS -v $HOST $PORT </dev/null; echo $?
Run Code Online (Sandbox Code Playgroud)

RHEL 6(nc-1.84):

安装:

$ sudo yum install nc
Run Code Online (Sandbox Code Playgroud)

例子:

成功:
$ nc -w 2 -v canyouseeme.org 80 </dev/null; echo $?
Connection to canyouseeme.org 80 port [tcp/http] succeeded!
0
Run Code Online (Sandbox Code Playgroud) 失败:
$ nc -w 2 -v canyouseeme.org 81 </dev/null; echo $?
nc: connect to canyouseeme.org port 81 (tcp) timed out: Operation now in progress
1
Run Code Online (Sandbox Code Playgroud)

如果主机名映射到多个IP,则上述失败命令将循环遍历其中的许多或全部.例如:

$ nc -w 2 -v microsoft.com 81 </dev/null; echo $?
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
1
Run Code Online (Sandbox Code Playgroud)

RHEL 7(nmap-ncat-6.40):

安装:

$ sudo yum install nmap-ncat
Run Code Online (Sandbox Code Playgroud)

例子:

成功:
$ nc -w 2 -v canyouseeme.org 80 </dev/null; echo $?
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connected to 52.202.215.126:80.
Ncat: 0 bytes sent, 0 bytes received in 0.22 seconds.
0
Run Code Online (Sandbox Code Playgroud) 失败:
$ nc -w 2 -v canyouseeme.org 81 </dev/null; echo $?
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connection timed out.
1
Run Code Online (Sandbox Code Playgroud)

如果主机名映射到多个IP,则上述失败命令将循环遍历其中的许多或全部.例如:

$ nc -w 2 -v microsoft.com 81 </dev/null; echo $?
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connection to 104.43.195.251 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection to 23.100.122.175 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection to 23.96.52.53 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection to 191.239.213.197 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection timed out.
1
Run Code Online (Sandbox Code Playgroud)

备注:

-v(--verbose)的参数和echo $?命令当然仅用于说明.

  • `timeout 2 bash -c"</dev/tcp/canyouseeme.org/81"; echo $?`很棒! (3认同)

Bra*_*des 51

有了netcat你可以查看端口是否是这样打开的:

nc my.example.com 80 < /dev/null
Run Code Online (Sandbox Code Playgroud)

nc如果打开TCP端口,则返回值将成功;如果无法建立TCP连接,则返回失败(通常为返回码1).

nc尝试此操作时,某些版本会挂起,因为即使在收到文件结尾后,它们也不会关闭其插槽的一半/dev/null.在我自己的Ubuntu笔记本电脑(18.04)上,netcat-openbsd我安装的netcat版本提供了一种解决方法:该-N选项对于获得即时结果是必要的:

nc -N my.example.com 80 < /dev/null
Run Code Online (Sandbox Code Playgroud)

  • 谢谢 - 也适用于没有`-z`支持的nc版本 - 例如,适用于RHEL/CentOS 7 (5认同)
  • 适用于不支持 `-w` 标志的 `nc` 风格。 (2认同)
  • +1这很棒,因为nc标配了alpine linux和ubuntu.可能是其他人 你需要远程安装时不需要额外安装.谢谢你!我可以补充一下,`nc host port -w 2 && echo it works` (2认同)
  • 我更喜欢`nc -vz localhost 3306`。它提供了更详细的输出。只在mac上试过。 (2认同)

ken*_*orb 27

在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
Run Code Online (Sandbox Code Playgroud)

测试:

$ ./test.sh 
Connection to example.com on port 80 succeeded
Run Code Online (Sandbox Code Playgroud)

这是一行(Bash语法):

</dev/tcp/localhost/11211 && echo Port open. || echo Port closed.
Run Code Online (Sandbox Code Playgroud)

请注意,某些服务器可以防止SYN Flood攻击,因此您可能会遇到TCP连接超时(~75secs).要解决超时问题,请尝试:

timeout 1 bash -c "</dev/tcp/stackoverflow.com/81" && echo Port open. || echo Port closed.
Run Code Online (Sandbox Code Playgroud)

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


Ahm*_*fan 12

我需要一个更灵活的解决方案来处理多个git存储库,所以我编写了基于12的以下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
Run Code Online (Sandbox Code Playgroud)


小智 10

如果您正在使用kshbash,则它们都支持使用/ dev/tcp/IP/PORT构造进行套接字的IO重定向.在此Korn shell的例子中,我重定向无操作的(:从插座STD-中):

W$ python -m SimpleHTTPServer &
[1]     16833
Serving HTTP on 0.0.0.0 port 8000 ...
W$ : </dev/tcp/127.0.0.1/8000
Run Code Online (Sandbox Code Playgroud)

如果套接字未打开,shell会输出错误:

W$ : </dev/tcp/127.0.0.1/8001
ksh: /dev/tcp/127.0.0.1/8001: cannot open [Connection refused]
Run Code Online (Sandbox Code Playgroud)

因此,您可以在if条件中将其用作测试:

SERVER=127.0.0.1 PORT=8000
if (: < /dev/tcp/$SERVER/$PORT) 2>/dev/null
then
    print succeeded
else
    print failed
fi
Run Code Online (Sandbox Code Playgroud)

no-op位于子shell中,因此如果std-in重定向失败,我可以抛出std-err.

我经常使用/ dev/tcp来检查HTTP上资源的可用性:

W$ print arghhh > grr.html
W$ python -m SimpleHTTPServer &
[1]     16863
Serving HTTP on 0.0.0.0 port 8000 ...
W$ (print -u9 'GET /grr.html HTTP/1.0\n';cat <&9) 9<>/dev/tcp/127.0.0.1/8000
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.6.1
Date: Thu, 14 Feb 2013 12:56:29 GMT
Content-type: text/html
Content-Length: 7
Last-Modified: Thu, 14 Feb 2013 12:55:44 GMT

arghhh
W$ 
Run Code Online (Sandbox Code Playgroud)

这个单线程打开文件描述符9,用于读取和写入套接字,将HTTP GET打印到套接字并用于cat从套接字读取.


mc0*_*c0e 9

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

就我而言,我想测试构建中本地apt-cacher-ng服务的可用性docker.这意味着在测试之前绝对不能安装任何东西.不nc,nmap,expect,telnetpython. perl然而,与核心库一起存在,所以我使用了这个:

perl -MIO::Socket::INET -e 'exit(! defined( IO::Socket::INET->new("172.17.42.1:3142")))'
Run Code Online (Sandbox Code Playgroud)


PRF*_*PRF 6

在某些情况下,像curl,telnet,nc o 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
Run Code Online (Sandbox Code Playgroud)


小智 6

使用bash检查端口

$ ./test_port_bash.sh 192.168.7.7 22
Run Code Online (Sandbox Code Playgroud)

端口22是开放的

HOST=$1
PORT=$2
exec 3> /dev/tcp/${HOST}/${PORT}
if [ $? -eq 0 ];then echo "the port $2 is open";else echo "the port $2 is closed";fi
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您想使用nc但没有支持 的版本-z,请尝试使用--send-only

nc --send-only <IP> <PORT> </dev/null
Run Code Online (Sandbox Code Playgroud)

并超时:

nc -w 1 --send-only <IP> <PORT> </dev/null
Run Code Online (Sandbox Code Playgroud)

如果是 IP,则无需 DNS 查找:

nc -n -w 1 --send-only <IP> <PORT> </dev/null
Run Code Online (Sandbox Code Playgroud)

它返回代码作为-z基于是否可以连接。


小智 0

我猜现在回答已经太晚了,而且这可能不是一个好的答案,但你可以...

把它放在一个带有某种计时器的 while 循环中怎么样?与 Solaris 相比,我更喜欢 Perl,但根据您使用的 shell,您应该能够执行以下操作:

TIME = 'date +%s' + 15
while TIME != `date +%s'
do whatever
Run Code Online (Sandbox Code Playgroud)

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

我怀疑 telnet 也有一个超时开关,但就在我的脑海中,我认为上面的方法会起作用。