如何在Bash中创建一个等待Web服务器响应的循环?

153
如何在bash中创建一个等待Web服务器响应的循环?
每隔10秒左右,它应该打印一个“.”,并等待服务器开始响应。
更新,此代码测试我是否从服务器获得良好的响应。
如果curl --output /dev/null --silent --head --fail "$url"命令返回成功,则显示“URL存在:$url”,否则显示“URL不存在:$url”。

你能更具体地说明你是如何等待服务器响应的吗? - chepner
只要服务器没有回复或者回复的不是200响应,我就认为它还没有准备好。 - sorin
9个回答

251

结合chepner的回答,以下方法适用于我:

until $(curl --output /dev/null --silent --head --fail http://myhost:myport); do
    printf '.'
    sleep 5
done

15
使用反引号 已经过时,应该使用 $( ) 代替。 - Serge Stroobandt
10
允许在放弃之前设置最长等待时间将是一个很棒的扩展。 - tkruse
4
@lexicore,由于这个命令并不需要身体部分,所以我们只请求头部(尽管您可以包括逻辑来检查服务器状态的更多内容)。省略 --head 不会改变任何内容,但如果您想对响应内容进行一些逻辑练习(比如 status.html),那么可以使用该选项。 - Thomas Ferris Nicolaisen
4
我曾遇到一种情况,使用 --head 命令总是返回 405 状态码。我不得不删除该命令才能使其正常工作。 - Ron Harlev
2
顺便提一下,看起来 $() 不被推荐使用,因为它会执行输出。至少我的 IDE 对此发出了警告。如果你删除 $(),它仍然应该正常工作,对吧? - Ferran Maylinch
显示剩余3条评论

66

我想限制最大尝试次数。根据托马斯所接受的答案,我做了这个:

attempt_counter=0
max_attempts=5

until $(curl --output /dev/null --silent --head --fail http://myhost:myport); do
    if [ ${attempt_counter} -eq ${max_attempts} ];then
      echo "Max attempts reached"
      exit 1
    fi

    printf '.'
    attempt_counter=$(($attempt_counter+1))
    sleep 5
done

2
如果由于某些原因请求的链接超时,我建议添加“--max-time 5”。 - Enigo
非常有帮助。我还附上了基于截止日期而不是基于尝试次数的超时版本:deadline=$(date -d "now + 20 seconds" +%Y%m%d%H%M%S) until ls /test; do echo "等待 ${attempts}"; if [[ "$(date -d now +%Y%m%d%H%M%S)" > "${deadline}" ]]; then echo "等待超时"; exit 1; fi; attempts=$(($attempts+1)) sleep 3; done(等待出现 /test 目录的时间为20秒,并每3秒轮询一次)。 - Tomáš Záluský

18

httping 这个工具很不错。 它简单、干净、安静。

while ! httping -qc1 http://myhost:myport ; do sleep 1 ; done

while/until等是个人喜好。


2
转念一想,永远是很长的时间……for i in `seq 60`; do httping -qc1 http://myhost:myport && echo && break sleep 5 echo -n ${i}.. done - Bruce Edge

16
海报提出了有关打印 . 的具体问题,但我认为大多数来到这里的人都在寻找下面的解决方案,因为它只是一个支持有限重试的单个命令。

海报提出了有关打印 . 的具体问题,但我认为大多数来到这里的人都在寻找下面的解决方案,因为它只是一个支持有限重试的单个命令。

curl --head -X GET --retry 5 --retry-connrefused --retry-delay 1 http://myhost:myport

2

使用反引号` `已经过时。

请改用$( )代替:

until $(curl --output /dev/null --silent --head --fail http://myhost:myport); do
  printf '.'
  sleep 5
done

2
以下代码片段:
  • 等待参数中所有URL返回200
  • 如果一个URL无法使用,30秒后过期
  • 一个curl请求超时时间为3秒

将它放入文件中,并像通用脚本一样使用它来等待所需服务可用。

#/bin/bash

##############################################################################################
# Wait for URLs until return HTTP 200
#
# - Just pass as many urls as required to the script - the script will wait for each, one by one
#
# Example: ./wait_for_urls.sh "${MY_VARIABLE}" "http://192.168.56.101:8080"
##############################################################################################

wait-for-url() {
    echo "Testing $1"
    timeout --foreground -s TERM 30s bash -c \
        'while [[ "$(curl -s -o /dev/null -m 3 -L -w ''%{http_code}'' ${0})" != "200" ]];\
        do echo "Waiting for ${0}" && sleep 2;\
        done' ${1}
    echo "${1} - OK!"
}

echo "Wait for URLs: $@"

for var in "$@"; do
    wait-for-url "$var"
done

要点:https://gist.github.com/eisenreich/195ab1f05715ec86e300f75d007d711c

将其更新为 curl -k ... 以测试您的 HTTPS 网站。 - Tomas Trdla

2

您还可以像这样组合timeout和tcp命令。它将在60秒后超时,而不是无限期等待。

timeout 60 bash -c '直到 echo > /dev/tcp/myhost/myport; 做睡眠5; 完成'


1

0
有趣的谜题。如果您的客户端没有访问或异步API,可以尝试像这样搜索您的TCP套接字:
until grep '***IPV4 ADDRESS OF SERVER IN REVERSE HEX***' /proc/net/tcp
do
  printf '.'
  sleep 1
done

但这是一个每秒等待1秒的繁忙等待。您可能需要更高的分辨率。此外,这是全局的。如果另一个连接被建立到该服务器,您的结果将无效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接