如何从bash / shell脚本评估HTTP响应代码?


203

我有一种感觉,我想念的是显而易见的东西,但是没有成功man [curl|wget]或使用google(“ http”这样一个不好的搜索词)。我正在寻找对频繁出现故障的Web服务器之一的快速修复,返回状态代码500和错误消息。一旦发生这种情况,需要重新启动它。

由于根本原因似乎很难找到,因此我们旨在快速修复,希望这将足以弥合时间,直到我们真正修复它为止(该服务不需要高可用性)

建议的解决方案是创建一个每5分钟运行一次的cron作业,并检查http:// localhost:8080 /。如果返回状态代码500,则将重新启动Web服务器。服务器将在一分钟内重新启动,因此无需检查是否已在运行重新启动。

该服务器是ubuntu 8.04最小安装版本,仅安装了足以运行其当前所需软件包的软件包。在bash中没有执行任务的硬性要求,但是我希望它可以在最小的环境中运行而无需安装更多的解释器。

(我对脚本非常熟悉,因此将http状态代码分配给环境变量的命令/选项就足够了-这就是我一直在寻找并且找不到的东西。)

Answers:


316

我尚未在500代码上对此进行测试,但是它可以在其他代码(例如200、302和404)上运行。

response=$(curl --write-out '%{http_code}' --silent --output /dev/null servername)

请注意,应引用为--write-out提供的格式。如@ibai所建议,添加--head以发出仅H​​EAD请求。由于不会传输页面内容,因此可以在检索成功时节省时间。


1
很好-谢谢:我已经找到--write-out了,但是错过了--output / dev / null。当所有内容都包含在其中时,响应代码会丢失太多信息,所以我根本没有看到它……
Olaf Kock 2010年

4
是否可以将响应代码和输出都存储在单独的变量中?当响应代码不是200时,我想回显输出
Vaibhav Bajpai 2014年

7
@VaibhavBajpai:尝试以下操作:response=$(curl --write-out \\n%{http_code} --silent --output - servername)-结果的最后一行将是响应代码。
暂停,直到另行通知。

2
如果第一个请求的结果为3XX,则不会显示最终请求状态。例如,如果返回的值是301重定向,则此脚本仅在此处停止。如果添加-IL,则可以得到最终状态。如果要显示所有请求的所有HTTP状态,请使用下面的示例。
Siliconrockstar 2015年

工作很好,谢谢!但是,对于我的情况(https),我也需要输入--insecure
Tomasz Racia

42
curl --write-out "%{http_code}\n" --silent --output /dev/null "$URL"

作品。如果不是,则必须按回车键以查看代码本身。


33

我今天需要快速演示一些东西,并提出了这个建议。以为如果有人需要类似于OP要求的东西,我会放在这里。

#!/bin/bash

status_code=$(curl --write-out %{http_code} --silent --output /dev/null www.bbc.co.uk/news)

if [[ "$status_code" -ne 200 ]] ; then
  echo "Site status changed to $status_code" | mail -s "SITE STATUS CHECKER" "my_email@email.com" -r "STATUS_CHECKER"
else
  exit 0
fi

这将在状态从200开始的每个状态更改发送电子邮件警报,因此它很傻并且可能很贪婪。为了改善这一点,我将研究遍历几个状态代码并根据结果执行不同的操作。


20

尽管已接受的响应是一个很好的答案,但它忽略了故障情况。如果请求中有错误或连接失败,curl将返回000

url='http://localhost:8080/'
status=$(curl --head --location --connect-timeout 5 --write-out %{http_code} --silent --output /dev/null ${url})
[[ $status == 500 ]] || [[ $status == 000 ]] && echo restarting ${url} # do start/restart logic

注意:这超出了所请求的500状态检查范围,也可以确认它curl甚至可以连接到服务器(即return 000)。

从中创建一个函数:

failureCode() {
    local url=${1:-http://localhost:8080}
    local code=${2:-500}
    local status=$(curl --head --location --connect-timeout 5 --write-out %{http_code} --silent --output /dev/null ${url})
    [[ $status == ${code} ]] || [[ $status == 000 ]]
}

测试得到500

failureCode http://httpbin.org/status/500 && echo need to restart

测试收到错误/连接失败(例如000):

failureCode http://localhost:77777 && echo need to start

测试未得到500

failureCode http://httpbin.org/status/400 || echo not a failure

9

使用netcat和awk,您可以手动处理服务器响应:

if netcat 127.0.0.1 8080 <<EOF | awk 'NR==1{if ($2 == "500") exit 0; exit 1;}'; then
GET / HTTP/1.1
Host: www.example.com

EOF

    apache2ctl restart;
fi

9

要遵循3XX重定向并为所有请求打印响应代码:

HTTP_STATUS="$(curl -IL --silent example.com | grep HTTP )";    
echo "${HTTP_STATUS}";

grep将捕获它们与“HTTP”的所有行。grep -m 1 HTTP如果是这样的话,也许只抓住第一个匹配项,或者换句话说,通过管道将Awk解析出结果代码。
三胞胎

3

这可以帮助评估http状态

var=`curl -I http://www.example.org 2>/dev/null | head -n 1 | awk -F" " '{print $2}'`
echo http:$var

2
head -n 1 | awk '{stuff}' 是一点反模式,awk 'NR==1 {stuff}'在一个过程中做同样的事情,纯Awk。
三胞胎

3

另一个变化:

       status=$(curl -sS  -I https://www.healthdata.gov/user/login  2> /dev/null | head -n 1 | cut -d' ' -f2)
status_w_desc=$(curl -sS  -I https://www.healthdata.gov/user/login  2> /dev/null | head -n 1 | cut -d' ' -f2-)

2

这是受到nicerobot解决方案启发的冗长而又易于理解的脚本,该脚本仅请求响应标头,并避免使用此处建议的IFS 。当遇到响应> = 400时,它将输出退回消息。此回显可以替换为退回脚本。

# set the url to probe
url='http://localhost:8080'
# use curl to request headers (return sensitive default on timeout: "timeout 500"). Parse the result into an array (avoid settings IFS, instead use read)
read -ra result <<< $(curl -Is --connect-timeout 5 "${url}" || echo "timeout 500")
# status code is second element of array "result"
status=${result[1]}
# if status code is greater than or equal to 400, then output a bounce message (replace this with any bounce script you like)
[ $status -ge 400  ] && echo "bounce at $url with status $status"


1

这是我的实现,比以前的一些答案更详细

curl https://somewhere.com/somepath   \
--silent \
--insecure \
--request POST \
--header "your-curl-may-want-a-header" \
--data @my.input.file \
--output site.output \
--write-out %{http_code} \
  > http.response.code 2> error.messages
errorLevel=$?
httpResponse=$(cat http.response.code)


jq --raw-output 'keys | @csv' site.output | sed 's/"//g' > return.keys
hasErrors=`grep --quiet --invert errors return.keys;echo $?`

if [[ $errorLevel -gt 0 ]] || [[ $hasErrors -gt 0 ]] || [[ "$httpResponse" != "200" ]]; then
  echo -e "Error POSTing https://somewhere.com/somepath with input my.input (errorLevel $errorLevel, http response code $httpResponse)" >> error.messages
  send_exit_message # external function to send error.messages to whoever.
fi

0

要添加到上面的@DennisWilliamson评论中:

@VaibhavBajpai:尝试以下操作:response = $(curl --write-out \ n%{http_code} --silent --output-servername)-结果的最后一行将是响应代码

然后,您可以使用以下类似内容从响应中解析响应代码,其中X可以表示一个正则表达式来标记响应的结尾(此处使用json示例)

X='*\}'
code=$(echo ${response##$X})

请参阅删除子字符串:http : //tldp.org/LDP/abs/html/string-manipulation.html


为什么要将模式放在变量中,为什么要使用无用echo的函数来获得最终值?Just code=${response##*\}}比较简单,可以避免许多常见的陷阱。而且,这是一个全局模式,不是正确的正则表达式。
三胞胎
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.