diff 명령이 diff를 제공할 때만 이메일을 보내도록 스크립트를 구성하십시오.

diff 명령이 diff를 제공할 때만 이메일을 보내도록 스크립트를 구성하십시오.

저는 스크립팅 세계가 처음이고 현재 제가 관리하는 SAN 장치에서 상태 검사를 수행하기 위해 스크립트를 사용하고 있습니다.

스크립트는 간단하며 원격 장치의 명령 출력을 현재 파일의 로컬 호스트로 리디렉션합니다. 그런 다음 diff 명령을 사용하여 현재 파일과 참조 파일의 출력을 비교하고 차이점에 대한 이메일 알림을 받습니다.

그런데 현재 제가 겪고 있는 문제는 스크립트를 실행할 때마다 스크립트 실행 후 이메일이 온다, 즉 비교 결과에 차이가 없는데도 스크립트 실행 시 빈 이메일이 뜬다는 것입니다.

이는 자동화된 상태 확인을 수행하는 것과 관련이 있기 때문에 매일 빈 이메일을 받는 것은 번거로울 수 있습니다. diff에 diff가 표시되지 않고 diff가 있고 diff가 표시되는 경우에만 이메일을 받지 않도록 diff를 조정하거나 더 많은 코드를 추가할 수 있는 방법이 있습니까?

현재 스크립트

### saves output of command switchshow in a file on local host
ssh user@ip_of_switch switchshow > switchshow_results

### Compares current output to reference file and mails the difference
diff switchshow_reference switchshow_results \
    | mail -s device_PORT_ERROR email_recipient

추가 정보가 필요한 경우 알려주시기 바랍니다.


도움과 자세한 설명에 감사드립니다 Slm :)

지금까지 이메일 부분이 작동하고 있습니다( diff명령과 차이가 있을 때만 이메일을 받습니다). 그러나 지금 내가 받는 이메일에는 테스트가 하나의 긴 문자열로 연결되어 있어 보기에도 좋지 않고, 받는 사람도 이해하기 쉽지 않습니다.

내 현재 스크립트는 아래에 붙여넣어졌습니다.

ssh test@ip_of_device switchshow > switchshow_results

variable=`diff switchshow_reference switchshow_results`

if [[ $variable -eq 0 ]]    
then    
  echo $"nothing"    
else    
  echo $variable | mail -s switch_HARDWARE_CHECK  recipeint_email_address    
fi

위 스크립트의 출력은 비어 있으며 diff명령에서 차이점을 찾지 못하면 이메일을 받지 못합니다. 그러나 diff명령이 차이점을 발견하면 아래에 붙여넣은 이메일을 받게 됩니다.

16c16 < 0 0 010000 id N4 Online FC F-Port 1 N Port + 1 NPIV public --- > 0 0 010000 id N4 No_Light FC F-Port 1 N Port + 1 NPIV public 26c26 < 10 10 010a00 id N4 Online FC F-Port 1 N Port + 1 NPIV public --- > 10 10 010a00 id N4 No_Light FC F-Port 1 N Port + 1 NPIV public 29c29 < 13 13 010d00 id N4 Online FC F-Port 50:06:01:67:3b:20:23:0a --- > 13 13 010d00 id N4 No_Light FC F-Port 50:06:01:67:3b:20:23:0a

이상적으로는 이메일에서 다음과 같이 표시되어야 합니다.

16c16 < 0 0 010000 id N4 Online FC F-Port 1 N Port + 1 NPIV public --- > 0 0 010000 id N4 No_Light FC F-Port 1 N Port + 1 NPIV public 

26c26 < 10 10 010a00 id N4 Online FC F-Port 1 N Port + 1 NPIV public --- > 10 10 010a00 id N4 No_Light FC F-Port 1 N Port + 1 NPIV public

29c29 < 13 13 010d00 id N4 Online FC F-Port 50:06:01:67:3b:20:23:0a --- > 13 13 010d00 id N4 No_Light FC F-Port 50:06:01:67:3b:20:23:0a

출력은 이메일에서 한 번에 한 줄씩 표시되어야 합니다. 어떤 제안이 있으십니까?

답변1

문제는 실행하는 데 사용하는 명령입니다 diff. 이 mail명령은 차이가 있는지 여부에 관계없이 결과를 실행할 때마다 트리거됩니다.

여기서는 2개의 echo명령을 사용하여 다음과 같이 2개의 파일을 시뮬레이션합니다.

$ diff <(echo 1) <(echo 2)
1c1
< 1
---
> 2

괜찮아 보이지만 echo명령이 동일하면 어떻게 될까요?

$ diff <(echo 1) <(echo 1)
$ 

글쎄요, 그건 문제가 아닌 것 같군요, 그렇죠? 명령의 출력을 diff다른 명령으로 파이프하면 echo어떻게 되나요 ?

$ diff <(echo 1) <(echo 1) | echo "hi"
hi

diff파이프에서 다른 명령으로의 빈 출력 이라도 해당 명령이 실행되도록 트리거합니다.

그렇다면 올바른 접근 방식은 무엇입니까?

당신이 정말로 하고 싶은 일은 두 가지 중 하나입니다. 명령의 상태를 확인하거나 and (and) 또는 연산자 (또는 연산자) diff와 같은 논리 연산자를 사용하십시오 .&&||

상태

대부분의 명령은 실행 시 상태를 반환합니다. 일반적으로 0 또는 1은 작업의 성공 또는 실패를 나타내는 데 사용됩니다. Bash에서 상태 변수를 분석하여 diff상태를 볼 수 있습니다.$?

diff파일이 일치하면 0을 반환합니다.

$ diff <(echo 1) <(echo 1)
$ echo $?
0

diff파일이 일치하지 않으면 1을 반환합니다.

$ diff <(echo 1) <(echo 2)
1c1
< 1
---
> 2

$ echo $?
1

따라서 그 자체로는 유용해 보이며 명령이 성공적으로 실행되었는지 알 수 있습니다. 하지만 우리가 그것에 대해 아무것도 할 수 있는 방법이 없습니다. 그럼 논리연산자를 살펴보겠습니다.

논리 연산자

또 다른 접근 방식은 첫 번째 명령이 성공하면 두 번째 명령이 실행되도록 2개의 명령을 변경하는 것입니다. 대신 첫 번째 명령이 실패할 경우 대체 연산자를 사용하여 두 번째 명령을 실행할 수 있습니다.

다양한 화용론

$ diff <(echo 1) <(echo 2) || echo "they're different"
1c1
< 1
---
> 2
they're different

같은 프라그마

$ diff <(echo 1) <(echo 1) && echo "they're the same"
they're the same

노트:이 방법을 사용하는 경우 주의하세요. 위의 내용은 실제로는 if .. then .. else 와 같은 논리 연산자이기 때문에 구조체 유형에 문제가 있습니다. 당신은 할 수 있습니다bashpitfalls 웹 사이트.

따라서 이것은 유효한 접근 방식인 것 같습니다. 하지만 어쩌면 다른 방법이 있을 수도 있습니다. 계속 읽으십시오.

그렇다면 그렇지 않으면

세 번째 방법은 if/then 블록을 사용하여 프로그램을 실행하는 것입니다 mail. if/then 명령은 방금 언급한 논리 연산자와 관련되어 있으며 조건문이라고 합니다.

노트:그리고 diff실제로 if/then 문을 위한 최고의 도구는 아닙니다. cmp상태만 반환하는 명령을 사용하는 것이 좋습니다 . 그럼 이제 업그레이드도 해보자.

동일한

$ cmp -s <(echo 1) <(echo 1)
$ echo $?
0

다른

$ cmp -s <(echo 2) <(echo 1)
$ echo $?
1

이것을 if/then 블록으로 확장하면 다음과 같습니다:

$ if cmp -s <(echo 2) <(echo 1);then echo "same"; else echo "different";fi
different

$ if cmp -s <(echo 1) <(echo 1);then echo "same"; else echo "different";fi
same

너의 문제

그런 다음 원래 질문에 대해 다음과 같이 할 수 있습니다.

if cmp -s switchshow_reference switchshow_results; then
  diff switchshow_reference switchshow_results \
     | mail -s device_PORT_ERROR email_recipient
fi

업데이트 #1

업데이트된 스크립트를 볼 때 다음과 같이 수정해야 합니다.

ssh test@ip_of_device switchshow > switchshow_results

variable=$(diff switchshow_reference switchshow_results)

if [[ $variable -eq 0 ]]    
then    
  echo $"nothing"
else    
  echo -n "$variable" | mail -s switch_HARDWARE_CHECK  recipeint_email_address

fi

출력이 한 줄로 나타나는 문제는 echo특수 문자를 확장하지 않고 사용했기 때문입니다 \n. 예를 들면 다음과 같습니다.

$ echo "oneline\ntwoline"
oneline\ntwoline

$ echo -e "oneline\ntwoline"
oneline
twoline

내가 수정한 또 다른 방법은 diff기능에 나쁜 영향을 미치지는 않지만 백틱( \..` ) has been deprecated in favor of this notation,$(...)` 입니다. 이러한 기능은 다른 명령 내에 명령을 중첩할 수 있는 기능이 있습니다. 처럼:

$ myvar=$(echo "good + $(echo bye)")
$ echo $myvar
good + bye

답변2

여기서도 같은 일을 하고 있지만 구성을 저장하기 위해 Subversion을 사용하고 있으므로 일반 diff 대신 svn diff를 수행합니다. 내 코드는 다음과 같습니다

diff=$(svn di)
if [ -n "$diff" ]
then
        svn di | mail -s subject recipient
fi

관련 정보