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

时间:2021-04-02 18:12:12

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.

我正在寻找一个快速和简单的方法,以便在远程服务器上打开一个给定的TCP端口,从Shell脚本中打开。

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).

我需要一个更好的方法,或者一个方法,如果它在8秒内没有连接,就可以强制telnet超时,然后返回我可以捕获的Shell(返回代码,或者stdout中的string)。

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 i86pc。

18 个解决方案

#1


363  

As pointed by B. Rhodes, nc will do the job. A more compact way to use it:

如B. Rhodes所指出的,nc将完成这项工作。一种更简洁的使用方法:

nc -z <host> <port>

That way nc will only check if the port is open, exiting with 0 on success, 1 on failure.

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

For a quick interactive check (with a 5 seconds timeout):

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

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

#2


98  

It's easy enough to do with the -z and -w TIMEOUT options to nc, but not all systems have nc installed. If you have a recent enough version of bash, this will work:

对于nc来说,使用-z和-w超时选项是很容易的,但是并不是所有的系统都安装了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

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). 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. 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. 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. 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.

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

#3


78  

TOC:

  • Using bash and timeout
    • Command
    • 命令
    • Examples
    • 例子
  • 使用bash和超时命令示例。
  • Using nc
    • Command
    • 命令
    • RHEL 6 (nc-1.84)
      • Installation
      • 安装
      • Examples
      • 例子
    • RHEL 6 (nc-1.84)安装示例。
    • RHEL 7 (nmap-ncat-6.40)
      • Installation
      • 安装
      • Examples
      • 例子
    • RHEL 7 (nmap-ncat-6.40)安装示例。
  • 使用nc命令RHEL 6 (nc-1.84)安装示例RHEL 7 (nmap-ncat-6.40)安装示例。
  • Remarks
  • 讲话

Using bash and timeout:

Note that timeout should be present with RHEL 6+, or is alternatively found in GNU coreutils 8.22. On MacOS, install it using brew install coreutils and use it as gtimeout.

注意,应该用RHEL 6+来表示超时,或者在GNU coreutils 8.22中找到。在MacOS上,使用brew安装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. Do not specify them merely as $HOST and $PORT, i.e. without the braces; it won't work in this case.

如果对主机和端口进行参数化,请确保将其指定为${host}和${port}。不要仅将它们指定为$HOST和$PORT,即没有括号;在这种情况下是行不通的。

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:

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):

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. For example:

如果主机名映射到多个ip,那么上面的失败命令将循环遍历许多或所有的IPs。例如:

$ 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):

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. For example:

如果主机名映射到多个ip,那么上面的失败命令将循环遍历许多或所有的IPs。例如:

$ 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 $? command are of course for illustration only.

-v (- verbose)参数和echo $?当然,命令只是用来说明的。

#4


34  

With netcat you can check whether a port is open like this:

使用netcat,您可以检查一个端口是否像这样打开:

nc my.example.com 80 < /dev/null

The return value of nc will be success if the TCP port was opened, and failure (typically the return code 1) if it could not make the TCP connection.

如果TCP端口被打开,那么nc的返回值将是成功的,如果不能进行TCP连接,则失败(通常是返回代码1)。

#5


21  

In Bash using pseudo-device files for TCP/UDP connections is straight forward. Here is the script:

在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

Testing:

测试:

$ ./test.sh 
Connection to example.com on port 80 succeeded

Here is one-liner (Bash syntax):

这是一行程序(Bash语法):

</dev/tcp/localhost/11211 && echo Port open. || echo Port closed.

Note that some servers can be firewall protected from SYN flood attacks, so you may experience a TCP connection timeout (~75secs). To workaround the timeout issue, try:

注意,有些服务器可以被防火墙保护,免受SYN洪水攻击,因此您可能会遇到TCP连接超时(~75secs)。要解决超时问题,请尝试:

timeout 1 bash -c "</dev/tcp/*.com/81" && echo Port open. || echo Port closed.

See: How to decrease TCP connect() system call timeout?

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

#6


7  

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. That means absolutely nothing can be installed prior to the test. No nc, nmap, expect, telnet or python. perl however is present, along with the core libraries, so I used this:

在我的例子中,我想测试一个来自docker构建的本地apt-cacher-ng服务的可用性。这意味着在测试之前绝对不能安装任何东西。没有nc、nmap、expect、telnet或python。然而,perl与核心库一起出现,所以我使用了这个:

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

#7


7  

I needed a more flexible solution for working on multiple git repositories so I wrote the following sh code based on 1 and 2. You can use your server address instead of gitlab.com and your port in replace of 22.

我需要一个更灵活的解决方案来处理多个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

#8


6  

If you're using ksh or bash they both support IO redirection to/from a socket using the /dev/tcp/IP/PORT construct. In this Korn shell example I am redirecting no-op's (:) std-in from a socket:

如果您使用的是ksh或bash,则它们都使用/dev/ tcp/ip/port构造从套接字中支持IO重定向。在这个Korn shell示例中,我将从一个套接字中插入“no-op”(:)

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.

无op是在一个亚层,所以我可以抛出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从套接字读取。

#9


3  

In some cases where tools like curl, telnet, nc o nmap are unavailable you still have a chance with wget

在某些情况下,如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

#10


3  

If you want to use nc but don't have a version that support -z, try using --send-only:

如果您想使用nc,但没有支持-z的版本,请尝试使用—只发送——

nc --send-only <IP> <PORT> </dev/null

and with timeout:

和超时:

nc -w 1 --send-only <IP> <PORT> </dev/null

and without DNS lookup if it's an IP:

没有DNS查询,如果是IP:

nc -n -w 1 --send-only <IP> <PORT> </dev/null

It returns the codes as the -z based on if it can connect or not.

它将代码作为-z返回,如果它可以连接或不连接。

#11


2  

I'm guessing that it's too late for an answer, and this might not be a good one, but here you go...

我猜对一个答案来说已经太晚了,这可能不是一个好的答案,但是你可以……

What about putting it inside of a while loop with a timer on it of some sort. I'm more of a Perl guy than Solaris, but depending on the shell you're using, you should be able to do something like:

把它放到一个while循环中,并在其中设置一个计时器。我比Solaris更像一个Perl人员,但是根据您使用的shell,您应该能够做一些事情:

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

And then just add a flag in the while loop, so that if it times out before completing, you can cite the timeout as reason for failure.

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

I suspect that the telnet has a timeout switch as well, but just off the top of my head, I think the above will work.

我怀疑telnet也有一个超时开关,但是我认为上面的内容会有用。

#12


0  

What about Netcat or Nmap?

那Netcat或Nmap呢?

#13


0  

I needed short script which was run in cron and hasn't output. I solve my trouble using nmap

我需要一个短小的脚本,它运行在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

To run it You should install nmap because it is not default installed package.

要运行它,您应该安装nmap,因为它不是默认安装的软件包。

#14


0  

This uses telnet behind the scenes, and seems to work fine on mac/linux. It doesn't use netcat because of the differences between the versions on linux/mac, and this works with a default mac install.

这在幕后使用telnet,并且在mac/linux上运行良好。它不使用netcat,因为在linux/mac上的版本不同,这与默认的mac安装有关系。

Example:

$ is_port_open.sh 80 google.com
OPEN

$ is_port_open.sh 8080 google.com
CLOSED

is_port_open.sh

PORT=$1
HOST=$2
TIMEOUT_IN_SEC=${3:-1}
VALUE_IF_OPEN=${4:-"OPEN"}
VALUE_IF_CLOSED=${5:-"CLOSED"}

function eztern()
{
  if [ "$1" == "$2" ]
  then
    echo $3
  else
    echo $4
  fi
}

# cross platform timeout util to support mac mostly
# https://gist.github.com/jaytaylor/6527607
function eztimeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }

function testPort()
{
  OPTS=""

  # find out if port is open using telnet
  # by saving telnet output to temporary file
  # and looking for "Escape character" response
  # from telnet
  FILENAME="/tmp/__port_check_$(uuidgen)"
  RESULT=$(eztimeout $TIMEOUT_IN_SEC telnet $HOST $PORT &> $FILENAME; cat $FILENAME | tail -n1)
  rm -f $FILENAME;
  SUCCESS=$(eztern "$RESULT" "Escape character is '^]'." "$VALUE_IF_OPEN" "$VALUE_IF_CLOSED")

  echo "$SUCCESS"
}

testPort 

#15


0  

check ports using bash

Example

$ ./test_port_bash.sh 192.168.7.7 22

the port 22 is open

端口22是打开的。

Code

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

#16


0  

Building on the most highly voted answer, here is a function to wait for two ports to be open, with a timeout as well. Note the two ports that mus be open, 8890 and 1111, as well as the max_attempts (1 per second).

在最高度投票的答案上,这是一个等待两个端口打开的函数,还有一个超时。注意这两个端口分别为open、8890和1111,以及max_try (1 / s)。

function wait_for_server_to_boot()
{
    echo "Waiting for server to boot up..."
    attempts=0
    max_attempts=30
    while ( nc 127.0.0.1 8890 < /dev/null || nc 127.0.0.1 1111 < /dev/null )  && [[ $attempts < $max_attempts ]] ; do
        attempts=$((attempts+1))
        sleep 1;
        echo "waiting... (${attempts}/${max_attempts})"
    done
}

#17


-1  

nmap-ncat to test for local port that is not already in use


availabletobindon() {
  port="$1"
  nc -w 2 -i 1 localhost "$port" 2>&1 | grep -v -q 'Idle timeout expired'
  return "$?"
}

#18


-2  

The answer lied with Expect. We wrote a simple script that sends a telnet on the port we needed, with a timeout of 8 seconds. There's plenty of examples to pick from too.

答案在意料之中。我们编写了一个简单的脚本,它在我们需要的端口上发送一个telnet,超时时间为8秒。也有很多例子可供选择。

We based ours off this post: http://www.unix.com/shell-programming-scripting/146568-expect-telnet-testing-tacacs-cisco.html

我们的基础是:http://www.unix.com/shell-编程-scripting/146568-expect-telnet- testingtacacs-cisco.html。

#1


363  

As pointed by B. Rhodes, nc will do the job. A more compact way to use it:

如B. Rhodes所指出的,nc将完成这项工作。一种更简洁的使用方法:

nc -z <host> <port>

That way nc will only check if the port is open, exiting with 0 on success, 1 on failure.

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

For a quick interactive check (with a 5 seconds timeout):

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

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

#2


98  

It's easy enough to do with the -z and -w TIMEOUT options to nc, but not all systems have nc installed. If you have a recent enough version of bash, this will work:

对于nc来说,使用-z和-w超时选项是很容易的,但是并不是所有的系统都安装了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

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). 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. 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. 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. 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.

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

#3


78  

TOC:

  • Using bash and timeout
    • Command
    • 命令
    • Examples
    • 例子
  • 使用bash和超时命令示例。
  • Using nc
    • Command
    • 命令
    • RHEL 6 (nc-1.84)
      • Installation
      • 安装
      • Examples
      • 例子
    • RHEL 6 (nc-1.84)安装示例。
    • RHEL 7 (nmap-ncat-6.40)
      • Installation
      • 安装
      • Examples
      • 例子
    • RHEL 7 (nmap-ncat-6.40)安装示例。
  • 使用nc命令RHEL 6 (nc-1.84)安装示例RHEL 7 (nmap-ncat-6.40)安装示例。
  • Remarks
  • 讲话

Using bash and timeout:

Note that timeout should be present with RHEL 6+, or is alternatively found in GNU coreutils 8.22. On MacOS, install it using brew install coreutils and use it as gtimeout.

注意,应该用RHEL 6+来表示超时,或者在GNU coreutils 8.22中找到。在MacOS上,使用brew安装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. Do not specify them merely as $HOST and $PORT, i.e. without the braces; it won't work in this case.

如果对主机和端口进行参数化,请确保将其指定为${host}和${port}。不要仅将它们指定为$HOST和$PORT,即没有括号;在这种情况下是行不通的。

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:

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):

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. For example:

如果主机名映射到多个ip,那么上面的失败命令将循环遍历许多或所有的IPs。例如:

$ 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):

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. For example:

如果主机名映射到多个ip,那么上面的失败命令将循环遍历许多或所有的IPs。例如:

$ 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 $? command are of course for illustration only.

-v (- verbose)参数和echo $?当然,命令只是用来说明的。

#4


34  

With netcat you can check whether a port is open like this:

使用netcat,您可以检查一个端口是否像这样打开:

nc my.example.com 80 < /dev/null

The return value of nc will be success if the TCP port was opened, and failure (typically the return code 1) if it could not make the TCP connection.

如果TCP端口被打开,那么nc的返回值将是成功的,如果不能进行TCP连接,则失败(通常是返回代码1)。

#5


21  

In Bash using pseudo-device files for TCP/UDP connections is straight forward. Here is the script:

在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

Testing:

测试:

$ ./test.sh 
Connection to example.com on port 80 succeeded

Here is one-liner (Bash syntax):

这是一行程序(Bash语法):

</dev/tcp/localhost/11211 && echo Port open. || echo Port closed.

Note that some servers can be firewall protected from SYN flood attacks, so you may experience a TCP connection timeout (~75secs). To workaround the timeout issue, try:

注意,有些服务器可以被防火墙保护,免受SYN洪水攻击,因此您可能会遇到TCP连接超时(~75secs)。要解决超时问题,请尝试:

timeout 1 bash -c "</dev/tcp/*.com/81" && echo Port open. || echo Port closed.

See: How to decrease TCP connect() system call timeout?

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

#6


7  

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. That means absolutely nothing can be installed prior to the test. No nc, nmap, expect, telnet or python. perl however is present, along with the core libraries, so I used this:

在我的例子中,我想测试一个来自docker构建的本地apt-cacher-ng服务的可用性。这意味着在测试之前绝对不能安装任何东西。没有nc、nmap、expect、telnet或python。然而,perl与核心库一起出现,所以我使用了这个:

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

#7


7  

I needed a more flexible solution for working on multiple git repositories so I wrote the following sh code based on 1 and 2. You can use your server address instead of gitlab.com and your port in replace of 22.

我需要一个更灵活的解决方案来处理多个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

#8


6  

If you're using ksh or bash they both support IO redirection to/from a socket using the /dev/tcp/IP/PORT construct. In this Korn shell example I am redirecting no-op's (:) std-in from a socket:

如果您使用的是ksh或bash,则它们都使用/dev/ tcp/ip/port构造从套接字中支持IO重定向。在这个Korn shell示例中,我将从一个套接字中插入“no-op”(:)

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.

无op是在一个亚层,所以我可以抛出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从套接字读取。

#9


3  

In some cases where tools like curl, telnet, nc o nmap are unavailable you still have a chance with wget

在某些情况下,如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

#10


3  

If you want to use nc but don't have a version that support -z, try using --send-only:

如果您想使用nc,但没有支持-z的版本,请尝试使用—只发送——

nc --send-only <IP> <PORT> </dev/null

and with timeout:

和超时:

nc -w 1 --send-only <IP> <PORT> </dev/null

and without DNS lookup if it's an IP:

没有DNS查询,如果是IP:

nc -n -w 1 --send-only <IP> <PORT> </dev/null

It returns the codes as the -z based on if it can connect or not.

它将代码作为-z返回,如果它可以连接或不连接。

#11


2  

I'm guessing that it's too late for an answer, and this might not be a good one, but here you go...

我猜对一个答案来说已经太晚了,这可能不是一个好的答案,但是你可以……

What about putting it inside of a while loop with a timer on it of some sort. I'm more of a Perl guy than Solaris, but depending on the shell you're using, you should be able to do something like:

把它放到一个while循环中,并在其中设置一个计时器。我比Solaris更像一个Perl人员,但是根据您使用的shell,您应该能够做一些事情:

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

And then just add a flag in the while loop, so that if it times out before completing, you can cite the timeout as reason for failure.

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

I suspect that the telnet has a timeout switch as well, but just off the top of my head, I think the above will work.

我怀疑telnet也有一个超时开关,但是我认为上面的内容会有用。

#12


0  

What about Netcat or Nmap?

那Netcat或Nmap呢?

#13


0  

I needed short script which was run in cron and hasn't output. I solve my trouble using nmap

我需要一个短小的脚本,它运行在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

To run it You should install nmap because it is not default installed package.

要运行它,您应该安装nmap,因为它不是默认安装的软件包。

#14


0  

This uses telnet behind the scenes, and seems to work fine on mac/linux. It doesn't use netcat because of the differences between the versions on linux/mac, and this works with a default mac install.

这在幕后使用telnet,并且在mac/linux上运行良好。它不使用netcat,因为在linux/mac上的版本不同,这与默认的mac安装有关系。

Example:

$ is_port_open.sh 80 google.com
OPEN

$ is_port_open.sh 8080 google.com
CLOSED

is_port_open.sh

PORT=$1
HOST=$2
TIMEOUT_IN_SEC=${3:-1}
VALUE_IF_OPEN=${4:-"OPEN"}
VALUE_IF_CLOSED=${5:-"CLOSED"}

function eztern()
{
  if [ "$1" == "$2" ]
  then
    echo $3
  else
    echo $4
  fi
}

# cross platform timeout util to support mac mostly
# https://gist.github.com/jaytaylor/6527607
function eztimeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }

function testPort()
{
  OPTS=""

  # find out if port is open using telnet
  # by saving telnet output to temporary file
  # and looking for "Escape character" response
  # from telnet
  FILENAME="/tmp/__port_check_$(uuidgen)"
  RESULT=$(eztimeout $TIMEOUT_IN_SEC telnet $HOST $PORT &> $FILENAME; cat $FILENAME | tail -n1)
  rm -f $FILENAME;
  SUCCESS=$(eztern "$RESULT" "Escape character is '^]'." "$VALUE_IF_OPEN" "$VALUE_IF_CLOSED")

  echo "$SUCCESS"
}

testPort 

#15


0  

check ports using bash

Example

$ ./test_port_bash.sh 192.168.7.7 22

the port 22 is open

端口22是打开的。

Code

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

#16


0  

Building on the most highly voted answer, here is a function to wait for two ports to be open, with a timeout as well. Note the two ports that mus be open, 8890 and 1111, as well as the max_attempts (1 per second).

在最高度投票的答案上,这是一个等待两个端口打开的函数,还有一个超时。注意这两个端口分别为open、8890和1111,以及max_try (1 / s)。

function wait_for_server_to_boot()
{
    echo "Waiting for server to boot up..."
    attempts=0
    max_attempts=30
    while ( nc 127.0.0.1 8890 < /dev/null || nc 127.0.0.1 1111 < /dev/null )  && [[ $attempts < $max_attempts ]] ; do
        attempts=$((attempts+1))
        sleep 1;
        echo "waiting... (${attempts}/${max_attempts})"
    done
}

#17


-1  

nmap-ncat to test for local port that is not already in use


availabletobindon() {
  port="$1"
  nc -w 2 -i 1 localhost "$port" 2>&1 | grep -v -q 'Idle timeout expired'
  return "$?"
}

#18


-2  

The answer lied with Expect. We wrote a simple script that sends a telnet on the port we needed, with a timeout of 8 seconds. There's plenty of examples to pick from too.

答案在意料之中。我们编写了一个简单的脚本,它在我们需要的端口上发送一个telnet,超时时间为8秒。也有很多例子可供选择。

We based ours off this post: http://www.unix.com/shell-programming-scripting/146568-expect-telnet-testing-tacacs-cisco.html

我们的基础是:http://www.unix.com/shell-编程-scripting/146568-expect-telnet- testingtacacs-cisco.html。