Hallo zusammen
Würde es gerne in einem Skript so machen, dass ich einen Dienst starten kann (über systemctl oder service..), und dann auf der nächsten Zeilen dynamisch gewartet wird (z.B. Endlosschleife) bis der Prozess wirklich existiert.
Irgendwie finde ich im Netz fast nur Beispiele welche z.B. bei Apache auf Port 80 oder bei MySQL auf Port 3306 prüfen: https://www.google.com/search?biw=1920& ... i8Q4dUDCAs
Es sollte in meinem Fall eher was sein, was generisch, also allgemein verwendbar, ist.
Vielen Dank für die Feedbacks.
Warten, bis ein Dienst gestartet ist? [Gelöst]
Warten, bis ein Dienst gestartet ist? [Gelöst]
Zuletzt geändert von jmar83 am 09.12.2019 16:29:00, insgesamt 2-mal geändert.
Freundliche Grüsse, Jan
Re: Warten, bis ein Dienst gestartet ist?
Ganz allgemein kannst du doch mit systemd prüfen ob ein bestimmer Dienst bereits läuft. Falls das sinnvoll/notwendig ist, können die Prozesse systemd mitteilen, wenn sie einsatzbereit sind (systemd-notify). Startest du also eine service-Unit beispielsweise mit
dann ist der Befehl erst fertig, wenn dieser Service gestartet und einsatzbereit ist. Das setzt natürlich voraus, dass der Service systemd darüber informiert, dass er einsatzbereit ist, was mit systemd-notify möglich ist. Ein Beispiel für eigene Dienste, die dieses Feature nutzen gibt es hier: https://askubuntu.com/questions/1120023 ... emd-notify
(Der Hauptprozess des fraglichen Dienstes sollte aber auf jeden Fall bereits existieren, wenn systemctl start ... abgeschlossen ist.)
Ansonsten habe ich behelfsweise auch schon in einer Endlosschleife auf einen Prozesse gewartet, die nicht von systemd gestartet werden. Etwa so
Keine sehr elegante Lösung, aber im Fall von mpd hat es sehr gut funktioniert und eventuell kann man die Suche mit pgrep noch mit weiteren Parametern präzisieren und damit verlässlicher machen.
Code: Alles auswählen
systemctl start mein-service.service
(Der Hauptprozess des fraglichen Dienstes sollte aber auf jeden Fall bereits existieren, wenn systemctl start ... abgeschlossen ist.)
Ansonsten habe ich behelfsweise auch schon in einer Endlosschleife auf einen Prozesse gewartet, die nicht von systemd gestartet werden. Etwa so
Code: Alles auswählen
#!/bin/bash
PROCESS_NAME=mpd
while : ; do
pgrep "${PROCESS_NAME}" && break
sleep 1s
done
echo "Prozess gestartet"
Re: Warten, bis ein Dienst gestartet ist?
Vielen Dank!!
Lässt sich das eigentlich nicht auch in der Unit-Datei (systemd) festlegen, type=... (simple, idle, fork...etc.?)
Code: Alles auswählen
"dann ist der Befehl erst fertig, wenn dieser Service gestartet und einsatzbereit ist. Das setzt natürlich voraus, dass der Service systemd darüber informiert, dass er einsatzbereit ist, was mit systemd-notify möglich ist."
Freundliche Grüsse, Jan
Re: Warten, bis ein Dienst gestartet ist?
Bei den unterschiedlichen typen fehlt mir ein bisschen der Überblick, aber bei simple, dbus und idle trifft das auf jeden Fall zu was ich gesagt habe und bei notify muss der Dienst systemd darüber informieren, dass er bereit ist.
oneshot ist insofern anders, als da der Dienst als bereit gilt, nachdem sich der Prozess beendet hat.
Den Unterschied zwischen simple und exec kapiere ich nicht und bei fork rechnet systemd damit, dass sich der gestartete Elternprozess beendet und ein bestimmter Kindprozess (idealerweise mit PID-Datei) der entscheidende ist.
oneshot ist insofern anders, als da der Dienst als bereit gilt, nachdem sich der Prozess beendet hat.
Den Unterschied zwischen simple und exec kapiere ich nicht und bei fork rechnet systemd damit, dass sich der gestartete Elternprozess beendet und ein bestimmter Kindprozess (idealerweise mit PID-Datei) der entscheidende ist.
Re: Warten, bis ein Dienst gestartet ist?
Vielen Dank für dein Feedback. Ja, das ganze ist nicht ganz trivial, und die Methode mit der Prozessüberprüfung sollte zwar allgemein verwendbar sein - diese ist aber auch eher "suboptimal"...
Freundliche Grüsse, Jan
Re: Warten, bis ein Dienst gestartet ist?
Da du nicht verraten hast, was dein Anwendungsfall ist (evtl. gäbe es eine bessere Lösung), ein paar allgemeine, aber auch systemd-spezifische Anmerkungen dazu:
Man kann generell feststellen, ob ein Prozess (für eine bestimmte Anwendung) läuft – wie schon öfter angesprochen per pgrep, ps etc.. Das heißt aber noch lange nicht, dass die Anwendung dahinter schon „ansprechbar“ ist, z.B. ein Webserver wie oben erwähnt auf Port 80 erreichbar ist. Es könnte in dem Prozess immer noch irgendeine Art der „Vorbereitung“ laufen. Für „Ansprechbarkeit“ braucht es eigentlich immer eine spezielle Methode, 100% generisch geht das nicht.
Wenn ein Dienst, z.B. per systemctl start gestartet wird passiert folgendes: systemd (PID 1) fork()t einen neuen Prozess ab (PID x), dieser Prozess (PID x) ersetzt per execve() sich selbst mit dem zu startenden Dienst (/usr/bin/apache2, /usr/bin/mpd, /usr/sbin/whatever; weiter PID x). Erst da ganz am Ende läuft der eigentliche Dienst und kann seine eigenen „Vorbereitungen“ treffen, nach denen er „ansprechbar“ ist.
Im Normalfall (Type=simple) geht systemctl start davon aus, dass der Dienst schon nach dem fork() erfolgreich gestartet ist. Das kann aber nach dem execve() immer noch schief gehen, wenn das eigentliche Programm einen Fehler verursacht.
Beim Type=exec geht systemctl start erst nach dem execve() davon aus, dass der Dienst gestartet ist. Damit bekommt man durch das systemctl start evtl. mehr Fehler mit und der Dienst ist außerdem schon „weiter“ gestartet, als beim Type=simple. Das garantiert aber wie gesagt immer noch nicht, dass ein Dienst schon „ansprechbar“ ist.
Ein systemctl start (ohne --no-block) wartet also im Normalfall schon so lange, bis ein Dienst läuft – soweit das allgemein sinnvoll möglich ist. Genaueres braucht eine Extrawurst: sd_notify(), Aktivierung des Services über nen systemd.socket, nen PID-File etc. – hängt von der Anwendung ab.
Man kann generell feststellen, ob ein Prozess (für eine bestimmte Anwendung) läuft – wie schon öfter angesprochen per pgrep, ps etc.. Das heißt aber noch lange nicht, dass die Anwendung dahinter schon „ansprechbar“ ist, z.B. ein Webserver wie oben erwähnt auf Port 80 erreichbar ist. Es könnte in dem Prozess immer noch irgendeine Art der „Vorbereitung“ laufen. Für „Ansprechbarkeit“ braucht es eigentlich immer eine spezielle Methode, 100% generisch geht das nicht.
Wenn ein Dienst, z.B. per systemctl start gestartet wird passiert folgendes: systemd (PID 1) fork()t einen neuen Prozess ab (PID x), dieser Prozess (PID x) ersetzt per execve() sich selbst mit dem zu startenden Dienst (/usr/bin/apache2, /usr/bin/mpd, /usr/sbin/whatever; weiter PID x). Erst da ganz am Ende läuft der eigentliche Dienst und kann seine eigenen „Vorbereitungen“ treffen, nach denen er „ansprechbar“ ist.
Im Normalfall (Type=simple) geht systemctl start davon aus, dass der Dienst schon nach dem fork() erfolgreich gestartet ist. Das kann aber nach dem execve() immer noch schief gehen, wenn das eigentliche Programm einen Fehler verursacht.
Beim Type=exec geht systemctl start erst nach dem execve() davon aus, dass der Dienst gestartet ist. Damit bekommt man durch das systemctl start evtl. mehr Fehler mit und der Dienst ist außerdem schon „weiter“ gestartet, als beim Type=simple. Das garantiert aber wie gesagt immer noch nicht, dass ein Dienst schon „ansprechbar“ ist.
Ein systemctl start (ohne --no-block) wartet also im Normalfall schon so lange, bis ein Dienst läuft – soweit das allgemein sinnvoll möglich ist. Genaueres braucht eine Extrawurst: sd_notify(), Aktivierung des Services über nen systemd.socket, nen PID-File etc. – hängt von der Anwendung ab.
Manchmal bekannt als Just (another) Terminal Hacker.
Re: Warten, bis ein Dienst gestartet ist?
Vielen Dank für deine hoch ausführliche Erklärung!!
Freundliche Grüsse, Jan