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?
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
Buildroot a trois systèmes init possibles, il y a donc trois façons de le faire:
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.
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
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.
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.
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"]
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.
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) &