bash / shell 스크립트에서 http 응답 코드를 평가하는 방법은 무엇입니까?


203

나는 명백한 것을 놓치고 있지만 man [curl|wget]Google에 성공하지 못했다는 느낌을 가지고 있습니다 ( "http"는 그러한 나쁜 검색어를 만듭니다). 자주 실패하는 웹 서버 중 하나에 대한 빠른 수정 프로그램을 찾고 있는데 오류 메시지와 함께 상태 코드 500을 반환합니다. 이 문제가 발생하면 다시 시작해야합니다.

근본 원인을 찾기 어려워 보이는 것처럼, 우리는 빠른 수정을 목표로하고 있습니다. 실제로 해결할 수있을 때까지 시간을 연결하기에 충분할 것으로 기대합니다 (서비스에는 고 가용성이 필요하지 않음)

제안 된 솔루션은 5 분마다 실행되는 cron 작업을 작성하여 http : // localhost : 8080 /을 확인하는 것 입니다. 상태 코드 500과 함께 반환되면 웹 서버가 다시 시작됩니다. 1 분 안에 서버가 다시 시작되므로 이미 실행중인 다시 시작을 확인할 필요가 없습니다.

문제의 서버는 현재 필요한 것을 실행하기에 충분한 패키지가 설치된 우분투 8.04 최소 설치입니다. bash에서 작업을 수행하는 데 필요한 요구 사항은 없지만 더 이상 인터프리터를 설치하지 않고도 최소한의 환경에서 실행하고 싶습니다.

(환경 변수에 http 상태 코드를 할당하는 명령 / 옵션이면 충분하다는 스크립팅에 충분히 익숙합니다. 이것은 내가 찾았고 찾을 수 없었습니다.)

답변:


316

나는 이것을 500 코드에서 테스트하지는 않았지만 200, 302 및 404와 같은 다른 코드에서는 작동합니다.

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

--write-out에 제공된 형식은 따옴표로 묶어야합니다. @ibai가 제안한대로 --headHEAD 전용 요청을 추가하십시오 . 페이지 내용이 전송되지 않기 때문에 검색이 성공할 때 시간이 절약됩니다.


1
좋았습니다-고맙습니다 : 이미 --write-out을 찾았지만 --output / dev / null을 놓쳤습니다. 모든 내용이 들어 왔을 때 응답 코드가 너무 많은 정보를 잃어 버렸기 때문에 나는 그것을 보지 못했습니다 ...
Olaf Kock

4
응답 코드와 출력을 별도의 변수에 저장할 수 있습니까? 응답 코드가 200이 아닐 때 출력을 에코하고 싶습니다
Vaibhav Bajpai

7
@ VaibhavBajpai : 이것을 시도하십시오 : response=$(curl --write-out \\n%{http_code} --silent --output - servername)-결과의 마지막 줄은 응답 코드입니다.
추후 공지가있을 때까지 일시 중지되었습니다.

2
첫 번째 요청의 결과가 3XX 인 경우 최종 요청 상태가 표시되지 않습니다. 예를 들어 반환 된 값이 301 리디렉션 인 경우이 스크립트는 여기서 중지합니다. -IL을 추가하면 최종 상태를 얻을 수 있습니다. 모든 요청에 ​​대한 모든 HTTP 상태를 표시하려면 아래 예제를 사용하십시오.
siliconrockstar

감사합니다! 그러나 내 경우에는 (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

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.
tripleee

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이 실패하고 표준 상태 var에서 오류 상태 코드를 가져옵니다. $?

/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 것을 사용하여 최종 값을 얻습니까? 그냥은 code=${response##*\}}간단하고 일반적인 함정의 숫자를 방지 할 수 있습니다. 또한 이것은 적절한 정규 표현식이 아닌 glob 패턴입니다.
tripleee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.