bash / shellスクリプトからのhttp応答コードを評価する方法は?


203

私は明白なものを欠いていると感じていますが、man [curl|wget]またはgoogleで成功していません(「http」はそのような悪い検索語になります)。エラーメッセージとともにステータスコード500を返すことが多い、頻繁に失敗するウェブサーバーの1つに対する迅速で汚い修正を探しています。これが発生したら、再起動する必要があります。

根本的な原因を見つけるのは難しいようですが、私たちは迅速な修正を目指しており、本当に修正できるまでの時間を埋めるのに十分であることを期待しています(サービスは高可用性を必要としません)

提案された解決策は、5分ごとに実行されるcronジョブを作成し、http:// localhost:8080 /をチェックすることです。これがステータスコード500で戻る場合、Webサーバーが再起動されます。サーバーは1分以内に再起動するため、すでに実行されている再起動を確認する必要はありません。

問題のサーバーは、現在必要なものを実行するのに十分なだけのパッケージがインストールされたubuntu 8.04最小インストールです。bashでタスクを実行するためのハード要件はありませんが、インタープリターをインストールせずに、このような最小限の環境で実行したいです。

(私はスクリプトに精通しているので、httpステータスコードを環境変数に割り当てるコマンド/オプションで十分です-これは私が探していて見つけられなかったものです。)

回答:


316

私はこれを500コードでテストしていませんが、200、302、404などの他のコードでは動作します。

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

--write-outに提供される形式は引用符で囲む必要があることに注意してください。@ibaiで提案され--headているように、HEADのみのリクエストを作成するために追加します。これにより、ページコンテンツが送信されないため、検索が成功したときに時間を節約できます。


1
ニース-ありがとう:--write-outはすでに見つかりましたが、-output / dev / nullがありませんでした。すべてのコンテンツが付属していると、応答コードが多くの情報で失われるため、私はそれを単に表示しませんでした...
Olaf Kock

4
応答コードと出力の両方を別々の変数に格納できますか?応答コードが200でない場合に出力をエコーし​​たい
Vaibhav Bajpai '16年

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"

動作します。そうでない場合は、コードを表示するためにReturnキーを押す必要があります。


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て、サーバーに接続できる(つまり、を返す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に多分代わりの意図、あるいはパイプの場合にのみ、最初の試合をつかみます。
Tripleee 2017年

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}'1つのプロセスで同じことをします。純粋なAwkです。
tripleee 2017年

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

データとステータスを組み合わせるここでの答えは好きではありませんでした。これが見つかりました:-fフラグを追加してcurlを失敗させ、標準のステータス変数からエラーステータスコードを取得します:$?

/unix/204762/return-code-for-curl-used-in-a-command-substitution

ここのすべてのシナリオに最適かどうかはわかりませんが、自分のニーズに合うようで、作業がはるかに簡単だと思います


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##*\}}はより単純で、多くの一般的な落とし穴を回避します。また、これはグロブパターンであり、適切な正規表現ではありません。
tripleee 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.