Para configurar o script para enviar email somente quando o comando diff dá uma diferença

1

Sou novo no mundo dos scripts e atualmente uso um script para executar uma verificação de integridade nos dispositivos san que eu gerencio.

O script é simples e redireciona a saída de comandos para um arquivo atual do dispositivo remoto para o host local. Em seguida, uso um comando diff para comparar a saída do arquivo atual e o arquivo de referência e obter um alerta por e-mail sobre a diferença.

No entanto, o problema que estou enfrentando atualmente é que toda vez que eu executo o script, recebo um e-mail depois que o script é executado, ou seja, mesmo que não haja diferença na comparação, recebo um e-mail em branco do execução de script.

Como isso está relacionado à realização de uma verificação de integridade automatizada, receber um e-mail em branco todos os dias será um incômodo. Existe alguma maneira de ajustar o diff ou adicionar mais algum código para ter certeza de que quando não houver diferença aparecendo a partir do diff, eu não deveria receber um email e só receber um email se houver uma diferença e mostrar a diferença.

script atual

### 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

Por favor, deixe-me saber se qualquer outra informação é necessária.

Obrigado pela ajuda e explicação dos detalhes Slm:)

Até agora, tenho a parte do email funcionando (recebo um email apenas se houver uma diferença do comando diff ). No entanto, o e-mail que agora recebo tem seu teste concatenado em uma longa sequência, que é ruim para a visualização e não é fácil de entender para as pessoas que a receberão.

Meu script atual está colado abaixo:

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

A saída do script acima está em branco e não recebo nenhum email quando o comando diff não encontra nenhuma diferença. No entanto, quando os comandos diff encontram uma diferença, recebo um email colado abaixo:

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

Isto idealmente deve ficar assim no email ..

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

A saída deve exibir uma linha por vez no email. Alguma sugestão?

    
por user46359 03.09.2013 / 02:03

2 respostas

5

O problema é o comando que você está usando para fazer o diff . Toda vez que o comando executar os resultados, se houver uma diferença ou não, será acionado o comando mail .

Exemplo

Aqui vamos simular os 2 arquivos usando 2 echo de comandos como:

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

Isso parece OK, mas o que acontece quando os comandos echo são a mesma coisa?

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

OK, isso não parece ser um problema, ou é? E se nós enviarmos a saída do comando diff para dizer outro comando echo :

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

Veja que mesmo a saída vazia de diff piped para outro comando ativará esse comando para execução.

Então, qual é o caminho certo?

O que você realmente quer fazer é uma das duas coisas. Verifique o status do comando diff ou use um operador lógico como && (e) ou o operador || (ou operador).

Status

A maioria dos comandos, quando executados, retorna um status. Normalmente, um zero ou um para denotar que eles foram executados com sucesso ou falharam. Você pode ver o status de diff analisando a variável de status $? no Bash.

diff retorna 0 se os arquivos corresponderem

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

diff retorna um 1 se os arquivos não corresponderem

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

$ echo $?
1

Então, por si só, parece útil, podemos dizer se um comando foi executado com sucesso ou não. No entanto, não temos como agir sobre isso. Então, vamos ver os operadores lógicos.

Operador lógico

O outro método é alterar 2 comandos para que, se o primeiro for bem-sucedido, o segundo seja executado. Por outro lado, você pode usar o operador alternativo para executar um segundo comando, se o primeiro falhar.

Exemplo

pragma diferente

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

mesmo pragma

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

OBSERVAÇÃO: Alguns cuidados devem ser usados se você usar esse método. Há um problema com o tipo de estrutura, porque os acima são verdadeiros operadores lógicos da mesma maneira que um if .. then .. else é. Você pode ler sobre isso no site de bashpitfalls .

Portanto, esta parece ser uma abordagem válida. Mas talvez haja outro caminho. Continue lendo.

Se então mais

Um terceiro método seria inscrever um bloco se / então para executar o programa mail . Se / então os comandos estiverem relacionados aos operadores lógicos que mencionei há um minuto, eles são chamados de condicionais.

NOTA: Também diff não é a melhor ferramenta para uso em declarações if / then. É melhor usar o comando cmp , que pode retornar apenas um status e nada mais. Então, vamos atualizar isso agora também.

Exemplo

mesmo

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

diferente

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

Estender isso para um bloco se / então seria algo como isto:

$ 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

Seu problema

Você poderia fazer algo assim para o seu problema original:

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

UPDATE # 1

Ao analisar seu script atualizado, você precisa fazer as seguintes modificações:

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

Os problemas que você estava enfrentando com a saída aparecendo como uma única linha foram causados pelo uso de echo sem avisar para expandir caracteres especiais, como \n . Por exemplo:

$ echo "oneline\ntwoline"
oneline\ntwoline

$ echo -e "oneline\ntwoline"
oneline
twoline

Uma outra modificação que fiz foi na forma como você executou o diff . Isso não afetou sua funcionalidade de maneira ruim, mas os backticks ( \ .. ' ) has been deprecated in favor of this notation, $ (...)'. Eles têm o benefício adicional de poder aninhar comandos dentro de outros comandos, como :

$ myvar=$(echo "good + $(echo bye)")
$ echo $myvar
good + bye
    
por 03.09.2013 / 03:12
0

Eu estou fazendo a mesma coisa aqui, mas eu salvo minha configuração com o subversion, então eu faço um svn diff em vez de um diff normal. Meu código é:

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

Espero que ajude.

Atenciosamente, Alex

    
por 16.11.2014 / 14:53