web-dev-qa-db-ja.com

diffコマンドが違いをもたらす場合にのみ電子メールを送信するようにスクリプトを構成するには

私はスクリプトの世界に不慣れで、現在、スクリプトを使用して、管理しているsanデバイスのヘルスチェックを実行しています。

スクリプトは単純で、コマンドの出力をリモートデバイスからローカルホストへの現在のファイルにリダイレクトします。次に、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コマンドとの違いがある場合にのみ電子メールを受け取ります)。しかし、私が今受け取っている電子メールは、テストが1つの長い文字列に連結されているため、表示するのが悪く、受け取る人にとって理解しにくいものです。

私の現在のスクリプトは以下に貼り付けられています:

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行ずつ表示する必要があります。助言がありますか?

1
user46359

問題は、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からの空の出力でさえ、そのコマンドの実行をトリガーします。

では、正しい方法は何ですか?

あなたが本当にやりたいことは、2つのことのうちの1つです。 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

したがって、それ自体が便利なように思えますが、コマンドが正常に実行されたかどうかを判断できます。ただし、これに対処する方法はありません。それでは、論理演算子を見てみましょう。

論理演算子

もう1つの方法は、2つのコマンドを変更して、最初のコマンドが成功した場合に2番目のコマンドが実行されるようにすることです。逆に、最初のコマンドが失敗した場合は、代替演算子を使用して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と同じように真の論理演算子であるため、構造体のタイプには1つの問題があります。これらについては bashpitfallsのWebサイト で読むことができます。

したがって、これは有効なアプローチのようです。しかし、おそらく別の方法があります。読み続けます。

それ以外の場合

3番目の方法は、if/thenブロックを参加させてmailプログラムを実行することです。コマンドが1分前に述べた論理演算子に関連している場合、それらは条件付きと呼ばれます。

注:また、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

出力が1行で表示されるという問題は、\nなどの特殊文字を展開するように指示せずにechoを使用したことが原因でした。例えば:

$ echo "oneline\ntwoline"
oneline\ntwoline

$ echo -e "oneline\ntwoline"
oneline
twoline

私が行ったもう1つの変更は、diffの実行方法にありました。これは機能に悪い影響を与えることはありませんでしたが、バッククォート(\ .. `) has been deprecated in favor of this notation, $(...)`。これらには、コマンドを内部にネストできるという追加の利点があります。次のような他のコマンド:

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

私はここで同じことをしていますが、Subversionで設定を保存しているので、通常のdiffの代わりにsvndiffを実行します。私のコードは:

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