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.