繁体   English   中英

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

[英]How to wait for an open port with netcat?

我正在尝试使用 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"

您不能将 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"

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

## 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 (如果在给定时间内未建立连接)。

正如这里所建议的,如果您没有安装nc而只有bashcoreutils ,您也可以执行以下操作:

#!/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"

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

# without timeout
wait-port localhost:8080

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

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

要扩展 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,因为它们缺少netcat-z选项。

对于那些遇到nc: invalid option -- 'z'

我试图在 docker 镜像中设置它。 令人惊讶的是,该图像中的nc中没有-z选项。

图像是 - 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

添加到上面的优秀答案中,如果这是经常使用的东西,那么为此目的使用工具可能是值得的。 我一直在为这个用例编写和使用uup

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

uup localhost:8080 -r

提供如下输出: 在此处输入图片说明

这是一个具有超时的 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

我编写了一个实用程序来等待端口打开,它还可以检查 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 获得 希望其他人会发现它有用!

在 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

这是我的单行 Bash 解决方案(使用 netcat),它等待 TCP 连接 10 秒,并在等待时向您反馈是否成功,如果端口打开则返回退出0<\/code>代码,否则返回1<\/code> :

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'

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

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

根据需要更改localhost和端口。

如果您正在寻找 docker-run-one-liner,请查看我基于 .netcat 循环的Docker 图像

$ docker run --rm igops/wait-for-port HOST PORT

例如,

$ docker run --rm igops/wait-for-port 172.17.0.1 80

将每0.1s查询172.17.0.1:80并在建立连接时退出:

Waiting for 172.17.0.1:80...
OK

等待另一个容器响应:

$ docker network create my-bridge
$ docker run --rm -d --net my-bridge --net-alias my-mongo mongo
$ docker run --rm --net my-bridge igops/wait-for-port my-mongo 27017
$ echo "Mongo is up at this point, do some useful stuff here"

等待 docker 主机上的一些服务:

$ docker run --rm --add-host="docker-host:host-gateway" igops/wait-for-port docker-host 22
$ echo "SSH server is running"

等待另一个发布了一些端口的容器:

$ docker run --rm -d -p 27017:27107 mongo
$ docker run --rm --add-host="docker-host:host-gateway" igops/wait-for-port docker-host 27017
$ echo "Mongo is up"

阅读更多

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM