원격으로 서버를 지속적으로 테스트하기 위해 쉘 스크립트를 작성하려고 하는데 로그아웃할 때 항상 else 문에서 멈춥니다.

원격으로 서버를 지속적으로 테스트하기 위해 쉘 스크립트를 작성하려고 하는데 로그아웃할 때 항상 else 문에서 멈춥니다.

내 서버를 지속적으로 테스트하고 서버가 다운되면 나에게 이메일을 보내기 위해 여기에 쉘 스크립트를 작성하려고 합니다.

문제는 ssh 연결에서 로그아웃할 때 &명령 끝에서 실행했음에도 불구하고 ./stest01.sh &자동으로 else에 빠지고 다시 로그인하여 종료할 때까지 계속 메일을 보낸다는 것입니다.

#!/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!" [email protected] < sdown.txt ;
        sleep 10 ;
    fi
done

답변1

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

이는 if명령문이 항상 else분기를 취함을 의미합니다.

이것을 설명하기 위해(이것은 아닙니다.정확히현재 상황은 다음과 같습니다. 그러나 grepGNU가 출력을 작성할 수 없는 경우 어떤 일이 발생하는지 보여줍니다.

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

여기에 grep생성된 문자열이 있지만 어디에도 쓸 수 없도록 echo두 출력 스트림을 모두 닫습니다 . grep보시다시피, GNU의 종료 상태는 grep0이 아닌 2입니다.

이는 GNU에만 해당되며 grepBSD grep시스템에서는 동일하게 작동하지 않습니다.

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

이 문제를 해결하려면 스크립트가 출력을 생성하지 않는지 확인하십시오. 를 사용하여 이 작업을 수행할 수 있습니다 exec >/dev/null 2>&1. 또한 우리는 다음에 관심이 있으므로 옵션을 grep사용해야 합니다.-q보다출력( grep전체 파일을 구문 분석할 필요가 없기 때문에 일반적으로 더 빠르지만 이 경우 파일이 작기 때문에 속도 차이가 최소화됩니다).

간단히 말해서:

#!/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!" [email protected] <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!" [email protected]
        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!" [email protected]

1분마다 실행되는 크론 작업(서버가 계속 다운되면 이메일은 1분마다 계속 전송됩니다):

* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" [email protected] )

관련 정보