当管道卷曲到 grep 时如何处理服务器关闭

how to handle server being down when piping curl to grep

我正在尝试编写一个脚本来查询 Web 服务器 API 并检查一个值,但我在尝试弄清楚如何最好地处理它时遇到了麻烦。到目前为止,我正在做的是使用 curl 获得响应,然后将其通过管道传递给 grep 以寻找模式。如果模式存在,我做一件事,如果不存在,我做另一件事。

if curl http://192.168.1.2:8080/api/query | grep -q mypattern; then
    echo "success"
    else echo "boo"
fi

但是如果服务器宕机,我不知道如何巧妙地处理它,因为服务器宕机产生的结果与找不到模式相同。我想要发生的是让 curl 继续发出请求,直到服务器响应,然后 grep 结果。我知道我可能会做到,但会非常笨拙。一个想法是首先循环 curl 直到退出代码为 0,但我确信有一种更实用的方法。有什么想法吗?

试试这个:

#!/bin/bash

n=5              # number of times to try.

testserver(){
    read server mypattern <<<"$@"   # read values of server and pattern
    try=1                           # lets start with try number 1.

    while (( try++ < n )); do       # have tried enough times?
        test="$(curl --max-time 10 "$server" 2>/dev/null)"
        (( $? == 0 )) &&            # If the connection was valid.
        [[ "$test" =~ "$mypattern" ]] && echo "success" && break 1
        sleep 5m                    # wait a little before trying again.
    done
}

testserver "http://192.168.1.2:8080/api/query" "SomeStringToTest"

这看起来不太笨:

if while ! curl http://192.168.1.2:8080/api/query; do sleep 1; done | 
    grep -q mypattern; then
    echo "success"
fi

您可能想限制调用 curl 的次数。你可以用类似的东西来做到这一点:

i=0; if while test $((i++)) -lt 4 && ! curl ...

可以使用 $PIPESTATUS:

#!/bin/bash
if curl http://192.168.1.2/api/query | grep -q mypattern; then
  echo "Found pattern"
elif [ "${PIPESTATUS[0]}" -eq 0 ]; then
  echo "Server up"
else
  echo "Server down"
fi

curl 具有内置超时状态,具有专用退出代码 (28)。

来自文档:

--connect-timeout <seconds>
              Maximum time in seconds that  you  allow  curl's  connection  to
              take.   This  only  limits the connection phase, so if curl con-
              nects within the given period it will continue - if not it  will
              exit.  Since version 7.32.0, this option accepts decimal values.

.....

28     Operation  timeout.  The  specified  time-out period was reached
              according to the conditions.

所以你可以像这样编写主循环脚本:

#!/bin/bash
#mypattern.sh example

query=""
mypattern=""
dogrep () {

if (grep -q "$mypattern" /tmp/result); 
    then 
        echo "success"
    else
        echo "boo"
fi
}

curl -s --connect-timeout 5 "$query" -o /tmp/result    

curlresult="$?"

case "$curlresult" in
"0") dogrep ; exit ;;
"28") echo "Could not connect to server" ; exit ;;
*) echo "something else went wrong" ; exit ;;
esac
  • </code> 是 API URL</li> <li><code>是模式

示例结果:

bash: >./mypattern.sh "http://google.com" "The document has moved"
success

bash: >./mypattern.sh "http://google.com" "The document has movde"
boo

bash: >./mypattern.sh "http://fjbdjhf" "The document has moved"
something else went wrong

bash: >./mypattern.sh "http://real.server.address.that.is.down" "The document has moved"
Could not connect to server

在上面:

  • 示例1:连接成功,模式匹配成功
  • 示例 2:连接成功,但没有模式匹配
  • 示例 3:甚至不是真正的服务器,这是例外情况
  • 示例4:真实服务器,但无法连接,5秒后超时

我相信如果您调整服务器停机的条件,这可以在某种程度上更符合您的特定要求。

  • 在这个例子中: “server being down”表示主机解析为真实地址,连接尝试在 5 秒内未被拒绝。
    • 如果这是 Internet 上的 API 地址,那么对那里的 ISP 网关进行简单的 ping 检查以验证与 Internet 的一般连接性,再加上 5 秒超时将相当准确地覆盖服务器正在有效下降。
    • 在您的情况下,在 LAN 上,您必须弄清楚什么确切条件意味着服务器已关闭,但此模板将各个部分分解得足以使很容易适应这些不同的因素。
while ! CURL_OUT="$(curl http://192.168.1.2:8080/api/query)"; do
    sleep 5
done
if echo "$CURL_OUT" | grep -q mypattern ; then
    echo "success"
else 
    echo "boo"
fi