Quando você executa um script chamado check_varnish_pro.sh
the test
ps ax | grep -q [v]arnish
é bem-sucedido porque há um script chamado check_
verniz _pro
em execução.
Estou correndo abaixo do script:
#!/bin/bash
ps ax | grep -q [v]arnish
if [ $? -eq 0 ];then
echo varnish is running...
exit 0
else
echo "Critical : varnish is not running "
exit 2
fi
A saída é como:
[root@server ~]# sh -x check_varnish_pro.sh
+ ps ax
+ grep -q '[v]arnish'
+ '[' 0 -eq 0 ']'
+ echo varnish is running...
varnish is running...
+ exit 0
Quando eu executo o mesmo na linha de comando, estou recebendo o status de saída como 1:
[root@server ~]# ps ax | grep -q [v]arnish; echo $?
1
O caso é como o verniz não está instalado no servidor. Este script funciona bem em um servidor onde o verniz está instalado.
Por que status de saída diferente quando executado usando script e linha de comando? Como melhorar este script?
Em geral, é uma má ideia tentar a abordagem simples com ps
e grep
para tentar determinar se um determinado processo está sendo executado.
Você seria muito melhor usar pgrep
para isso:
if pgrep "varnish" >/dev/null; then
echo "Varnish in running"
else
echo "Varnish is not running"
fi
Consulte o manual para pgrep
. Em alguns sistemas (provavelmente não no Linux), você obtém um sinal -q
que corresponde ao mesmo sinalizador para grep
, o que elimina a necessidade de redirecionar para /dev/null
. Há também um sinalizador -f
que executa a correspondência na linha de comando completa em vez de apenas no nome do processo. Também é possível limitar a correspondência a processos pertencentes a um usuário específico usando -u
.
A instalação de pgrep
também oferece acesso a pkill
, que permite sinalizar processos com base em seus nomes.
Além disso, se este é um daemon de serviço , e se o seu sistema Unix tiver uma maneira de consultá-lo para obter informações (por exemplo, se ele está ativo ou não), então esse é o > adequada forma de verificar.
No Linux, você tem systemctl
( systemctl is-active --quiet varnish
retornará 0 se estiver em execução, 3 caso contrário), no OpenBSD você terá rcctl
, etc.
Agora, para o seu script:
No seu script, você analisa a saída de ps ax
. Essa saída conterá o nome do próprio script, check_varnish_pro.sh
, que obviamente contém a string varnish
. Isso lhe dá um falso positivo. Você teria percebido isso se tivesse executado sem o sinal -q
para grep
durante o teste.
#!/bin/bash
ps ax | grep '[v]arnish'
Executando:
$ ./check_varnish_pro.sh
31004 p1 SN+ 0:00.04 /bin/bash ./check_varnish_pro.sh
Outra questão é que, embora você tente "ocultar" o processo grep
de ser detectado pelo próprio grep
usando [v]
no padrão. Essa abordagem falhará se você executar o script ou a linha de comando em um diretório que tenha um arquivo ou diretório denominado varnish
(nesse caso, você obterá um falso positivo novamente). Isso ocorre porque o padrão é sem aspas e o shell executará a globalização do nome de arquivo com ele.
Veja:
bash-4.4$ set -x
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep '[v]arnish'
bash-4.4$ touch varnish
+ touch varnish
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep varnish
91829 p2 SN+p 0:00.02 grep varnish
A presença do arquivo varnish
fará com que o shell substitua [v]arnish
pelo nome do arquivo varnish
e você obtenha um hit no padrão na tabela de processos (o processo grep
).
@AlexP explica muito sucintamente o que realmente está acontecendo, mas a ideia da @ Kusalananda de usar pgrep
/ pkill
para um processo crítico é strongmente desencorajado . Melhor soluções incluem:
systemctl status varnishd
deve cuidar disso em uma instalação moderna * nix. Se por alguma circunstância infeliz você não tiver um serviço disponível, basta alterar o script de inicialização para relatar o problema assim que o processo terminar:
varnish || true
some_command_to_send_an_alert_that_the_service_has_died
kill -0 "$pid"
.