Prozess beim shutdown noch zu Ende laufen lassen

Alle weiteren Dienste, die nicht in die drei oberen Foren gehören.
Antworten
7Saturn
Beiträge: 19
Registriert: 04.02.2018 21:43:36

Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von 7Saturn » 04.02.2018 21:53:50

Moin.

Ich hoffe mal, das passt hier thematisch rein. So eine mMn richtig passende Kategorie habe ich leider keine gefunden.

Folgende Ausgangslage: Hier rennt ein Debian stretch, auf dem alle 10 Minuten eine Software Serverlogs auswertet und die Ergebnisse für den nächsten Lauf speichert. Auf diese Weise muss nicht immer das gesamte Log von neuem ausgewertet werden. Gestartet wird das bisher über Cron. In der Vergangenheit habe ich festgestellt, dass im ungünstigsten Fall ein Shutdown genau zu dem Zeitpunkt, zu dem diese Daten gespeichert werden, diese Zustands-Datei unbrauchbar macht. Was dann zur Folge hat, dass man diese Zustandsdatei löschen und doch von ganz von vorne anfangen muss. Und das kann dauern...

Bisher habe ich mir immer damit beholfen, ein eigenes Skript zum Runterfahren/Neustarten zu benutzen, das ggf. so lange wartet, bis der Prozess beendet ist, und erst dann den tatsächlichen shutdown-/reboot-Befehl absetzt. Funktioniert zwar, aber irgendwie kann ich mir nicht vorstellen, dass das nicht auch »sauber« mit Systemd machbar ist. Zumal man das auch gerne mal vergisst. Und den Hardwareschalter interessiert das erst recht nicht...

Drum die Frage: Kann man Linux mit Systemd oder auf eine andere Weise so konfigurieren, dass ein standardmäßiger Shutdown, oder Reboot, ggf. auch über den Hardwareknopf ausgelöst, erst mal abwartet, wenn ein gewisser Prozess noch läuft? Was ich mir schon überlegt hatte ist, dass man ein Skript schreibt, das tatsächlich auch nichts anderes macht, als zu warten, bis der Prozess beendet ist. Und das Skript dann in Systemd so zu hinterlegen, dass es »noch schnell« vor dem eigentlichen Runterfahren ausgeführt wird. Keine Ahnung, ob das so funktioniert, wie ich es mir vorstelle...

breakthewall
Beiträge: 507
Registriert: 30.12.2016 23:48:51

Re: Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von breakthewall » 05.02.2018 02:54:16

Soweit mir bekannt ist, ist das unter Systemd nicht mehr möglich. Denn hier wurde ab Systemd 230 eine Neuerung eingeführt, wodurch alle Nutzerprozesse beim Herunterfahren aus Sicherheitsgründen beendet werden. Zumal es eine dubiose Praxis darstellt, beim Herunterfahren noch etwas abzuarbeiten, was sich zu diesem Zeitpunkt jeglicher Kontrolle entzieht. Wenn soetwas allerdings umsetzen musst, dann würde ich versuchen das als Systemdienst umzusetzen, der von Systemd als Unit kontrolliert wird. Hier könntest gemäß der Event-Hierarchie, ggf. noch einen Prozess starten, der zum Zeitpunkt des shutdown.target aktiv wird. Von daher einfach mal ausprobieren.

NAB
Beiträge: 5501
Registriert: 06.03.2011 16:02:23
Lizenz eigener Beiträge: MIT Lizenz

Re: Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von NAB » 05.02.2018 06:19:48

Hast du da eine "Stop-Job is running"-Meldung beim Herunterfahren?

Dann kannst du in der
/etc/systemd/system.conf
einfach "DefaultTimeoutStopSec" deutlich weiter hochsetzen. Dann sollte er dir laufende Prozesse nicht mehr killen (bzw. später killen).
Never change a broken system. It could be worse afterwards.

"No computer system can be absolutely secure." Intel Document Number: 336983-001

7Saturn
Beiträge: 19
Registriert: 04.02.2018 21:43:36

Re: Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von 7Saturn » 05.02.2018 08:26:50

breakthewall hat geschrieben: ↑ zum Beitrag ↑
05.02.2018 02:54:16
Soweit mir bekannt ist, ist das unter Systemd nicht mehr möglich.
Schade.
breakthewall hat geschrieben: ↑ zum Beitrag ↑
05.02.2018 02:54:16
Denn hier wurde ab Systemd 230 eine Neuerung eingeführt, wodurch alle Nutzerprozesse beim Herunterfahren aus Sicherheitsgründen beendet werden.
Um ehrlich zu sein, bin ich aus dem Grund heraus ohnehin am Überlegen, ein extra Skript anzulegen, weil es mehrere dieser Prozesse parallel gibt, die alle als ihr eigener User rennen. Das könnte man auch als ein einzelnes Root-Skript zusammengefasst ablaufen lassen, das ebenfalls diese einzelnen Jobs als User anstößt. Oder würden dann diese Tochterprozesse trotzdem abgewürgt?
breakthewall hat geschrieben: ↑ zum Beitrag ↑
05.02.2018 02:54:16
Zumal es eine dubiose Praxis darstellt, beim Herunterfahren noch etwas abzuarbeiten, was sich zu diesem Zeitpunkt jeglicher Kontrolle entzieht.
Mir fällt halt keine wirklich gute Alternative ein, außer das als Cron oder Systemdienst laufen zu lassen. Zu Fuß kommt gar nicht in Frage und das eigens dafür angelegte shutdown-Skript will ich gerade eben los werden.
breakthewall hat geschrieben: ↑ zum Beitrag ↑
05.02.2018 02:54:16
Wenn soetwas allerdings umsetzen musst, dann würde ich versuchen das als Systemdienst umzusetzen, der von Systemd als Unit kontrolliert wird. Hier könntest gemäß der Event-Hierarchie, ggf. noch einen Prozess starten, der zum Zeitpunkt des shutdown.target aktiv wird. Von daher einfach mal ausprobieren.
OK, ist also nicht von vornherein ausgeschlossen.
NAB hat geschrieben: ↑ zum Beitrag ↑
05.02.2018 06:19:48
Hast du da eine "Stop-Job is running"-Meldung beim Herunterfahren?
Nope, aber ist bisher ja auch noch als Cronjob realisiert.
NAB hat geschrieben: ↑ zum Beitrag ↑
05.02.2018 06:19:48
Dann kannst du in der
/etc/systemd/system.conf
einfach "DefaultTimeoutStopSec" deutlich weiter hochsetzen. Dann sollte er dir laufende Prozesse nicht mehr killen (bzw. später killen).
Das wäre eine gute Alternative. Es dreht sich dabei zumeist ja nur um 1-2 Minuten, bis das ganz sicher abgelaufen ist. Danke euch beiden schon mal für die Tips.

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von uname » 05.02.2018 08:54:49

Leider hast du etwas wenig über die Anwendung geschrieben. Aber der Fehler ist wohl mehr in dem Programm zu suchen. Würde es einfach abstürzen (Programme stürzen von Zeit zu Zeit ab), würde es einen ähnlichen Fehler produzieren, was ähnlich ärgerlich wie ein Shutdown wäre.

Du schreibst die (alte) Zustands-Datei wird unbrauchbar gemacht. Genau das darf nicht passieren. Die Zustandsdatei muss in mindestens zwei Generationen (Vater, Sohn) vorliegen. Evtl. musst du weitere Werte wie z. B. aktuelle Zeile usw. zwischenspeichern. Beim Beginn der Verarbeitung verwendest du die benötigsten Statusinformationen und verschiebst die Zustands-Datei vom Sohn zum Vater (eine Art Backup). Eine neue Zustandsdatei liegt erst dann vor, wenn die Verabeitung erfolgreich durchlaufen wurde. Stürzt die Software ab bzw. wird der Rechner neu gestartet muss beim nächsten durch Cron angesteuerten Durchlauf deine Sotware erkennen, dass noch keine neue Zustandsdatei (Sohn) vorliegt und die Verarbeitung muss auf Basis der alten Zustandsdatei (Vater) und evtl. weiterer Dateien wiederholt werden.

7Saturn
Beiträge: 19
Registriert: 04.02.2018 21:43:36

Re: Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von 7Saturn » 05.02.2018 10:50:17

Ja, das Problem liegt im Wesentlichen an der Nichtbenutzung von temporären Files. Der letzte Schritt, also das löschen des alten Files und ersetzen mit dem neuen wäre wesentlich schneller, als der Schreibvorgang, der zuletzt läuft.

TomL

Re: Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von TomL » 05.02.2018 11:17:55

7Saturn hat geschrieben: ↑ zum Beitrag ↑
05.02.2018 08:26:50
...und das eigens dafür angelegte shutdown-Skript will ich gerade eben los werden.
Ich glaube, dass das die einzige Möglichkeit ist, die halbwegs zuverlässig funktioniert ... die allerdings auch nur solange zuverlässig funktioniert, wie nicht jemand direkt "systemctl shutdown" im Terminal eingibt. Ganz egal, wie Du Dein Programm startest, ob über Cron oder Systemd-Timer oder als Systemd-Daemon, ab dem Moment, ab dem das Shutdown.Target läuft, ist das System nicht mehr dasselbe, wie zuvor... weil ab dem Momet Services und Prozesse aufgefordert werden, sich zu beenden oder nach dem Timeout beendet werden. Und es imho nicht möglich, einen Delay-Job präzise und gleichbleibend als erstes in der Shutdown-Kette zu platzieren, oder besser noch das Shutdown.Target selber zu verzögern, weil ab dem Shutdown-Event eben keine Prozesse mehr gestartet werden können... was ich persönlich auch für sinnvoll halte.

Ich glaube, dass es ein Design-Fehler der App ist, wenn die beim Shutdown noch 1 bis 2 Minuten braucht, um ihre Daten zu sichern.... das müssten von der Menge ja Gigabytes sein. Besser wäre es, wenn das Script nicht zyklisch über Cron gestartet wird, sondern einfach permanent als Daemon läuft und selber auf SIGTERM reagiert, also auf die von systemd beim Shutdown.Target gesendete Benachrichtigung, sich zu beenden, um dann eben nur schnell alles offene zu beenden und schließen. Das sollte für ausreichende Sicherheit der Daten sorgen.

Benutzeravatar
Profbunny
Beiträge: 592
Registriert: 04.04.2004 11:12:29
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Bautzen

Re: Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von Profbunny » 05.02.2018 11:26:34

Für genau diesen Fall gibt es systemd-inhibit. Allerdings ist die Anwendung recht tricky, wie viewtopic.php?f=32&t=165009 hier beschrieben.
Rechner / Server Debian sid

7Saturn
Beiträge: 19
Registriert: 04.02.2018 21:43:36

Re: Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von 7Saturn » 05.02.2018 11:29:44

Also der Haken bei der Sache ist der, dass die eigentliche Analyse-Zeit unproblematisch ist. Also wenn der shutdown irgendwo vor den letzten 1-2 Sekunden ist, macht's nichts, wenn's abgeschossen wird. Aber wenn das halt genau dann zuschlägt, während das Programm gerade speichert (das dauert auch nicht lange, aber genau da hat's halt schon getroffen), dann ist das File im Eimer, und beim nächsten run verweigert er die Arbeit damit, weil das File defekt ist. Dann muss man Hand anlegen. Aber alles in allem sieht es so aus, als wenn es wohl sinnvoller wäre, das ursprüngliche Problem (mit dem Temp-File) zu lösen. Ich seh's mir auf jeden Fall mal an, ob da was geht.
Edit:
Das mit dem inhibit sieht ja sehr spannend aus. Genau so was meinte ich. Für den Moment wäre das OK. Aber es ist natürlich richtig, dass ein Tempfile das Problem recht elegant und zuverlässig lösen könnte.

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von scientific » 05.02.2018 11:40:03

Wenn du dieses Zustandsfile einfach löscht, dann erstellt die Anwendung dieses einfach wieder neu?
Wo liegt denn dieses Zustandsfile überhaupt?
Diese Anwendung wird für jeden User extra ausgeführt? Und nur dann, wann dieser User eingeloggt ist, oder überhaupt regelmäßig für alle (oder eine ausgewählte Liste) am System vorhandener User (also jene Logins für physische Personen, die sich auch graphisch einloggen können)?

Um einen Prozess als User unter einer bestimmten ID laufen lassen zu können, hast du mehrere Möglichkeiten.

1) Du führst ihn in der User-Instanz des Users aus. Diese wird beim ersten Login gestartet, und wenn sich der User von der letzten Session abmeldet, wird die User-Instanz wieder beendet. (Du könntest dich ja graphisch in Gnome und auf einem anderen TTY in der Konsole einloggen, und gleichzeitig noch von einem externen Rechner über ssh!)
Damit ein Service mit dieser UID in dieser Usersession ausgeführt wird, kannst du in /etc/systemd/user/ deine Service-Unit anlegen.
Z.B.

Code: Alles auswählen

# editor /etc/systemd/user/Test.service
[Unit]
Description=Testunit für einen User-Service
[Service]
ExecStart=/bin/true
RemainAfterExit=yes
[Install]
WantedBy=default.target
(RemainAfterExit=yes lässt diese Unit nach beenden von /bin/true aktiv. Das ist so, wie wenn ein Dienst im Hintergrund weiterlaufen würde. mit systemctl --user stop Test.service kannst du diese Unit wieder stoppen, also den Dienst beenden)
Damit du für einzelne User dieses Testscript aktivierst musst du als dieser User folgenden Befehl in einem Terminal oder auf der Console ausführen:

Code: Alles auswählen

$ systemctl --user enable Test.service
Dann log ich aus und log dich wieder ein und teste mit

Code: Alles auswählen

$ systemctl --user status Test.service
ob der Service läuft.

Damit dies Unit für alle User automatisch enabled ist, kannst du gleich einen Symlink setzen

Code: Alles auswählen

# cd /etc/systemd/user/default.target.wants
#ln -s ../Test.service
Wie schon erwähnt, werden diese Services mit dem letzten Ausloggen des Users aus dem letzten Terminal/graphischen Sitzung beendet. Müsstest einmal probieren, ob so ein Service noch korrekt beendet wird.

2) Du führst einen Systemservice ein. Am besten einen sogenannten "instanziierenden". Das heißt du brauchst eine Instanziierende Systemd-Unit:

Code: Alles auswählen

editor /etc/systemd/system/test@.service
[Unit]
Description=Testservice für User %i
After=default.target
[Service]
User=%i
ExecStart=/bin/true
RemainAfterExit=yes
TimeoutStopSec=2m
[Install]
WantedBy=default.target
Die Unit wartet dann beim Stoppen 2 Minuten, bis sie gekillt wird. (wenn du mehr Zeit benötigst, brauchst du nur TimeoutStopSec erhöhen). Außerdem wird sie mit der UID des Users, für den sie enabled wird, ausgeführt. Das heißt, wenn du für fritz, franz und hannelore den System-Service aktivieren möchtest, führst du als Root das aus:

Code: Alles auswählen

systemctl enable test@fritz test@franz test@hannelore
Beim nächsten Boot wird für diese 3 User dann der Dienst gestartet und für jeden user mit dessen UID ausgeführt.

Hast du die Möglichkeit, dass deine Anwendung das Zustandsfile in ein von dir zu konfigurierendes Verzeichnis schreiben kann? Dann kannst du nämlich noch die Möglichkeit des RuntimeDirectory in der Systemd-Unit nutzen.
Dazu ergänzt du im Abschnitt [Service]

Code: Alles auswählen

[Service]
...
RuntimeDirectory=test-%i
Dann wird unter /var/run für deine drei User jeweils das Verzeichnis test-fritz test-franz und test-hannelore angelegt. Dort hinein kannst du dann das Zustandsfile schreiben lassen.
Wird der Dienst beendet, wird dieses RuntimeDirectory defaultmäßig gelöscht. Das bedeutet, wenn der Rechner runtergefahren wird, wird eine Anwendung gekillt und das Zustandsfile ist automatisch gelöscht. Beim nächsten Boot (und damit wenn das nächste mal der Dienst gestartet wird) findet die Anwendung ein jungfräulich leeres RuntimeDirectory vor und es kann ein frisches Zustandfile anlegen.

Wenn die Anwendung regelmäßig aufgerufen werden soll, kannst du dir eine Timer-Unit bauen und noch ein Target zwischen die Timerunit und deine Service-Files schalten. Das kann ich dir gerne zeigen. Wenn zwischen diesen Runs das Zustandsfile erhalten bleiben muss (davon gehe ich aus), muss wohl noch eine Unit mit dem Start des Timers gestartet werden, welche läuft, solange der Timer aktiv ist, und die dieses RuntimeDirectory herstellt. Da muss ich noch nachdenken, hab aber schon eine Idee dazu.

Aber ich les gerade, dass die Option RuntimeDirectoryPreserve=yes das Runtimedirectory auch nach einem Stop des Serivces erhält. /run und /var/run ist ein tmpfs und wird beim Shutdown gelöscht. Das heißt, so wie die Serviceunit oben ist, um die Option ergänzt, lässt deine Zustandsfile leben, solange der Rechner gebootet bleibt. Beim Shutdown ist es dann automatisch weg und wird beim ersten Run des Services wieder angelegt.

Du musst mir jetzt also nur noch sagen, ob die Anwendung die Möglichkeit hat, das Zustandsfile in ein bestimmtes Verzeichnis abzulegen (am besten per Commandline-Option).
Die timer-Unit und das zugehörige Target, welches dann die Services startet, ist einfach. Das zeigt ich dir nachher, wenn wir abgeklärt haben, ob das für dich überhaupt passt.

Ist da etwas dabei, das interessant für dich klingt? (Auch wenns momentan grad äußerst komplex klingt... ist es aber nicht. Ich helf dir gerne!!)

lg scientific
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

scientific
Beiträge: 3020
Registriert: 03.11.2009 13:45:23
Lizenz eigener Beiträge: Artistic Lizenz
Kontaktdaten:

Re: Prozess beim shutdown noch zu Ende laufen lassen

Beitrag von scientific » 05.02.2018 11:46:05

Hab nochmal dein Eingangspost gelesen.
Wenn du in der Systemd-Unit im Abschnitt [Service] noch Type=oneshot einfügst, dann wird der nächste Serivce erst ausgeführt, wenn dieser Service beendet wurde. Das kann natürlich ungute Verzögerungen verursachen, wenn diese Unit ungünstige Abhängigkeiten verursacht. Kann aber auch das erfolgreiche Beenden beim Shutdown bedingen, bevor die Maschine ausgeschaltet wird.
dann putze ich hier mal nur...

Eine Auswahl meiner Skripte und systemd-units.
https://github.com/xundeenergie

auch als Debian-Repo für Testing einbindbar:
deb http://debian.xundeenergie.at/xundeenergie testing main

Antworten