将脚本配置为仅在 diff 命令给出差异时发送电子邮件

将脚本配置为仅在 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命令存在差异时我才会收到电子邮件)。然而,我现在收到的电子邮件将其测试连接成一长串,这不利于查看,并且对于将要收到它的人来说不容易理解。

我当前的脚本粘贴在下面:

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管道传输到另一个命令的空输出也会触发该命令运行。

那么什么是正确的方法呢?

你真正想做的是两件事之一。要么检查命令的状态diff,要么使用逻辑运算符,例如 and &&(与)或运算符||(或运算符)。

地位

大多数命令在执行时都会返回一个状态。通常用零或一来表示它们运行成功或失败。您可以通过分析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 保存我的配置,所以我做一个 svn diff 而不是普通的 diff。我的代码是:

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

相关内容