서버를 원격으로 테스트하는 쉘 스크립트를 작성하려고하지만 로그 아웃 할 때 else 문에 계속 빠집니다. 때와 함께 실행하더라도 ./stest01.sh

내 서버를 계속 테스트하고 다운되면 이메일을 보내주는 쉘 스크립트를 작성하려고합니다.

문제는 ssh 연결에서 로그 아웃 할 때와 &같이 명령이 끝날 때와 함께 실행하더라도 ./stest01.sh &자동으로 다른 것으로 떨어지고 다시 로그인하여 죽일 때까지 중단없이 메일을 계속 보낸다는 것입니다.

#!/bin/bash
while true; do
    date > sdown.txt ;
    cp /dev/null pingop.txt ;
    ping -i 1 -c 1 -W 1 myserver.net > pingop.txt &
    sleep 1 ;
    if
        grep "64 bytes" pingop.txt ;
    then
        :
    else
        mutt -s "Server Down!" myemail@address.com < sdown.txt ;
        sleep 10 ;
    fi
done


답변

GNU grep가 결과를 쓰려고하면 SSH 연결이 끊어 졌기 때문에 출력을 쓸 곳이 없기 때문에 0이 아닌 종료 상태로 실패합니다.

이것은 if진술이 항상 else지점을 취하고 있음을 의미합니다 .

이것을 설명하기 위해 (이것은 귀하의 경우에 정확히 일어나지 않지만 GNU grep가 출력을 쓸 수없는 경우 어떻게되는지 보여줍니다 ) :

$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2

여기서 우리 grepecho생성 하는 문자열 이지만 두 출력 스트림을 모두 닫아서 grep어디에도 쓸 수 없도록합니다. 보다시피 GNU의 종료 상태는 grep0이 아니라 2입니다.

이것은 GNU 특히입니다 grep, grep같은 동작하지 않습니다 BSD 시스템에서 :

$ echo 'hello' | grep hello >&- 2>&-    # using BSD grep here
$ echo $?
0

이를 해결하려면 스크립트가 출력을 생성하지 않는지 확인하십시오. 당신은 이것을 할 수 있습니다 exec >/dev/null 2>&1. 또한 출력을 보는 데 전혀 관심이 없기 때문에 옵션 grep과 함께 사용해야 합니다 (일반적으로 전체 파일을 구문 분석 할 필요가 없으므로 속도가 빨라지 지만이 경우에는 매우 작습니다) 파일이 너무 작아서 속도의 차이).-qgrep

한마디로 :

#!/bin/sh

# redirect all output not redirected elsewhere to /dev/null by default:
exec >/dev/null 2>&1

while true; do
    date >sdown.txt

    ping -c 1 -W 1 myserver.net >pingop.txt

    if ! grep -q "64 bytes" pingop.txt; then
        mutt -s "Server Down!" myemail@address.com <sdown.txt
        break
    fi

    sleep 10
done

ping중간 파일 중 하나가 필요하지 않고 직접 날짜 스탬프가 포함 된 다른 중간 파일을 제거하여 직접 테스트를 사용할 수도 있습니다 .

#!/bin/sh

exec >/dev/null 2>&1

while true; do
    if ! ping -q -c 1 -W 1 myserver.net; then
        date | mutt -s "Server Down!" myemail@address.com
        break
    fi

    sleep 10
done

위 스크립트의 두 가지 변형 모두 호스트에 도달하지 못하면 루프를 종료하고 전송되는 전자 메일 수를 최소화합니다. 서버가 결국 다시 나타날 것으로 예상되는 경우 대신 break예를 들어 sleep 10m또는 다른 것으로 바꿀 수 있습니다.

나는 또한 약간에 사용되는 옵션을 쥐게 한 ping으로 -i 1훨씬 이해가되지 않습니다를 -c 1.

더 짧음 (호스트에 연결할 수 없을 때 이메일을 계속 보내지 않으려는 경우 제외) :

#!/bin/sh

exec >/dev/null 2>&1

while ping -q -c 1 -W 1 myserver.net; do
    sleep 10
done

date | mutt -s "Server Down!" myemail@address.com

1 분마다 실행되는 크론 작업 (서버가 다운 된 경우 1 분마다 이메일을 계속 전송 함) :

* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )