Bagaimana cara mengevaluasi kode respons http dari skrip bash / shell?

203

Saya merasa bahwa saya kehilangan yang jelas, tetapi belum berhasil man [curl|wget]atau google ("http" membuat istilah pencarian yang buruk). Saya mencari perbaikan cepat & kotor ke salah satu server web kami yang sering gagal, mengembalikan kode status 500 dengan pesan kesalahan. Setelah ini terjadi, itu harus dimulai ulang.

Karena root root tampaknya sulit ditemukan, kami bertujuan untuk memperbaiki dengan cepat, berharap cukup untuk menjembatani waktu hingga kami benar-benar dapat memperbaikinya (layanan tidak memerlukan ketersediaan tinggi)

Solusi yang diusulkan adalah membuat pekerjaan cron yang berjalan setiap 5 menit, memeriksa http: // localhost: 8080 / . Jika ini kembali dengan kode status 500, server web akan dimulai kembali. Server akan restart dalam waktu kurang dari satu menit, jadi tidak perlu memeriksa untuk me-restart sudah berjalan.

Server yang dimaksud adalah instalasi minimal ubuntu 8.04 dengan hanya cukup paket yang diinstal untuk menjalankan apa yang saat ini dibutuhkan. Tidak ada persyaratan sulit untuk melakukan tugas di bash, tapi saya ingin menjalankannya dalam lingkungan yang minimal tanpa menginstal lebih banyak juru bahasa.

(Saya cukup akrab dengan skrip bahwa perintah / opsi untuk menetapkan kode status http ke variabel lingkungan akan cukup - ini adalah apa yang saya cari dan tidak dapat temukan.)

Olaf Kock
sumber

Jawaban:

316

Saya belum menguji ini pada kode 500, tetapi berfungsi pada orang lain seperti 200, 302 dan 404.

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

Catatan, format yang disediakan untuk --write-out harus dikutip. Seperti yang disarankan oleh @ibai, tambahkan --headuntuk membuat permintaan HEAD only. Ini akan menghemat waktu ketika pengambilan berhasil karena konten halaman tidak akan dikirim.

Dijeda sampai pemberitahuan lebih lanjut.
sumber
1
Bagus - terima kasih: Saya sudah menemukan - menulis-keluar, tetapi melewatkan --output / dev / null. Ketika semua konten datang dengan itu, kode respons hilang dalam terlalu banyak informasi, jadi saya tidak melihatnya ...
Olaf Kock
4
Bisakah saya menyimpan kode respon dan output dalam variabel terpisah? Saya ingin mengulang output ketika kode respon tidak 200
Vaibhav Bajpai
7
@VaibhavBajpai: Coba ini: response=$(curl --write-out \\n%{http_code} --silent --output - servername)- baris terakhir dalam hasilnya adalah kode respons.
Dijeda sampai pemberitahuan lebih lanjut.
2
Ini tidak menunjukkan status permintaan akhir jika hasil dari permintaan pertama adalah 3XX. Misalnya jika nilai yang dikembalikan adalah pengalihan 301, maka skrip ini hanya berhenti di situ. Jika Anda menambahkan -IL, maka Anda bisa mendapatkan status akhir. Jika Anda ingin menampilkan semua status HTTP untuk semua permintaan, gunakan contoh saya di bawah ini.
siliconrockstar
Bekerja dengan baik, terima kasih! Namun dalam kasus saya (https) saya harus meletakkannya --insecurejuga.
Tomasz Racia
42
curl --write-out "%{http_code}\n" --silent --output /dev/null "$URL"

bekerja. Jika tidak, Anda harus menekan kembali untuk melihat kode itu sendiri.

hd1
sumber
33

Saya perlu melakukan demo sesuatu dengan cepat hari ini dan menghasilkan ini. Kupikir aku akan meletakkannya di sini jika seseorang membutuhkan sesuatu yang mirip dengan permintaan 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" "[email protected]" -r "STATUS_CHECKER"
else
  exit 0
fi

Ini akan mengirimkan peringatan email pada setiap perubahan negara bagian dari 200, jadi itu bodoh dan berpotensi rakus. Untuk meningkatkan ini, saya akan melihat perulangan melalui beberapa kode status dan melakukan tindakan berbeda tergantung pada hasilnya.

Chris Gillatt
sumber
20

Meskipun respons yang diterima adalah jawaban yang baik, itu mengabaikan skenario kegagalan. curlakan kembali 000jika ada kesalahan dalam permintaan atau ada kegagalan koneksi.

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

Catatan: ini sedikit melampaui 500pemeriksaan status yang diminta untuk juga mengonfirmasi bahwa curlbahkan dapat terhubung ke server (yaitu mengembalikan000 ).

Buat fungsi dari itu:

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

Tes mendapatkan 500:

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

Tes mendapatkan kesalahan / kegagalan koneksi (yaitu 000):

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

Tes tidak mendapatkan 500:

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

Dengan netcat dan awk Anda dapat menangani respons server secara manual:

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
marco
sumber
9

Untuk mengikuti pengalihan 3XX dan mencetak kode respons untuk semua permintaan:

HTTP_STATUS="$(curl -IL --silent example.com | grep HTTP )";    
echo "${HTTP_STATUS}";
siliconrockstar
sumber
Ini grepakan menangkap semua baris dengan "HTTP" di dalamnya. Mungkin grep -m 1 HTTPhanya untuk merebut pertandingan pertama, jika itu maksudnya, atau mungkin malah mengirim ke Awk untuk menguraikan kode hasil saja.
tripleee
3

ini dapat membantu mengevaluasi status http

var=`curl -I http://www.example.org 2>/dev/null | head -n 1 | awk -F" " '{print $2}'`
echo http:$var
Tango
sumber
2
head -n 1 | awk '{stuff}' adalah sedikit antipattern, awk 'NR==1 {stuff}'melakukan hal yang sama dalam satu proses, Awk murni.
tripleee
3

Variasi lain:

       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-)
dkinzer
sumber
2

Inilah skrip yang bertele-tele - namun mudah dipahami -, terinspirasi oleh solusi nicerobot , yang hanya meminta header respons dan menghindari penggunaan IFS seperti yang disarankan di sini . Ini menampilkan pesan bouncing ketika menemukan respons> = 400. Gema ini dapat diganti dengan skrip bouncing.

# 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"
Thomas Praxl
sumber
1

saya tidak suka jawaban di sini yang mencampur data dengan status. menemukan ini: Anda menambahkan flag -f untuk membuat curl gagal dan mengambil kode status kesalahan dari status standar var: $?

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

Saya tidak tahu apakah itu sempurna untuk setiap skenario di sini, tetapi tampaknya sesuai dengan kebutuhan saya dan saya pikir itu jauh lebih mudah untuk dikerjakan

nathan g
sumber
1

Berikut ini adalah implementasi saya, yang sedikit lebih bertele-tele daripada beberapa jawaban sebelumnya

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
AG6HQ
sumber
0

Untuk menambahkan komentar @DennisWilliamson di atas:

@VaibhavBajpai: Coba ini: response = $ (curl --write-out \ n% {http_code} --silent --output - servername) - baris terakhir pada hasilnya adalah kode respon

Anda kemudian dapat mengurai kode respons dari respons menggunakan sesuatu seperti berikut ini, di mana X dapat menandakan regex untuk menandai akhir respons (menggunakan contoh json di sini)

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

Lihat Penghapusan Substring: http://tldp.org/LDP/abs/html/string-manipulation.html

pengguna1015492
sumber
Mengapa Anda meletakkan pola dalam variabel, dan mengapa Anda menggunakan yang tidak bergunaecho untuk mendapatkan nilai akhir? Hanya code=${response##*\}}lebih sederhana dan menghindari sejumlah perangkap umum. Juga, itu adalah pola gumpalan, bukan ekspresi reguler yang tepat.
tripleee