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)
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的状态杀死并退出.
Acu*_*nus 100
timeout
nc
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)
$ 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)
$ 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 $?命令当然仅用于说明.
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)
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)
Ahm*_*fan 12
我需要一个更灵活的解决方案来处理多个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
Run Code Online (Sandbox Code Playgroud)
小智 10
如果您正在使用ksh或bash,则它们都支持使用/ 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从套接字读取.
虽然是一个老问题,但我刚刚处理了它的一个变体,但这里没有一个解决方案是适用的,所以我找到了另一个,并为后代添加它.是的,我知道OP说他们知道这个选项并且它不适合他们,但对于之后跟随它的任何人来说它可能证明是有用的.
就我而言,我想测试构建中本地apt-cacher-ng服务的可用性docker.这意味着在测试之前绝对不能安装任何东西.不nc,nmap,expect,telnet或python. perl然而,与核心库一起存在,所以我使用了这个:
perl -MIO::Socket::INET -e 'exit(! defined( IO::Socket::INET->new("172.17.42.1:3142")))'
Run Code Online (Sandbox Code Playgroud)
在某些情况下,像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
$ ./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 也有一个超时开关,但就在我的脑海中,我认为上面的方法会起作用。