Evita file PID, cron o qualsiasi altra cosa che tenti di valutare processi che non sono i loro figli.
C'è un ottimo motivo per cui in UNIX puoi SOLO aspettare i tuoi figli. Qualsiasi metodo (analisi ps, pgrep, memorizzazione di un PID, ...) che tenta di aggirare il problema è difettoso e presenta buchi aperti. Di 'solo di no .
È invece necessario che il processo che monitora il processo sia il genitore del processo. Cosa significa questo? Significa che solo il processo che avvia il processo può attendibilmente attenderne la fine. In bash, questo è assolutamente banale.
until myserver; do
echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2
sleep 1
done
Il pezzo sopra di codice bash viene eseguito myserver
in un until
ciclo. La prima riga inizia myserver
e attende che termini. Al termine, until
controlla il suo stato di uscita. Se lo stato di uscita è 0
, significa che è terminato con grazia (il che significa che hai chiesto di chiuderlo in qualche modo, e lo ha fatto con successo). In tal caso non vogliamo riavviarlo (abbiamo appena chiesto di spegnerlo!). Se lo stato di uscita è non 0
, until
verrà eseguito il corpo del ciclo, che emette un messaggio di errore sul STDERR e riavvia il loop (torna alla linea 1) dopo 1 secondo .
Perché aspettiamo un secondo? Perché se qualcosa non va nella sequenza di avvio di myserver
e si blocca immediatamente, avrai un ciclo molto intenso di riavvio e arresto costante nelle tue mani. Il sleep 1
toglie il ceppo da quello.
Ora tutto ciò che devi fare è avviare questo script bash (in modo asincrono, probabilmente), e lo monitorerà myserver
e lo riavvierà secondo necessità. Se vuoi avviare il monitor all'avvio (facendo "sopravvivere" al riavvio del server), puoi programmarlo nel cron (1) del tuo utente con una @reboot
regola. Apri le tue regole cron con crontab
:
crontab -e
Quindi aggiungi una regola per avviare lo script del monitor:
@reboot /usr/local/bin/myservermonitor
In alternativa; guarda inittab (5) e / etc / inittab. Puoi aggiungere una riga lì dentro per myserver
iniziare a un certo livello di init ed essere rigenerato automaticamente.
Modificare.
Vorrei aggiungere alcune informazioni sul perché non utilizzare i file PID. Mentre sono molto popolari; sono anche molto imperfetti e non c'è motivo per non farlo nel modo giusto.
Considera questo:
Riciclo PID (interrompendo il processo sbagliato):
/etc/init.d/foo start
: start foo
, scrivi foo
il PID su/var/run/foo.pid
- Poco dopo:
foo
muore in qualche modo.
- Qualche tempo dopo: qualsiasi processo casuale che inizia (chiamalo
bar
) prende un PID casuale, immagina che prenda foo
il vecchio PID.
- Noti
foo
che non c'è più: /etc/init.d/foo/restart
legge /var/run/foo.pid
, controlla per vedere se è ancora vivo, trova bar
, pensa che lo sia foo
, lo uccide, ne inizia uno nuovo foo
.
I file PID diventano obsoleti. È necessaria una logica troppo complicata (o dovrei dire non banale) per verificare se il file PID è obsoleto e tale logica è nuovamente vulnerabile 1.
.
Cosa succede se non si ha nemmeno accesso in scrittura o ci si trova in un ambiente di sola lettura?
È inutile complicazioni eccessive; guarda quanto è semplice il mio esempio sopra. Non è necessario complicarlo affatto.
Vedi anche: I file PID sono ancora imperfetti quando lo fai "giusto"?
A proposito; anche peggio dei file PID sta analizzando ps
! Non farlo mai.
ps
è molto insostituibile. Mentre lo trovi su quasi tutti i sistemi UNIX; i suoi argomenti variano notevolmente se si desidera un output non standard. E l'output standard è SOLO per il consumo umano, non per l'analisi tramite script!
- L'analisi
ps
porta a MOLTI falsi positivi. Prendi l' ps aux | grep PID
esempio e ora immagina che qualcuno inizi un processo con un numero da qualche parte come argomento che sembra essere lo stesso del PID con cui hai fissato il tuo demone! Immagina due persone che iniziano una sessione X e stai chiedendo a X di uccidere la tua. È solo ogni tipo di male.
Se non vuoi gestire tu stesso il processo; ci sono alcuni sistemi perfettamente validi là fuori che fungeranno da monitor per i tuoi processi. Guarda runit , per esempio.