web-dev-qa-db-fra.com

Comment redémarrer automatiquement un processus d'arrière-plan Linux en cas d'échec?

J'ai un processus qui est exécuté par le script init.d sur le fond. Par exemple:

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

Dans certaines conditions, mon processus peut échouer et revenir. Existe-t-il un moyen (standard) de détecter son échec et de le redémarrer automatiquement?

30
Honza

Le moyen le plus simple serait de l’ajouter à /etc/inittab , conçu pour faire ce genre de chose:

respawn Si le processus n'existe pas, démarrez-le. N'attendez pas sa fin (poursuivez l'analyse du fichier/etc/inittab). Redémarrez le processus quand il meurt. Si le processus existe, ne faites rien et continuez à analyser le fichier/etc/inittab.

Par exemple, vous pouvez faire ceci:

# Run my stuff
myprocess:2345:respawn:/bin/myprocess
14
Alan Shutko

Buildroot a trois systèmes init possibles, il y a donc trois façons de le faire:

BusyBox init

Avec cela, on ajoute une entrée à /etc/inittab.

::respawn:/bin/myprocess

Notez que BusyBox init a un format idiosyncratique /etc/inittab. Le deuxième champ n'a pas de sens et le premier n'est pas un ID mais un nom de base de périphérique.

Linux "System V" init

De nouveau, on ajoute une entrée à /etc/inittab.

myprocess:2345:respawn:/bin/myprocess

systemd

On écrit un fichier unité dans, disons, /etc/systemd/system/myprocess.service:

[Unit]
Description=My Process

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

[Install]
WantedBy=multi-user.target

Activez cette option pour démarrer automatiquement au démarrage avec:

systemctl enable myprocess.service

Démarrez-le manuellement avec:

systemctl start myprocess.service

Lectures complémentaires

25
JdeBP

Qu'en est-il de la création d'un sous-shell avec une boucle qui appelle constamment le même processus?

Si elle se termine, la prochaine itération de la boucle continue et recommence.

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

Si le sous-shell meurt, c'est terminé. La seule possibilité dans ce cas serait de créer un autre processus (je l'appellerai nécromancien) qui vérifie si votre processus est actif, démarrez-le s'il ne l'est pas et exécutez ce nécromancien avec cron afin de pouvoir le vérifier régulièrement.

La prochaine étape serait de se demander ce qui pourrait arriver si Cron meurt, mais à un moment donné, vous devriez vous sentir en sécurité et cesser de vous inquiéter.

22
Trylks

Vous pouvez utiliser Monit . C'est vraiment facile à utiliser et assez flexible. Voir, par exemple, cette configuration pour redémarrer le processus Tomcat en cas d'échec.

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

Il contient également de nombreux exemples de configuration pour de nombreux cas d'utilisation.

3
Clyde D'Cruz

Si vous n'êtes pas un super utilisateur ou un utilisateur root et si Docker est installé sur votre système Linux, vous pouvez créer une image de menu fixe de votre processus, en utilisant docker pour le redémarrer si le système est réinitialisé.

Fichier: 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

Pour démarrer votre conteneur Docker,

docker-compose up -d

Je trouve qu'il est facile de gérer mon propre processus avec le redémarrage automatique si je ne suis pas un super utilisateur du système.

Pour un exemple de création d’une image de menu fixe, voici un exemple rapide:

Fichier: 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"]
1
Michael Qin

Vous pouvez utiliser restarter

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

Sur les nouveaux systèmes, utilisez systemd qui résout tous ces problèmes triviaux.

0
sivann

Dans mon cas, comme solution rapide, j’ai modifié et utilisé la solution de @Trylks pour envelopper le programme que je lançais. Je voulais que ça se termine uniquement en sortie propre.

Devrait courir dans la plupart des coquillages:

#!/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
user1183098