Come riavviare automaticamente un processo in background di Linux se fallisce?


32

Ho un processo che viene eseguito dallo script init.d in background. Per esempio:

case "$1" in 
    start)
       /bin/myprocess &
    stop)
       killall myprocess
    restart)
       killall myprocess
       /bin/myprocess &
esac

In determinate condizioni, il processo multiplo può non riuscire e tornare. Esiste un modo (standard) per rilevarne l'errore e riavviarlo automaticamente?


Certo, ma varia in base alla distribuzione. Praticamente tutti forniscono una sorta di service manager.
David Schwartz,

Non esiste una distribuzione standard, ma buildroot. Quindi devo farlo manualmente ...
Honza,

Risposte:


14

Il modo più semplice sarebbe aggiungerlo a / etc / inittab , che è progettato per fare questo genere di cose:

respawn Se il processo non esiste, avvia il processo. Non attendere la sua conclusione (continua la scansione del file / etc / inittab). Riavvia il processo quando muore. Se il processo esiste, non eseguire alcuna operazione e continuare la scansione del file / etc / inittab.

Ad esempio, potresti farlo:

# Run my stuff
myprocess:2345:respawn:/bin/myprocess

Nota, /etc/inittabfunziona (o addirittura esiste) se e solo se hai un sistema init basato su sysvinit. Con upstart e con systemd non funziona. Devi installare sia busybox (shell molto primitiva che rende doloroso il ripristino di compiti sysadm, ma può sostituire un initd compatibile con sysvinit) o sysvinit (è un fossile). In un contenitore docker, solo il primo non è doloroso.
Peter dice di reintegrare Monica il

27

Buildroot ha tre possibili sistemi init, quindi ci sono tre modi per farlo:

BusyBox init

Con questo, si aggiunge una voce a /etc/inittab.

::respawn:/bin/myprocess

Si noti che BusyBox initha un /etc/inittabformato idiosincratico . Il secondo campo è privo di significato e il primo campo non è un ID ma un nome di base del dispositivo.

Linux "Sistema V" init

Ancora una volta, si aggiunge una voce a /etc/inittab.

myprocess:2345:respawn:/bin/myprocess

systemd

Uno scrive un file unitario, per esempio /etc/systemd/system/myprocess.service:

[Unit]
Description=My Process

[Service]
ExecStart=/bin/myprocess
Restart=always

[Install]
WantedBy=multi-user.target

Abilita questo per l'avvio automatico all'avvio con:

systemctl enable myprocess.service

Avvialo manualmente con:

systemctl start myprocess.service

Ulteriori letture


ma quando usi questo approccio inittab, il tuo processo non è più accessibile tramite l'interfaccia "di servizio", giusto? cioè non puoi andare service mything starto service mything stoppiù .... c'è un modo per avere il meglio di entrambi? vale a dire un servizio sysvinit non cancellabile, ma è anche utilizzabile tramite 'servizio'?
Horseyguy,

25

Che dire della creazione di una subshell con un ciclo che chiama costantemente lo stesso processo?

Se termina, la successiva iterazione del ciclo continua e lo riavvia.

(while true; do 
    /bin/myprocess
done) &

Se la subshell muore, è finita però. L'unica possibilità in quel caso sarebbe quella di creare un altro processo (lo chiamerò negromante) che controlla se il tuo processo è vivo, avviarlo in caso contrario ed esegui questo negromante con cron, in modo da poterlo controllare regolarmente.

Il prossimo passo sarebbe chiedersi cosa potrebbe succedere se cron morisse, ma ad un certo punto dovresti sentirti al sicuro e smettere di preoccuparti.


3

Puoi usare Monit . È davvero facile da usare e abbastanza flessibile. Vedere ad esempio questa configurazione per riavviare il processo Tomcat in caso di errore.

check process tomcat with pidfile /var/run/tomcat.pid
   start program = "/etc/init.d/tomcat start"
   stop  program = "/etc/init.d/tomcat stop"
   if failed port 8080 type tcp then restart

Ha anche molti esempi di configurazione per molti casi d'uso.


1

Se non sei un super utente o root e se il tuo sistema Linux ha Docker installato, puoi creare un'immagine docker del tuo processo, usando docker per riavviare il processo se il sistema viene riavviato.

File: docker-compose.yml

version: "3"
services:
  lserver:
    image: your_docker_image:latest
    ports:
    - 8080:8080   # just use 8080 as an example
    restart: always  # this is where your process can be guaranteed to restart

Per avviare il contenitore della finestra mobile,

docker-compose up -d

Trovo che sia facile gestire il mio processo con il riavvio automatico se non sono un superutente del sistema.

Per un esempio di come creare un'immagine docker, ecco un esempio veloce:

File: Dockerfile

FROM alpine:3.5

RUN apk update && apk upgrade && rm -rf /var/cache/apk/*
WORKDIR /app
COPY my-process-server /app
RUN ln -s /app/my-process-server /usr/local/bin/my-process-server

EXPOSE 8080

CMD ["my-process-server"]

0

Nel mio caso, come soluzione rapida, ho modificato e usato la soluzione di @ Trylks per completare il programma che stavo lanciando. Volevo che finisse solo con un'uscita pulita.

Dovrebbe funzionare nella maggior parte delle shell:

#!/bin/sh

echo ""
echo "Use: $0 ./program"
echo ""

#eg="/usr/bin/apt update"

echo "Executing $1 ..."

EXIT_CODE=1
(while [ $EXIT_CODE -gt 0 ]; do
    $1
    # loops on error code: greater-than 0
    EXIT_CODE=$?
done) &

0

È possibile utilizzare il riavvio

start)
   restarter -c /bin/myprocess &
stop)
   pkill -f myprocess

Sui sistemi più recenti usa systemd che risolve tutti quei problemi banali

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.