我正在寻找一种快速而简单的方法,用于在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
我要么需要一个更好的方法,或者如果它在8秒内没有连接就强制telnet超时,并返回我可以在Shell中捕获的东西(返回代码或stdout中的字符串) .
我知道Perl方法,它使用IO :: Socket :: INET模块并编写了一个测试端口的成功脚本,但是如果可能的话,我宁愿避免使用Perl .
注意:这是我的服务器运行的地方(我需要从中运行它)
SunOS 5.10 Generic_139556-08 i86pc i386 i86pc
16 回答
我需要一个更灵活的解决方案来处理多个git存储库,所以我根据1和2编写了以下sh代码 . 您可以使用您的服务器地址代替gitlab.com,并将您的端口替换为22 .
正如B. Rhodes指出的那样,
nc
将完成这项工作 . 一种更紧凑的使用方式:那样
nc
只会检查端口是否打开,成功时退出0,失败时退出1 .对于快速交互式检查(超时5秒):
在某些情况下,像curl,telnet,nc o nmap这样的工具不可用,你仍然有机会使用wget
对
nc
的-z
和-w TIMEOUT
选项很容易,但并非所有系统都安装了nc
. 如果您有最新版本的bash,这将有效:这里发生的是
timeout
将运行子命令并在它未在指定的超时内退出时杀死它(在上例中为1秒) . 在这种情况下,bash
是子命令,并使用其特殊的/dev/tcp handling来尝试打开与指定的服务器和端口的连接 . 如果bash
可以在超时内打开连接,cat
将立即关闭它(因为它从/dev/null
读取)并退出状态代码0
,它将通过bash
然后timeout
传播 . 如果bash
在指定的超时之前发生连接失败,则bash
将退出,退出代码为1,timeout
也将返回 . 如果bash无法 Build 连接并且指定的超时到期,则timeout
将终止bash
并以状态124退出 .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
.命令:
如果参数化主机和端口,请确保将它们指定为
${HOST}
和${PORT}
,如上所述 . 不要仅将它们指定为$HOST
和$PORT
,即没有括号;在这种情况下它不起作用 .示例:
成功:
失败:
如果必须保留
bash
的退出状态,使用nc:
请注意,在RHEL 7上安装了向后不兼容的
nc
版本 .命令:
请注意,下面的命令是唯一的,因为它对于RHEL 6和7都是相同的 . 它只是安装和输出不同 .
RHEL 6(nc-1.84):
安装:
示例:
成功:
失败:
如果主机名映射到多个IP,则上述失败命令将循环遍历其中的许多或全部 . 例如:
RHEL 7(nmap-ncat-6.40):
安装:
示例:
成功:
失败:
如果主机名映射到多个IP,则上述失败命令将循环遍历其中的许多或全部 . 例如:
备注:
-v
(--verbose
)参数和echo $?
命令当然仅供参考 .使用
netcat
,您可以检查端口是否像这样打开:如果打开TCP端口,
nc
的返回值将成功,如果无法 Build TCP连接,则返回失败(通常是返回码1) .在Bash中使用pseudo-device files进行TCP / UDP连接是直截了当的 . 这是脚本:
测试:
这是一行(Bash语法):
请注意,某些服务器可以受SYN防火墙保护泛洪攻击,因此您可能会遇到TCP连接超时(~75secs) . 要解决超时问题,请尝试:
见:How to decrease TCP connect() system call timeout?
虽然是一个老问题,但我刚刚处理了它的一个变体,但这里没有一个解决方案是适用的,所以我找到了另一个,并为后代添加它 . 是的,我知道OP说他们知道这个选项并且它不适合他们,但对于之后跟随它的任何人来说它可能证明是有用的 .
就我而言,我想测试
docker
构建中本地apt-cacher-ng
服务的可用性 . 这意味着在测试之前绝对不能安装任何东西 . 否nc
,nmap
,expect
,telnet
或python
. 然而,perl
与核心库一起存在,所以我使用了这个:如果您正在使用 ksh 或 bash ,则它们都支持使用 /dev/tcp/IP/PORT 构造进行套接字的IO重定向 . 在这个 Korn shell 示例中,我从套接字重定向no-op( : )std-in:
如果套接字未打开,shell会输出错误:
因此,您可以在 if 条件中将其用作 test :
no-op位于子shell中,因此如果std-in重定向失败,我可以抛出std-err .
我经常使用 /dev/tcp 来检查HTTP资源的可用性:
这个单行打开 file descriptor 9 用于读取和写入套接字,将 HTTP GET 打印到套接字并使用 cat 从套接字读取 .
如果您想使用
nc
但没有支持-z
的版本,请尝试使用--send-only
:并且超时:
并且如果它是IP,则不进行DNS查找:
它返回代码
-z
基于它是否可以连接 .我猜这个答案已经太晚了,这可能不是一个好的,但是你走了......
把它放在一个带有定时器的while循环里面怎么样呢 . 我不是Solaris的Perl人,但根据你使用的shell,你应该能够做到这样的事情:
然后只需在while循环中添加一个标志,这样如果它在完成之前超时,你可以引用超时作为失败的原因 .
我怀疑telnet也有一个超时开关,但就在我的头顶,我认为上面的内容是可行的 .
我需要在cron中运行并且没有输出的短脚本 . 我使用nmap解决了我的麻烦
运行它您应该安装nmap,因为它不是默认安装的软件包 .
这在幕后使用telnet,似乎在mac / linux上运行良好 . 它不使用netcat,因为linux / mac上的版本之间存在差异,这适用于默认的mac安装 .
示例:
is_port_open.sh
使用bash检查端口
示例
港口22是开放的
代码
在最高投票答案的基础上,这里有一个等待两个端口打开的功能,也有一个超时 . 注意两个打开的端口,8890和1111,以及max_attempts(每秒1个) .
nmap-ncat测试尚未使用的本地端口