Wie starte ich einen Linux-Hintergrundprozess automatisch neu, wenn er fehlschlägt?

32

Ich habe einen Prozess, der von init.d Skript im Hintergrund ausgeführt wird. Z.B:

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

Unter bestimmten Umständen kann myprocess fehlschlagen und zurückkehren. Gibt es einen (Standard-) Weg, um einen Fehler zu erkennen und automatisch neu zu starten?

Honza
quelle
Sicher, aber es hängt von der Verteilung ab. Ziemlich alle von ihnen stellen eine Art Service-Manager zur Verfügung.
David Schwartz
Es gibt keine Standarddistribution, sondern buildroot. Also muss ich es manuell machen ...
Honza

Antworten:

14

Der einfachste Weg wäre es in dem / etc / inittab , die entworfen, um diese Art der Sache zu tun:

respawn Wenn der Prozess nicht existiert, starten Sie den Prozess. Warten Sie nicht auf die Beendigung (scannen Sie die Datei / etc / inittab weiter). Starten Sie den Prozess neu, wenn er stirbt. Wenn der Prozess vorhanden ist, tun Sie nichts und scannen Sie die Datei / etc / inittab weiter.

Zum Beispiel könnten Sie dies tun:

# Run my stuff
myprocess:2345:respawn:/bin/myprocess
Alan Shutko
quelle
Hinweis: Funktioniert /etc/inittab(oder existiert sogar) genau dann, wenn Sie ein sysvinit-basiertes Init-System haben. Mit Emporkömmling und mit systemd nicht. Sie müssen entweder busybox (eine sehr primitive Shell, die das Wiederherstellen von sysadm-Aufgaben schmerzhaft macht, aber einen sysvinit-kompatiblen initd ersetzen kann) oder sysvinit (ein Fossil) installieren . In einem Docker-Container ist nur der erste nicht schmerzhaft.
Peterh sagt wieder Monica
27

Buildroot verfügt über drei mögliche Init-Systeme. Dazu gibt es drei Möglichkeiten:

BusyBox init

Damit fügt man einen Eintrag zu /etc/inittab.

::respawn:/bin/myprocess

Beachten Sie, dass BusyBox initein eigenwilliges /etc/inittabFormat hat. Das zweite Feld ist bedeutungslos und das erste Feld ist keine ID, sondern ein Gerätebasisname.

Linux "System V" init

Auch hier fügt man einen Eintrag hinzu /etc/inittab.

myprocess:2345:respawn:/bin/myprocess

systemd

Man schreibt eine Unit-Datei in /etc/systemd/system/myprocess.service:

[Unit]
Description=My Process

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

[Install]
WantedBy=multi-user.target

Aktivieren Sie dies, um beim Booten automatisch zu starten mit:

systemctl enable myprocess.service

Starten Sie es manuell mit:

systemctl start myprocess.service

Weitere Lektüre

JdeBP
quelle
aber wenn Sie diesen Ansatz inittab verwenden, ist Ihr Prozess nicht mehr über die "Service" -Schnittstelle zugänglich, oder? dh du kannst nicht gehen service mything startoder service mything stopnicht mehr ... gibt es einen Weg, das Beste von beidem zu haben? dh nicht zusammenstoßbarer Sysvinit-Dienst, aber kann er auch über "Dienst" verwendet werden?
Horseyguy
25

Wie wäre es, eine Subshell mit einer Schleife zu erstellen, die ständig den gleichen Prozess aufruft?

Wenn es endet, wird die nächste Iteration der Schleife fortgesetzt und erneut gestartet.

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

Wenn die Unterschale stirbt, ist es zwar vorbei. In diesem Fall besteht die einzige Möglichkeit darin, einen weiteren Prozess zu erstellen (ich nenne ihn Nekromant), der überprüft, ob Ihr Prozess aktiv ist. Starten Sie ihn, falls dies nicht der Fall ist, und führen Sie diesen Nekromanten mit cron aus, damit Sie ihn regelmäßig überprüfen können.

Der nächste Schritt würde sich fragen, was passieren könnte, wenn cron stirbt, aber irgendwann sollten Sie sich sicher fühlen und aufhören, sich Sorgen zu machen.

Trylks
quelle
3

Sie könnten Monit gebrauchen . Es ist sehr einfach zu bedienen und sehr flexibel. In dieser Konfiguration sehen Sie beispielsweise, wie Sie den Tomcat-Prozess bei einem Fehler neu starten.

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

Es enthält auch viele Konfigurationsbeispiele für viele Anwendungsfälle.

Clyde D'Cruz
quelle
1

Wenn Sie kein Superuser oder Root sind und auf Ihrem Linux-System Docker installiert ist, können Sie ein Docker-Image Ihres Prozesses erstellen und den Prozess mit Docker neu starten, wenn das System neu gestartet wird.

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

So starten Sie Ihren Docker-Container:

docker-compose up -d

Ich finde es einfach, meinen eigenen Prozess mit automatischem Neustart abzuwickeln, wenn ich kein Superuser des Systems bin.

Ein Beispiel für die Erstellung eines Docker-Images finden Sie hier in einem kurzen Beispiel:

Datei: 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"]
Michael Qin
quelle
0

In meinem Fall habe ich als schnelle Lösung die Lösung von @Trylks modifiziert und verwendet, um das von mir gestartete Programm zu verpacken. Ich wollte, dass es nur beim sauberen Ausgang endet.

Sollte in den meisten Shells laufen:

#!/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) &
user9869932
quelle
0

Sie können einen Neustarter verwenden

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

Verwenden Sie auf neueren Systemen systemd, um all diese trivialen Probleme zu lösen

sivann
quelle