Perché ottengo un diverso stato di uscita per ps | grep in una sceneggiatura?


11

Sto correndo sotto lo 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

L'output è come ::

[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 eseguo lo stesso nella riga di comando, ricevo lo stato di uscita come 1:

[root@server ~]# ps ax  | grep -q [v]arnish; echo $?
1

Il caso è come se la vernice non fosse installata nel server. Questo script funziona bene in un server in cui è installata la vernice.

Perché un diverso stato di uscita quando eseguito usando script e riga di comando? Come migliorare questo script?


Utilizzare un vero sistema di supervisione dei processi, non questo tipo di pirateria informatica. Il tuo sistema operativo avrà quasi sicuramente un modo integrato per garantire che i tuoi demoni che vuoi mantenere vengano automaticamente riavviati in caso di guasto, sia che si tratti di upstart, daemontools, systemd, launchd o una delle tante, molte altre alternative. Tutti saranno più robusti e capaci di questo tipo di pirateria a mano.
Charles Duffy,

Risposte:


10

Quando si esegue uno script denominato check_varnish_pro.shtest

ps ax  | grep -q [v]arnish

ha esito positivo perché è in esecuzione uno script denominato check_varnish_pro .


14

In generale, è una cattiva idea provare l'approccio semplice pse grepprovare a determinare se un determinato processo è in esecuzione.

Sarebbe molto meglio usare pgrepper questo:

if pgrep "varnish" >/dev/null; then
  echo "Varnish in running"
else
  echo "Varnish is not running"
fi

Vedere il manuale di pgrep. Su alcuni sistemi (probabilmente non su Linux), ottieni un -qflag che corrisponde allo stesso flag per il grepquale elimina la necessità di reindirizzare /dev/null. C'è anche un -fflag che esegue la corrispondenza sulla riga di comando completa anziché solo sul nome del processo. Si può anche limitare la corrispondenza ai processi appartenenti a un utente specifico che utilizza -u.

L'installazione pgrepti dà anche accesso a ciò pkillche ti consente di segnalare i processi in base al loro nome.

Inoltre, se questo è un demone di servizio e se il tuo sistema Unix ha un modo per interrogarlo per informazioni (ad esempio, se è attivo e funzionante o meno), allora questo è il modo corretto di controllarlo.

Su Linux, hai systemctl( systemctl is-active --quiet varnishrestituirà 0 se è in esecuzione, 3 altrimenti), su OpenBSD hai rcctl, ecc.


Ora alla tua sceneggiatura:

Nel tuo script, analizzi l'output di ps ax. Questo output conterrà il nome dello script stesso check_varnish_pro.sh, che ovviamente contiene la stringa varnish. Questo ti dà un falso positivo. Lo avresti notato se lo avessi eseguito senza la -qbandiera grepdurante il test.

#!/bin/bash
ps ax | grep '[v]arnish'

Eseguendolo:

$ ./check_varnish_pro.sh
31004 p1  SN+     0:00.04 /bin/bash ./check_varnish_pro.sh

Un altro problema è che sebbene si provi a "nascondere" il grepprocesso dall'essere rilevato da grepsolo usando [v]nel modello. Questo approccio fallirà se ti capita di eseguire lo script o la riga di comando in una directory in cui è presente un file o una directory varnish(nel qual caso otterrai di nuovo un falso positivo). Questo perché il modello non è quotato e la shell eseguirà il nome del file in esso.

Vedere:

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

La presenza del file varnishfarà sì che la shell si sostituisca [v]arnishcon il nome del file varnishe si otterrà un hit sul modello nella tabella del grepprocesso (il processo).


4
perché tutto è un file "in linux land".
Zee,

@ z_- Non sono sicuro di come sia collegato, ma questo vale anche su Unices non Linux.
Kusalananda

4
Non solo il processo grep; lo script nominato check_varnish_pro.shè anche un fattore.
TNW,

@TNW All'inizio non l'ho notato, ma hai ragione. Lo aggiungerò.
Kusalananda

3

@AlexP spiega in modo molto succinto cosa sta realmente accadendo, ma l'idea di @ Kusalananda di usare pgrep/ pkillper un processo critico è fortemente scoraggiata . Le soluzioni migliori includono:

  • Chiedere al servizio se è in esecuzione. systemctl status varnishddovrebbe occuparsene in una moderna installazione * nix.
  • Se per qualche sfortunata circostanza non disponi di un servizio disponibile, puoi semplicemente modificare lo script di avvio per segnalare il problema non appena il processo termina:

    varnish || true
    some_command_to_send_an_alert_that_the_service_has_died
  • In alternativa, modificare lo script che avvia il servizio per registrare il PID, quindi controllare periodicamente lo stato con kill -0 "$pid".

Sono d'accordo, stavo solo affrontando gli aspetti di shell scripting del problema. Nota che systemctlè quasi disponibile solo su Linux (AFAIK) e non su tutti i moderni sistemi simili a Unix.
Kusalananda

La domanda originale aveva il tag "linux"; Non sono sicuro del motivo per cui è stato rimosso da @muru.
l0b0

Grazie l0b0. Ho avuto due domande "Perché" e "Come migliorare". La risposta di AlexP ha risolto la mia prima domanda e la tua risposta è la soluzione migliore per la seconda domanda. Ma Kusalananda spiega cose relative a questo che penso possano essere utili per le persone che hanno problemi simili. Quindi sono confuso ora quale accettare come risposta.
prado,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.