So stellen Sie sicher, dass eine Anwendung unter Linux weiterhin ausgeführt wird

83

Ich versuche sicherzustellen, dass ein Skript weiterhin auf einem Entwicklungsserver ausgeführt wird. Es sammelt Statistiken und bietet einen Webdienst, so dass es bestehen bleiben soll, aber einige Male am Tag stirbt es aus unbekannten Gründen ab. Wenn wir bemerken, dass wir es einfach erneut starten, ist es ein Problem, und einige Benutzer haben keine Berechtigung (oder kein Know-how), es zu starten.

Der Programmierer in mir möchte ein paar Stunden damit verbringen, dem Problem auf den Grund zu gehen, aber die beschäftigte Person in mir ist der Meinung, dass es eine einfache Möglichkeit geben muss, zu erkennen, ob eine App nicht ausgeführt wird, und sie erneut zu starten.

Ich weiß , ich könnte cron-Skript ps durch grep:

ps -A | grep appname

Aber auch dies ist eine weitere Stunde meines Lebens, in der ich etwas verschwendet habe, das bereits vorhanden sein muss ... Gibt es nicht eine vorgefertigte App, mit der ich eine ausführbare Datei übergeben kann (optional mit Argumenten) und die einen Prozess auf unbestimmte Zeit laufen lässt?

Falls es einen Unterschied macht, ist es Ubuntu.

Oli
quelle
1
Es hängt davon ab, ob Statistiken verloren gehen, wenn das Skript nicht ausgeführt wird, aber ich denke, der Programmierer in Ihnen hat Recht - Sie sollten mehr darüber erfahren, warum das Skript nicht auf unbestimmte Zeit fortgesetzt wird.
Jonathan Leffler
1
Es ist eher ein On-Demand-Dienstprogramm als etwas, das ständig Zahlen knirscht. Wenn es abstürzt, bevor Daten gespeichert werden, geht nichts verloren. Der Job wird nur beim nächsten Ausführen abgeschlossen.
Oli
Die Frage wurde bei Standard oder am besten beantwortet , um den von init.d gestarteten Prozess am Leben zu erhalten . Die Lösungen umfassen die Verwendung von systemd und /etc/inittab.
Koppor

Antworten:

37

Hinweis: Upstart befindet sich im Wartungsmodus und wurde von Ubuntu, das systemd verwendet, abgebrochen . Im Handbuch des Systems finden Sie Einzelheiten zum Schreiben der Dienstdefinition.

Da Sie Ubuntu verwenden, könnte Sie Upstart interessieren , das den traditionellen sysV-Init ersetzt hat . Ein wichtiges Merkmal ist, dass ein Dienst neu gestartet werden kann, wenn er unerwartet stirbt. Fedora ist zum Emporkömmling übergegangen, und Debian befindet sich im Experiment, daher lohnt es sich möglicherweise, einen Blick darauf zu werfen.

Dies kann in dieser Situation jedoch zu viel des Guten sein, da die Implementierung eines Cron- Skripts 2 Minuten dauert.

#!/bin/bash
if [[ ! `pidof -s yourapp` ]]; then
    invoke-rc.d yourapp start
fi
JimB
quelle
Ich muss beachten, dass die Konfiguration von upstart zur Verwaltung Ihres Dienstes und zur Aufrechterhaltung des Betriebs recht einfach ist (Sie schreiben eine kleine Konfigurationsdatei). Diese Lösung ist viel sauberer, einfacher und besser als jede andere auf "einfachen" Cron / Shell-Skripten basierende Überwachung.
Thor
@thor - (Hinweis: Dies ist aus dem Jahr 2008, als der Start neu war und die Dokumentation schwieriger zu bekommen war). Ich stimme zu, das "einfache" Cron-Skript sollte nur veranschaulichen, dass ein Skript auch nicht komplex sein muss, um die Arbeit zu erledigen.
JimB
Aha. Ich habe Ihre Antwort sowieso upvoted wenn mein Kommentar platzieren
thor
85

Ich habe ein einfaches Skript mit cron verwendet, um sicherzustellen, dass das Programm ausgeführt wird. Wenn dies nicht der Fall ist, wird es gestartet. Dies ist möglicherweise nicht die perfekte Lösung, die Sie suchen, aber es ist einfach und funktioniert ziemlich gut.

#!/bin/bash
#make-run.sh
#make sure a process is always running.

export DISPLAY=:0 #needed if you are running a simple gui app.

process=YourProcessName
makerun="/usr/bin/program"

if ps ax | grep -v grep | grep $process > /dev/null
then
    exit
else
    $makerun &
fi

exit

Fügen Sie dann jede Minute oder alle 5 Minuten einen Cron-Job hinzu.

Chris Wendt
quelle
2
Das ist Genie. Es wird einen Neustart überleben und nichts zu installieren.
Ian Purton
Ich habe dies selbst verwendet, da für die Installation keine Root-Berechtigung erforderlich ist.
JohnMudd
Was wäre das process name, wenn ich ein Python-Skript am Laufen halten möchte?
Benutzer
@Benutzer Verwenden Sie diese Option, ps ax | grep XXXum nur Ihren Prozess aufzulisten. Dann ist es XXX.
Strongwillow
10
Führen Sie als Cron One-Liner einmal pro Minute aus:* * * * * ps aux|grep -v grep|grep -q YourProcessName || /usr/bin/program &
ACK_stoverflow
43

Monit ist perfekt dafür :)

Sie können einfache Konfigurationsdateien schreiben, die monit anweisen, z. B. einen TCP-Port, eine PID-Datei usw. Zu überwachen

monit führt einen Befehl aus, den Sie angeben, wenn der zu überwachende Prozess nicht verfügbar ist / zu viel Speicher verwendet / die CPU zu lange fixiert / etc. Außerdem wird eine E-Mail-Benachrichtigung angezeigt, die Sie darüber informiert, was passiert ist und ob etwas dagegen unternommen werden kann.

Wir verwenden es, um eine Menge unserer Websites am Laufen zu halten und uns frühzeitig zu warnen, wenn etwas schief geht.

- Ihr treuer Angestellter, Monit

Gareth
quelle
19
Wie hältst du Monit am Laufen?
JohnMudd
2
Dieser ist ziemlich schwer zu lernen. Ich möchte nur ein Skript neu starten (anstelle eines Dienstes) und habe das Dokument stundenlang gelesen, konnte es aber nicht herausfinden.
Tyler Long
21

Wenn Sie eine systemd-basierte Distribution wie Fedora und aktuelle Ubuntu-Versionen verwenden, können Sie die "Restart" -Funktion von systemd verwenden für Dienste verwenden. Es kann als Systemdienst oder als Benutzerdienst eingerichtet werden, wenn es von einem bestimmten Benutzer verwaltet und als solcher ausgeführt werden muss, was in der jeweiligen Situation des OP wahrscheinlicher ist.

Die Neustart - Option nimmt einen no , on-success, on-failure, on-abnormal, on-watchdog, on-abort, oderalways .

Um es als Benutzer auszuführen, platzieren Sie einfach eine Datei wie die folgende in ~/.config/systemd/user/something.service:

[Unit]
Description=Something

[Service]
ExecStart=/path/to/something
Restart=on-failure

[Install]
WantedBy=graphical.target

dann:

systemctl --user daemon-reload
systemctl --user [status|start|stop|restart] something

Keine Root-Berechtigung / Änderung von Systemdateien erforderlich, keine Cron-Jobs erforderlich, nichts zu installieren, höllisch flexibel (siehe alle zugehörigen Serviceoptionen in der Dokumentation).

Weitere Informationen zur Verwendung der systemd-Instanz pro Benutzer finden Sie unter https://wiki.archlinux.org/index.php/Systemd/User .

Raman
quelle
Tolle Antwort, aber ~ / .config / systemd / user / Something.service war für mich ein wenig mehrdeutig. Ist der Teil "Benutzer" wörtlich "Benutzer" oder wie "Ihr Benutzername"? Wenn es "Ihr Benutzername" ist, erscheint mir das überflüssig, da Sie diese Datei in Ihrem Home-Verzeichnis erstellen. Bearbeiten: sieht aus wie es buchstäblich "Benutzer" ist
fivedogit
8

Ich habe von cron "killall -0 programname || /etc/init.d/programname start" verwendet. kill wird fehlschlagen, wenn der Prozess nicht existiert. Wenn es existiert, liefert es ein Nullsignal an den Prozess (das der Kernel ignoriert und sich nicht die Mühe macht, es weiterzugeben.)

Diese Redewendung ist einfach zu merken (IMHO). Im Allgemeinen verwende ich dies, während ich immer noch versuche herauszufinden, warum der Dienst selbst fehlschlägt. IMHO sollte ein Programm nicht einfach unerwartet verschwinden :)


quelle
7

Setzen Sie Ihren Lauf in eine Schleife. Wenn er beendet wird, wird er erneut ausgeführt ... while (true) {starte meine App ..}

Klathzazt
quelle
3
Wenn das Skript aus unbekannten Gründen stirbt, wird es wahrscheinlich auch das Schleifenskript abbrechen, nicht wahr?
Gareth
4
Ich bin mit Garath zusammen, wenn das System lang laufende Prozesse beendet, wird die vorgeschlagene Schleife - die vor der App beginnen würde - zuerst beendet.
ekerner
2
Um Ihre beiden Kommentare zu beantworten: Nein, wenn das Skript aus unbekannten Gründen stirbt, ist das Schleifenskript nicht betroffen, da es in einem separaten Prozess ausgeführt wird. Wenn das System jedoch zufällig lange laufende Prozesse zufällig beendet, ist dies immer noch ein Problem - Ich bezweifle jedoch, dass dies der Fall ist. Der Rest des Systems wurde nicht als betroffen gemeldet und ist voll von anderen lang laufenden Prozessen, die ebenfalls neu gestartet worden wären (nur erwähnt, dass dieses eine Skript ein Problem hat).
Klathzazt
4

Ich konnte Chris Wendt- Lösung aus irgendeinem Grund nicht zum Laufen bringen, und es war schwer zu debuggen. Dieser ist ziemlich gleich, aber einfacher zu debuggen, schließt Bash vom Pattern Matching aus. Zum Debuggen einfach ausführen : bash ./root/makerun-mysql.sh. Im folgenden Beispiel mit mysql-server ersetzen Sie einfach den Wert der Variablen für processund makerunfür Ihren Prozess.

  • Erstellen Sie ein BASH-Skript wie folgt ( nano /root/makerun-mysql.sh):
#!/bin/bash
process="mysql"
makerun="/etc/init.d/mysql restart"
if ps ax | grep -v grep | grep -v bash | grep --quiet $process
then
    printf "Process '%s' is running.\n" "$process"
    exit
else
    printf "Starting process '%s' with command '%s'.\n" "$process" "$makerun"
    $makerun
fi
exit
  • Stellen Sie sicher , es ist ausführbar durch die richtigen Dateiberechtigungen Hinzufügen (dh chmod 700 /root/makerun-mysql.sh)

  • Fügen Sie dies dann Ihrem crontab ( crontab -e) hinzu:

# Keep processes running every 5 minutes
*/5 * * * * bash /root/makerun-mysql.sh
Cjohansson
quelle
1
Beachten Sie, dass das Skript im Vergleich zur Lösung von Chris Wendt hier nicht als Hintergrundaufgabe gestartet wird.
Mason
2

Das superviseWerkzeug vondaemontools wäre meine Präferenz - aber dann ist alles, was Dan J Bernstein schreibt, meine Präferenz :)

http://cr.yp.to/daemontools/supervise.html

Sie müssen eine bestimmte Verzeichnisstruktur für Ihr Anwendungsstart-Skript erstellen, diese ist jedoch sehr einfach zu verwenden.

Asfand Qazi
quelle
1

Wie startet man diese App? Gabelt es sich in den Hintergrund? Beginnt es mit nohup .. & etc? Wenn es das letztere ist, überprüfen Sie, warum es in nohup.out gestorben ist. Wenn es das erste ist, erstellen Sie die Protokollierung.

Was Ihre Hauptfrage betrifft: Sie könnten es cronen oder einen anderen Prozess im Hintergrund ausführen (nicht die beste Wahl) und pidof in einem Bashscript verwenden, ganz einfach:

if [ `pidof -s app` -eq 0 ]; then
    nohup app &
fi
gx.
quelle
1

Sie könnten es zu einem Dienst machen, der von inittab aus gestartet wird (obwohl einige Linux-Versionen in /etc/event.d zu etwas Neuerem übergegangen sind). Diese integrierten Systeme stellen sicher, dass Ihr Dienst weiterhin ausgeführt wird, ohne eigene Skripte zu schreiben oder etwas Neues zu installieren.

Paul Tomblin
quelle
1

Es ist ein Job für ein DMD (Daemon Monitoring Daemon). es sind ein paar da; Normalerweise schreibe ich jedoch nur ein Skript, das prüft, ob der Dämon ausgeführt wird, und wenn nicht, und stelle es in cron, damit es jede Minute ausgeführt wird.

Javier
quelle
1

nannyLesen Sie ' ', auf das in Kapitel 9 (S. 197 oder so ungefähr) des "Unix Hater's Handbook" (eine von mehreren Quellen für das Buch als PDF) verwiesen wird .

Jonathan Leffler
quelle
1

Eine schöne, einfache Möglichkeit, dies zu tun, ist wie folgt:

  1. Schreiben Sie Ihren Server so, dass er stirbt, wenn er den erwarteten Port nicht überwachen kann
  2. Stellen Sie einen Cronjob ein, um zu versuchen, Ihren Server jede Minute zu starten

Wenn es nicht läuft, startet es und wenn es läuft, läuft es nicht. In jedem Fall ist Ihr Server immer aktiv.

Casey Rodarmor
quelle
0

Ich denke, eine bessere Lösung ist, wenn Sie die Funktion auch testen. Wenn Sie beispielsweise einen Apache testen mussten, reicht es nicht aus, nur zu testen, ob auf den Systemen "Apache" -Prozesse vorhanden sind.

Wenn Sie testen möchten, ob Apache OK ist, versuchen Sie, eine einfache Webseite herunterzuladen, und testen Sie, ob Ihr eindeutiger Code in der Ausgabe enthalten ist.

Wenn nicht, töte den Apachen mit -9 und starte dann neu. Und senden Sie eine E-Mail an das Stammverzeichnis (eine weitergeleitete E-Mail-Adresse an das Stammverzeichnis des Unternehmens / Servers / Projekts).

Peter - Setzen Sie Monica wieder ein
quelle
1
Das ist wahr. Viele der in anderen Antworten vorgeschlagenen Überwachungslösungen bieten Protokollüberwachung.
Oli
0

Es ist noch einfacher:

#!/bin/bash

export DISPLAY=:0

process=processname
makerun="/usr/bin/processname"

if ! pgrep $process > /dev/null
then
    $makerun &
fi

Sie müssen sich jedoch daran erinnern, dass der Prozessname eindeutig ist.

Radosław Ganczarek
quelle