如何使用netcat等待开放端口?

问题描述 投票:0回答:13

我正在尝试使用 jenkins 制作一个自定义 dockerfile。我会等到端口 8080 打开,而不是使用 netcat 执行丑陋的“睡眠 60”,但我对 bash 脚本和 netcat 不太有信心。

这是我正在尝试做的一个例子:

#!/bin/bash
 
opened=0
 
while [ "$opened"  == "0" ]; do
  echo "Waiting jenkins to launch on 8080..."
  nc -vz localhost 8080
done
 
echo "Jenkins launched"
bash shell netcat
13个回答
156
投票

您无法将netcat设置为等待某个端口打开,因此您必须在进行下一次检查之前添加等待部分。试试这个:

#!/bin/bash

echo "Waiting jenkins to launch on 8080..."

while ! nc -z localhost 8080; do   
  sleep 0.1 # wait for 1/10 of the second before check again
done

echo "Jenkins launched"

75
投票

我建议使用以下一款衬垫:

## netcat version:
timeout 22 sh -c 'until nc -z $0 $1; do sleep 1; done' stackoverflow.com 443

## pure bash version:
timeout 22 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' stackoverflow.com 443

连接建立后,这两个命令都会退出,每秒尝试一次,最多持续 22 秒。

请注意,由于

timeout
命令,当端口可访问时,退出代码为
0
,否则
124
(如果在给定时间内没有建立连接)。


18
投票

按照here的建议,如果您没有安装

nc
,而只安装了
bash
coreutils
,您也可以执行以下操作:

#!/bin/bash

echo "Waiting jenkins to launch on 8080..."

while ! timeout 1 bash -c "echo > /dev/tcp/localhost/8080"; do   
  sleep 1
done

echo "Jenkins launched"

12
投票

我发现这是一个很常见的问题,需要编写一个实用程序来等待端口打开,并具有可选的超时:

# without timeout
wait-port localhost:8080

# timeout after a minute
wait-port -t 60000 localhost:8080

它是开源的,可在 github.com/dwmkerr/wait-port 获取。希望其他人会发现它有用!


11
投票

为了扩展 user987339 的答案,以下是如何轻松等待终端中的端口:

等待端口函数

将此函数添加到您的 ~/.bashrc 设置文件中:

waitport() {
    while ! nc -z localhost $1 ; do sleep 1 ; done
}

注销然后重新登录以加载 ~/.bashrc。然后,运行此命令来验证端口 3000 是否有服务器正在侦听:

$ waitport 3000
Connection to localhost port 3000 [tcp/hbci] succeeded!

这已在 macOS 上得到验证。它可能不适用于 Fedora/CentOS,因为它们缺少

-z
netcat
选项。


5
投票

我用它来等待几个端口打开,没有 netcat:

while (! (: </dev/tcp/localhost/27017) &> /dev/null || ! (: </dev/tcp/localhost/9200) &> /dev/null); do
    sleep 2;
done

根据需要更改

localhost
和端口。


4
投票

这是我的单行 Bash 解决方案(使用 netcat),它等待 10 秒的 TCP 连接,并在等待期间向您提供是否成功或失败的反馈,如果端口打开,则返回退出代码

0
,否则
1
:

bash -c 'echo -n "Waiting port 8080 .."; for _ in `seq 1 40`; do echo -n .; sleep 0.25; nc -z localhost 8080 && echo " Open." && exit ; done; echo " Timeout!" >&2; exit 1'

您可以将硬编码端口

8080
替换为
$1
并删除
bash -c
(如果代码片段保存在脚本文件
wait-port
中),然后在控制台中使用以下命令调用:
wait-port 8080

这是3个终端的记录,其中两个等待端口打开,其他终端打开其中一个端口,因此当其中一个等待成功时,另一个超时:

虽然该行有很多指令,但如果您需要在无法首先存储脚本的主机中“远程”执行等待,那么它可能会很有用。在 Docker 容器中。


3
投票

补充上面的优秀答案,如果这是经常使用的东西,那么为此目的使用工具可能是值得的。对于这个用例,我一直编写并使用 uup

在您的示例中,运行的命令是:

uup localhost:8080 -r

提供如下输出:


3
投票

我编写了一个实用程序来等待端口打开,它还可以检查 MySQL、PostgreSQL、Redis 等可用性。

# Checking TCP port
wait4x tcp localhost:8080

# Checking TCP port with specific timeout (5 Minutes)
wait4x tcp localhost:8080 -t 5m

它是开源的,可在 https://github.com/atkrad/wait4x 获取。希望其他人会发现它有用!


3
投票

这是一个有超时的 for 循环示例,因此它会尝试例如10 次,采用指数退避(2、4、8、16 秒等),但最终放弃。 Netcat 也有 1 秒超时。

for EXPONENTIAL_BACKOFF in {1..10}; do
    nc -w 1 -z db.local 3306 && break;
    DELAY=$((2**$EXPONENTIAL_BACKOFF))
    echo "db not yet available, sleeping for $DELAY seconds"
    sleep $DELAY
done

输出为:

db not yet available, sleeping for 2 seconds
db not yet available, sleeping for 4 seconds
db not yet available, sleeping for 8 seconds
db not yet available, sleeping for 16 seconds

3
投票

在 CI 上运行测试之前,我使用此脚本检查端口。

#!/bin/bash

for _ in `seq 1 20`; do
    echo -n .
    if nc -z localhost $1; then
        exit 0
    fi
    sleep 0.5
done

exit 1
$ bin/wait-port 3306

2
投票

对于那些有困难的人

nc: invalid option -- 'z'

我试图在 docker 镜像中设置它。令人惊讶的是,该图像中的

-z
中没有
nc
的选项。

图像是 -

Linux elasticsearch 4.4.0-101-generic #124~14.04.1-Ubuntu SMP Fri Nov 10 19:05:36 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux 

我使用以下循环来等待端口打开。

#!/bin/bash

echo "Waiting elastic search to launch on 9200..."

open=0;
while [ $open -eq 0 ]
do
    check_port=`nc -v -w 1 -i 1 127.0.0.1 9200 &> /dev/stdout`
    echo $check_port
    if [[ "$check_port" == *"Connected to"* ]]
    then
        break
    fi
    sleep 1
done

echo "Elastic Search launched"

以下是上述脚本的一行:

open=0;while [ $open -eq 0 ]; do check_port=`nc -v -w 1 -i 1 127.0.0.1 9200 &> /dev/stdout`; echo $check_port; if [[ "$check_port" == *"Connected to"* ]]; then   break; fi; sleep 1; done

0
投票

我使用这个示例用法

./xl_wait_port.sh [port] [ up | down ]

参数:

  • 等待的港口
  • 还等什么,上涨还是下跌

可以从 github xl_wait_port 下载。我是作者。

代码片段

echo Waiting for port $PORT_NO to go $MODE.
LOOP_FLAG=1
WARN_FLAG=1
while [ "$LOOP_FLAG" -gt 0 ]; do
  LOOP_FLAG=1
  STATUS=`lsof -i :$PORT_NO`
  if [ "up" == $MODE ]; then
    if [ "1" -eq "$STATUS" ]; then
      LOOP_FLAG=0
    fi
  else
    if [ "0" = "$STATUS" ]; then
      LOOP_FLAG=0
    fi
  fi
  RESULT=$((WARN_FLAG % 35))
  if [ "$RESULT" -eq "0" ]; then
    echo "Process is taking some time. Please check or wait."
  fi
  sleep 1
  ((WARN_FLAG++))
done
echo Port $PORT_NO is now $MODE.
© www.soinside.com 2019 - 2024. All rights reserved.