Bash / shell betiğinden http yanıt kodları nasıl değerlendirilir?


205

Ben bariz eksik hissediyorum ama başarılı değil man [curl|wget]veya google ("http" böyle kötü bir arama terimi yapar) hissediyorum var . Bir hata iletisi ile durum kodu 500 döndürerek, sık başarısız olan web sunucularımızdan birine hızlı ve kirli bir düzeltme arıyorum. Bu olduğunda, yeniden başlatılması gerekir.

Temel nedenin bulunması zor gibi göründüğünden, gerçekten düzeltebileceğimiz zamana köprü kurmanın yeterli olacağını umarak hızlı bir düzeltme hedefliyoruz (hizmetin yüksek kullanılabilirliğe ihtiyacı yoktur)

Önerilen çözüm, http: // localhost: 8080 / 'yi kontrol ederek 5 dakikada bir çalışan bir cron işi oluşturmaktır . Bu durum 500 koduyla geri dönerse, web sunucusu yeniden başlatılır. Sunucu bir dakikadan kısa bir süre içinde yeniden başlatılır, bu nedenle halihazırda çalışmakta olan yeniden başlatmaları kontrol etmeye gerek yoktur.

Söz konusu sunucu, şu anda ihtiyaç duyduğu şeyi çalıştırmak için yeterli paket yüklü ubuntu 8.04 minimum kurulumudur. Görevi bash'da yapmak zor bir gereklilik değildir, ancak daha fazla tercüman yüklemeden bu kadar minimal bir ortamda çalışmasını istiyorum.

(Http durum kodunu bir ortam değişkenine atamak için komut / seçeneklerin yeterli olacağı komut dizisini yeterince tanıyorum - aradığım ve bulamadığım şey bu.)

Yanıtlar:


319

Bunu 500 kodda test etmedim, ancak 200, 302 ve 404 gibi diğerleri üzerinde çalışıyor.

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

Not: --write-out için sağlanan format alıntılanmalıdır. @İbai tarafından önerildiği gibi, --headyalnızca HEAD isteği yapmak için ekleyin . Bu, sayfa içeriği iletilmeyeceğinden, alma işleminin başarılı olduğu zaman kazandırır.


1
Güzel - teşekkürler: --writ-out'u buldum, ancak --output / dev / null özledim. Tüm içerik onunla birlikte geldiğinde, yanıt kodu çok fazla bilgi kayboldu, bu yüzden sadece görmedim ...
Olaf Kock

4
Hem yanıt kodunu hem de çıktıyı ayrı değişkenlerde saklayabilir miyim? Yanıt kodu 200 olmadığında çıktıyı yankılamak istiyorum
Vaibhav Bajpai

7
@VaibhavBajpai: Şunu deneyin: response=$(curl --write-out \\n%{http_code} --silent --output - servername)- sonuçtaki son satır yanıt kodu olacaktır.
sonraki duyuruya kadar duraklatıldı.

2
İlk isteğin sonucu 3XX ise, bu son istek durumunu göstermez. Örneğin, döndürülen değer 301 yönlendirmesi ise, bu komut dosyası orada durur. -IL eklerseniz, son durumu alabilirsiniz. Tüm istekler için tüm HTTP durumlarını göstermek istiyorsanız, aşağıdaki örneğimi kullanın.
siliconrockstar

Harika çalışıyor, teşekkürler! Ancak benim durumumda (https) ben de koymak gerekiyordu --insecure.
Tomasz Racia

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

İşler. Değilse, kodun kendisini görüntülemek için return tuşuna basmanız gerekir.


33

Bugün bir şeyi hızlıca tanıtmam gerekiyordu ve bununla geldim. Birisi OP'nin isteğine benzer bir şeye ihtiyaç duyarsa buraya koyacağımı düşündüm.

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

Bu, 200'den sonraki her eyalet değişikliği için bir e-posta uyarısı gönderecektir, bu yüzden aptal ve potansiyel olarak açgözlüdür. Bunu geliştirmek için, birkaç durum kodu arasında döngü ve sonuca bağlı olarak farklı eylemler gerçekleştirmek bakacağım.


20

Kabul edilen cevap iyi bir cevap olmasına rağmen, başarısızlık senaryolarına bakmaktadır. istekte bir hata varsa veya bir bağlantı hatası varsa curlgeri döner 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

Not: Bu , sunucuya bile bağlanabildiğini (yani geri döndüğünü ) 500doğrulamak için istenen durum kontrolünün biraz ötesine geçer .curl000

Ondan bir işlev oluşturun:

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 ]]
}

Test alma 500:

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

Test alma hatası / bağlantı hatası (örn. 000):

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

Test alamıyor 500:

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

9

Netcat ve awk ile sunucu yanıtını elle işleyebilirsiniz:

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

Tüm talepler için 3XX yönlendirmelerini takip etmek ve yanıt kodlarını yazdırmak:

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

grepOnlarda "HTTP" olan tüm satırları yakalayacaktır. Belki grep -m 1 HTTPde sadece ilk maçı kapmak için, eğer niyet buysa, ya da bunun yerine sadece sonuç kodunu ayrıştırmak için Awk'a yönelin.
Üçlü

3

bu http durumunun değerlendirilmesine yardımcı olabilir

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

3
head -n 1 | awk '{stuff}' biraz antipattern, awk 'NR==1 {stuff}'aynı şeyi tek bir süreçte yapıyor, saf Awk.
Üçlü

3

Başka bir varyasyon:

       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

Burada , sadece yanıt başlıklarını talep eden ve burada önerildiği gibi IFS kullanmaktan kaçınan nicerobot'un çözümünden esinlenen uzun soluklu - ama anlaşılması kolay - komut dosyası geliyor . > = 400 yanıtıyla karşılaştığında bir geri dönme iletisi çıkarır. Bu yankı bir geri dönen komut dosyasıyla değiştirilebilir.

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

2

İşte benim önceki yanıtların bazılarından biraz daha ayrıntılı olan uygulamam

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

Bu uygulama GERÇEKTEN ÇALIŞIR !!! HttpResponseCode'u geri gelen içerikten ayrı tutarsınız!
Eric Manley

1

Ben durumu ile veri karıştırmak burada cevapları beğenmedi. buldum: kıvrımın başarısız olmasını sağlamak için -f bayrağını ekler ve standart durum var: $?

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

Buradaki her senaryo için mükemmel olup olmadığını bilmiyorum, ama ihtiyaçlarıma uygun görünüyor ve bence çalışmak çok daha kolay


0

Yukarıdaki @DennisWilliamson yorumuna eklemek için:

@VaibhavBajpai: Bunu deneyin: response = $ (curl --write-out \ n% {http_code} --silent --output - sunucuadı) - sonuçtaki son satır yanıt kodu olacaktır

Daha sonra, aşağıdaki gibi bir şey kullanarak yanıt kodunu yanıttan ayrıştırabilirsiniz; burada X, yanıtın sonunu işaretlemek için bir normal ifade gösterebilir (burada bir json örneği kullanarak)

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

Bkz. Alt Dizeyi Kaldırma: http://tldp.org/LDP/abs/html/string-manipulation.html


Deseni neden bir değişkene koyuyorsunuz ve neden nihai değeri elde etmek için işe yaramazsınızecho ? Sadece code=${response##*\}}daha basittir ve bir dizi yaygın tuzaktan kaçınır. Ayrıca, bu düzenli bir ifade değil, bir glob paterni.
Üçlü
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.