测试是否从Shell脚本打开了远程TCP端口

本文翻译自:Test if remote TCP port is open from a shell script

I'm looking for a quick and simple method for properly testing if a given TCP port is open on a remote server, from inside a Shell script. 我正在寻找一种快速,简单的方法来从Shell脚本内部正确测试远程服务器上是否打开了给定的TCP端口。

I've managed to do it with the telnet command, and it works fine when the port is opened, but it doesn't seem to timeout when it's not and just hangs there... 我已经用telnet命令做到了,当打开端口时,它可以正常工作,但是当端口不打开时,它似乎并没有超时,而只是挂在那里。

Here's a sample: 这是一个示例:

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

I either need a better way, or a way to force telnet to timeout if it doesn't connect in under 8 seconds for example, and return something I can catch in Shell (return code, or string in stdout). 我或者需要一种更好的方法,或者是一种强制telnet超时的方法(例如,如果它在8秒内没有连接),然后返回我可以在Shell中捕获的内容(返回代码或stdout中的字符串)。

I know of the Perl method, which uses the IO::Socket::INET module and wrote a successful script that tests a port, but would rather like to avoid using Perl if possible. 我知道Perl方法,该方法使用IO :: Socket :: INET模块并编写了成功的脚本来测试端口,但如果可能的话,希望避免使用Perl。

Note: This is what my server is running (where I need to run this from) 注意:这就是我的服务器正在运行的(我需要从中运行)

SunOS 5.10 Generic_139556-08 i86pc i386 i86pc SunOS 5.10 Generic_139556-08 i86pc i386 i86pc


#1楼

参考:https://stackoom.com/question/kEGj/测试是否从Shell脚本打开了远程TCP端口


#2楼

TOC: 目录:

  • Using bash and timeout 使用bash和timeout
    • Command 命令
    • Examples 例子
  • Using nc 使用nc
    • Command 命令
    • RHEL 6 (nc-1.84) RHEL 6(nc-1.84)
      • Installation 安装
      • Examples 例子
    • RHEL 7 (nmap-ncat-6.40) RHEL 7(nmap-ncat-6.40)
      • Installation 安装
      • Examples 例子
  • Remarks 备注

Using bash and timeout : 使用bash和timeout

Note that timeout should be present with RHEL 6+, or is alternatively found in GNU coreutils 8.22. 请注意, timeout应该在RHEL 6+中出现,或者可以在GNU coreutils 8.22中找到。 On MacOS, install it using brew install coreutils and use it as gtimeout . 在MacOS上,使用brew install coreutils安装它,并将其用作gtimeout

Command: 命令:

$ timeout $TIMEOUT_SECONDS bash -c "</dev/tcp/${HOST}/${PORT}"; echo $?

If parametrizing the host and port, be sure to specify them as ${HOST} and ${PORT} as is above. 如果对主机和端口进行参数设置,请确保如上所述将它们指定为${HOST}${PORT} Do not specify them merely as $HOST and $PORT , ie without the braces; 不要仅将它们指定为$HOST$PORT ,即不使用大括号; it won't work in this case. 在这种情况下将不起作用。

Example: 例:

Success: 成功:

$ timeout 2 bash -c "</dev/tcp/canyouseeme.org/80"; echo $?
0

Failure: 失败:

$ timeout 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?
124

If you must preserve the exit status of bash , 如果您必须保留bash的退出状态,

$ timeout --preserve-status 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?
143

Using nc : 使用nc

Note that a backward incompatible version of nc gets installed on RHEL 7. 请注意,RHEL 7上安装了向后不兼容的nc版本。

Command: 命令:

Note that the command below is unique in that it is identical for both RHEL 6 and 7. It's just the installation and output that are different. 请注意,以下命令是唯一的,因为它对于RHEL 6和7是相同的。只是安装和输出是不同的。

$ nc -w $TIMEOUT_SECONDS -v $HOST $PORT </dev/null; echo $?

RHEL 6 (nc-1.84): RHEL 6(nc-1.84):

Installation: 安装:

$ sudo yum install nc

Examples: 例子:

Success: 成功:
 $ nc -w 2 -v canyouseeme.org 80 </dev/null; echo $? Connection to canyouseeme.org 80 port [tcp/http] succeeded! 0 
Failure: 失败:
 $ 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 

If the hostname maps to multiple IPs, the above failing command will cycle through many or all of them. 如果主机名映射到多个IP,则上面失败的命令将在许多或所有IP中循环。 For example: 例如:

 $ 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 

RHEL 7 (nmap-ncat-6.40): RHEL 7(nmap-ncat-6.40):

Installation: 安装:

 $ sudo yum install nmap-ncat 

Examples: 例子:

Success: 成功:
 $ 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 
Failure: 失败:
 $ nc -w 2 -v canyouseeme.org 81 </dev/null; echo $? Ncat: Version 6.40 ( http://nmap.org/ncat ) Ncat: Connection timed out. 1 

If the hostname maps to multiple IPs, the above failing command will cycle through many or all of them. 如果主机名映射到多个IP,则上面失败的命令将在许多或所有IP中循环。 For example: 例如:

 $ 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 

Remarks: 备注:

The -v ( --verbose ) argument and the echo $? -v (-- --verbose )参数和echo $? command are of course for illustration only. 命令当然仅用于说明。


#3楼

If you're using ksh or bash they both support IO redirection to/from a socket using the /dev/tcp/IP/PORT construct. 如果您使用的是kshbash,它们都支持使用/ dev / tcp / IP / PORT构造从IO重定向到套接字或从套接字重定向。 In this Korn shell example I am redirecting no-op's ( : ) std-in from a socket: 在此Korn shell示例中,我从套接字重定向no-op的( )std-in:

W$ python -m SimpleHTTPServer &
[1]     16833
Serving HTTP on 0.0.0.0 port 8000 ...
W$ : </dev/tcp/127.0.0.1/8000

The shell prints an error if the socket is not open: 如果套接字未打开,则外壳会显示错误:

W$ : </dev/tcp/127.0.0.1/8001
ksh: /dev/tcp/127.0.0.1/8001: cannot open [Connection refused]

You can therefore use this as the test in an if condition: 因此,可以在if条件下将此作为测试

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

The no-op is in a subshell so I can throw std-err away if the std-in redirection fails. no-op位于子外壳中,因此如果std-in重定向失败,我可以丢弃std-err。

I often use /dev/tcp for checking the availability of a resource over HTTP: 我经常使用/ 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$ 

This one-liner opens file descriptor 9 for reading from and writing to the socket, prints the HTTP GET to the socket and uses cat to read from the socket. 这个单行代码打开文件描述符9以便从套接字读取和写入套接字,将HTTP GET打印到套接字,并使用cat从套接字读取。


#4楼

It's easy enough to do with the -z and -w TIMEOUT options to nc , but not all systems have nc installed. 使用nc-z-w TIMEOUT选项非常容易,但是并非所有系统都安装了nc If you have a recent enough version of bash, this will work: 如果您的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

What's happening here is that timeout will run the subcommand and kill it if it doesn't exit within the specified timeout (1 second in the above example). 这里发生的是,如果超时未在指定的超时时间内退出(在上面的示例中为1秒),则timeout将运行子命令并将其杀死。 In this case bash is the subcommand and uses its special /dev/tcp handling to try and open a connection to the server and port specified. 在这种情况下, bash是子命令,并使用其特殊的/ dev / tcp处理来尝试打开与指定服务器和端口的连接。 If bash can open the connection within the timeout, cat will just close it immediately (since it's reading from /dev/null ) and exit with a status code of 0 which will propagate through bash and then timeout . 如果bash可以在超时内打开连接,则cat会立即将其关闭(因为它正在从/dev/null读取),并以状态代码0退出,该状态代码将通过bash传播,然后timeout If bash gets a connection failure prior to the specified timeout, then bash will exit with an exit code of 1 which timeout will also return. 如果bash在指定的超时之前连接失败,则bash将以退出代码1退出,该timeout代码也将返回。 And if bash isn't able to establish a connection and the specified timeout expires, then timeout will kill bash and exit with a status of 124. 如果bash无法建立连接并且指定的超时时间到期,则timeout将杀死bash并以124状态退出。


#5楼

While an old question, I've just dealt with a variant of it, but none of the solutions here were applicable, so I found another, and am adding it for posterity. 虽然这是一个老问题,但我只是处理了它的一个变体,但这里没有一个适用的解决方案,因此我找到了另一个解决方案,并将其添加以供后代使用。 Yes, I know the OP said they were aware of this option and it didn't suit them, but for anyone following afterwards it might prove useful. 是的,我知道OP表示他们知道此选项,因此不适合他们,但是对于之后的所有人来说,它可能会有用。

In my case, I want to test for the availability of a local apt-cacher-ng service from a docker build. 就我而言,我想从docker构建中测试本地apt-cacher-ng服务的可用性。 That means absolutely nothing can be installed prior to the test. 这意味着在测试之前绝对不能安装任何东西。 No nc , nmap , expect , telnet or python . 没有ncnmapexpecttelnetpython perl however is present, along with the core libraries, so I used this: 但是, perl与核心库一起存在,因此我使用了以下代码:

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

#6楼

I needed short script which was run in cron and hasn't output. 我需要在cron中运行且没有输出的简短脚本。 I solve my trouble using 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

To run it You should install nmap because it is not default installed package. 要运行它,您应该安装nmap,因为它不是默认安装的软件包。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值