[erledigt]Script zum checken und neu starten beendet sich nicht

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
oln
Beiträge: 553
Registriert: 05.01.2021 09:41:24

[erledigt]Script zum checken und neu starten beendet sich nicht

Beitrag von oln » 12.02.2025 15:20:17

Hallo Forum,
ich habe ein Script was als Cronjob läuft.

Code: Alles auswählen

#!/bin/bash

if [ -z ${MB_JETTY_PORT+x} ]; then export MB_JETTY_PORT=1025; else echo "var is set to '$MB_JETTY_PORT'"; fi
if [ -z ${MB_DB_TYPE+x} ]; then export MB_DB_TYPE=mysql; else echo "var is set to '$MB_DB_TYPE'"; fi
if [ -z ${MB_DB_CONNECTION_URI+x} ]; then export MB_DB_CONNECTION_URI=jdbc:mysql://server:3306/metabase?user=dbuser_meta&password=geheim; else echo "var is set to '$MB_DB_CONNECTION_URI'"; fi


check_process() {
  [ "$1" = "" ]  && return 0
  [ $(pgrep -f $1) ] && return 1 || return 0
}

cd /usr/home/user/public_html/metabase/

check_process "metabase.jar"

[ $? -eq 0 ] && echo "$(date) : Metabase not running, restarting..." &&  $(/home/user/bin/jdk-23.0.2/bin/java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar ) &
Das macht was es soll. Nur beendet sich das Script wenn ich es händisch ausführe nicht. Wo ist das Problem?
Zuletzt geändert von oln am 19.02.2025 09:48:31, insgesamt 2-mal geändert.
Gruß Ole
AbuseIPDB

Benutzeravatar
Meillo
Moderator
Beiträge: 9296
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von Meillo » 12.02.2025 15:24:11

`set -x' hilft beim Debuggen. Dann kannst du sehen, welche Befehle ausgefuehrt werden und du siehst, bei welchem das Script haengen bleibt.
Use ed once in a while!

Benutzeravatar
oln
Beiträge: 553
Registriert: 05.01.2021 09:41:24

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von oln » 12.02.2025 15:34:46

Danke für den Hinweis. Wenn Metabase läuft und nur der Check gemacht wir, dann beendet sich das Script. Irgendwie scheint das Problem daran zu liegen, metabase in den Hintergrund zu schicken.
Gruß Ole
AbuseIPDB

Benutzeravatar
oln
Beiträge: 553
Registriert: 05.01.2021 09:41:24

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von oln » 19.02.2025 08:41:16

Moin,
leider bringt mich "set -x" nicht weiter. Ich bekomme da die Ausgabe "+ /pfad/zum/script/script.sh".
Irgend etwas lässt das Script nicht beenden. Sieht es jemand von euch?
Gruß Ole
AbuseIPDB

Benutzeravatar
Meillo
Moderator
Beiträge: 9296
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von Meillo » 19.02.2025 08:44:31

oln hat geschrieben: ↑ zum Beitrag ↑
19.02.2025 08:41:16
Moin,
leider bringt mich "set -x" nicht weiter. Ich bekomme da die Ausgabe "+ /pfad/zum/script/script.sh".
Irgend etwas lässt das Script nicht beenden.
Du bist noch eine Ebene zu hoch. Du solltest das `set -x' dann *in* dieses Script einbauen, damit du siehst, *wo* in diesem Script es haengen bleibt. ;-)
Use ed once in a while!

tobo
Beiträge: 2457
Registriert: 10.12.2008 10:51:41

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von tobo » 19.02.2025 08:58:21

oln hat geschrieben: ↑ zum Beitrag ↑
19.02.2025 08:41:16
Moin,
leider bringt mich "set -x" nicht weiter.
Schau' dir mal die letzte Zeile an: $(...)& sollte wohl (...)& oder gleich ... & sein!?

Benutzeravatar
oln
Beiträge: 553
Registriert: 05.01.2021 09:41:24

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von oln » 19.02.2025 09:15:30

Moin,
danke nochmal.
Das Script bleibt bei diesem Befehl hängen:

Code: Alles auswählen

$(/home/user/bin/jdk-23.0.2/bin/java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar )
Nur warum? Starten tut er den Befehl. Läuft aber nicht weiter.
Gruß Ole
AbuseIPDB

Benutzeravatar
Meillo
Moderator
Beiträge: 9296
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von Meillo » 19.02.2025 09:25:01

Meist ist das Debuggen einfacher, wenn man den Code vereinfacht. Statt:

Code: Alles auswählen

check_process "metabase.jar"

[ $? -eq 0 ] && echo "$(date) : Metabase not running, restarting..." &&  $(/home/user/bin/jdk-23.0.2/bin/java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar ) &
Besser:

Code: Alles auswählen

check_process "metabase.jar" || exit

echo "$(date) : Metabase not running, restarting..."
/home/user/bin/jdk-23.0.2/bin/java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar &
Ich habe auch die unnoetige Kommandosubstitution um den Java-Befehl entfernt, wie auch tobo schon empfohlen hat.
Use ed once in a while!

Benutzeravatar
MSfree
Beiträge: 11759
Registriert: 25.09.2007 19:59:30

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von MSfree » 19.02.2025 09:33:15

Wäre es nicht viel sinnvoller, das ganze in eine Systemd-Unit zu packen? Die beherrschen das Neustarten eines Prozesses von sich aus, ohne diese kuriose Verrenkung über cron.

Über systemd startet ein Programm immer genau dann neu, wenn es sich beendet hat oder abgestürzt ist. Da muß man nicht über den höchst ineffektiven Weg gehen, abzufragen, ob ein Prozeß noch läuft. Alles, was es dazu braucht, ist die Zeile

Code: Alles auswählen

Restart=always
in der Unit.

Benutzeravatar
oln
Beiträge: 553
Registriert: 05.01.2021 09:41:24

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von oln » 19.02.2025 09:48:02

Danke, dass hatte ich auch schon probiert. Aber nun klappt alles.
Gruß Ole
AbuseIPDB

Benutzeravatar
oln
Beiträge: 553
Registriert: 05.01.2021 09:41:24

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von oln » 19.02.2025 09:49:29

MSfree hat geschrieben: ↑ zum Beitrag ↑
19.02.2025 09:33:15
Wäre es nicht viel sinnvoller, das ganze in eine Systemd-Unit zu packen? Die beherrschen das Neustarten eines Prozesses von sich aus, ohne diese kuriose Verrenkung über cron.

Über systemd startet ein Programm immer genau dann neu, wenn es sich beendet hat oder abgestürzt ist. Da muß man nicht über den höchst ineffektiven Weg gehen, abzufragen, ob ein Prozeß noch läuft. Alles, was es dazu braucht, ist die Zeile

Code: Alles auswählen

Restart=always
in der Unit.
Ja wäre sinnfoller. Aber ein ManagedServer. Da kann ich nichts tun.
Gruß Ole
AbuseIPDB

Benutzeravatar
Meillo
Moderator
Beiträge: 9296
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Script zum checken und neu starten beendet sich nicht

Beitrag von Meillo » 19.02.2025 09:49:39

oln hat geschrieben: ↑ zum Beitrag ↑
19.02.2025 09:48:02
Aber nun klappt alles.
Das freut mich.

Was genau hat den Unterschied gemacht?
Use ed once in a while!

Benutzeravatar
oln
Beiträge: 553
Registriert: 05.01.2021 09:41:24

Re: [erledigt]Script zum checken und neu starten beendet sich nicht

Beitrag von oln » 19.02.2025 10:25:24

Tja ich habe nur eure Kürzungen im Script vorgenommen.
Dann ging es auf einmal.
Gruß Ole
AbuseIPDB

Benutzeravatar
Meillo
Moderator
Beiträge: 9296
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: [erledigt]Script zum checken und neu starten beendet sich nicht

Beitrag von Meillo » 19.02.2025 10:42:24

oln hat geschrieben: ↑ zum Beitrag ↑
19.02.2025 10:25:24
Tja ich habe nur eure Kürzungen im Script vorgenommen.
Dann ging es auf einmal.
Ich finde so ein ``dann ging's auf einmal'' ja immer hoechst unbefriedigend und wuerde den konkreten Grund immer herausfinden wollen. Also die Aenderungen schrittweise wieder zurueck zu bauen, um herauszufinden, welche Aenderung genau den Unterschied gemacht hat. Ich denke mir: Wenn ich nicht verstehe, warum genau es in einem Fall funktioniert und im anderen nicht, dann kann ich mir auch nicht sicher sein, dass das Problem nun geloest ist. Ich wuerde schon wissen wollen, ob ich nur irgend ein Symptom entfernt haben oder ob ich die Quelle beseitigt habe. Und in dem Zuge wuerde ich auch wissen wollen, was genau die Quelle war, damit ich daraus lernen kann und mein Wissen mehre. Damit gewinne ich Kontrolle und Verstehen ueber das System.

... ausserdem macht es die Mithelfenden hier im Forum gluecklich wenn sie durch die Mithilfe ihr Wissen aufbauen koennen, indem sie etwas zurueck bekommen und nicht nur Tipps reinstecken. Das hilft dabei, dass einem beim naechsten Mal wieder geholfen wird und man nicht auf Ignorelisten landet, weil es frustrierend ist, zu helfen und nicht zu erfahren, was geholfen hat. ;-)



Meine Vermutung ist, dass es an der Kommandosubstitution (in Verbindung mit dem Hintergrund-&) liegt. Eine Kommandosubstitution bedeutet ja, dass der Befehl ausgefuehrt wird und seine Ausgabe an die Stelle im Script gesetzt wird. Solange das nicht erledigt ist, kann das Script eigentlich nicht weiter machen, weil es die Ausgabe ja vielleicht im weiteren Scriptverlauf braucht. Daran koennte es liegen, dass es blockiert, statt den Befehl in den Hintergrund zu legen und einfach weiterzumachen. Allerdings haben alle meine Versuche mit

Code: Alles auswählen

$( sleep 300 ) &
funktioniert, d.h. das Script hat sich beendet und der Sleep ist im Hintergrund weitergelaufen, egal ob mit bash oder mksh. Folglich muss es doch noch an etwas anderem liegen.

Welche Shell genau wird bei dir denn verwendet?
Use ed once in a while!

Benutzeravatar
oln
Beiträge: 553
Registriert: 05.01.2021 09:41:24

Re: [erledigt]Script zum checken und neu starten beendet sich nicht

Beitrag von oln » 19.02.2025 11:17:36

Meillo hat geschrieben: ↑ zum Beitrag ↑
19.02.2025 10:42:24
Meine Vermutung ist, dass es an der Kommandosubstitution (in Verbindung mit dem Hintergrund-&) liegt. Eine Kommandosubstitution bedeutet ja, dass der Befehl ausgefuehrt wird und seine Ausgabe an die Stelle im Script gesetzt wird. Solange das nicht erledigt ist, kann das Script eigentlich nicht weiter machen, weil es die Ausgabe ja vielleicht im weiteren Scriptverlauf braucht. Daran koennte es liegen, dass es blockiert, statt den Befehl in den Hintergrund zu legen und einfach weiterzumachen. Allerdings haben alle meine Versuche mit

Code: Alles auswählen

$( sleep 300 ) &
funktioniert, d.h. das Script hat sich beendet und der Sleep ist im Hintergrund weitergelaufen, egal ob mit bash oder mksh. Folglich muss es doch noch an etwas anderem liegen.

Welche Shell genau wird bei dir denn verwendet?
Ich benutze die Bash. Genau daran lag es. Ich habe die Kommandosubstitution zum Test wieder eingebaut und hatte das selbe Problem wie vorher. Also ohne dem geht es.
Gruß Ole
AbuseIPDB

Benutzeravatar
heisenberg
Beiträge: 4158
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: [erledigt]Script zum checken und neu starten beendet sich nicht

Beitrag von heisenberg » 19.02.2025 12:25:39

Auch wenn es Dich - ole - vermutlich nicht interessiert und Du das Script auch nicht erstellt hast, möchte ich zu dem Script unabhängig von der Hauptfragestellung hier nochmal kommentieren als Beitrag für die allgemeine Diskussion darüber.

Das Script enthält einen kritischen Fehler:

Code: Alles auswählen

MB_DB_CONNECTION_URI=jdbc:mysql://server:3306/metabase?user=dbuser_meta&password=geheim
Das fehlende Quoting ist hier kritisch und sorgt dafür, dass die Variablenzuweisung aufgrund es enthaltenen & in den Hintergrund gesetzt wird. D. h. in der aktuellen Shell wird die Variable nicht verändert. Zusätzlich wird die Variable im Hintergrund nur auf einen Teil des Wertes gesetzt, weil & das Befehlsende bestimmt. Der Befehl ist also doppelt kaputt. So tut es das, was es soll:

Code: Alles auswählen

MB_DB_CONNECTION_URI="jdbc:mysql://server:3306/metabase?user=dbuser_meta&password=geheim"
Insgesamt ist dieses Script für mich auf eine Weise geschrieben, was es trotz der Kürze sehr schlecht lesbar macht:
  1. Die Zeilen sind recht lange
  2. If-Abfragen sind komplett in einer Zeile
  3. Befehlsverkettung per && kombiniert mehrere Befehle in einer Zeile
  4. Überflüssige Konstrukte
Die Zeilen sind zu lang

Mir scheint, der Autor des Scriptes empfindet es als einfacher lesbar, wenn das Programm weniger Zeilen hat, Für mich erschwert es das lesen. Die Aufteilung auf mehrere Zeilen ließe eine Struktur erkennen und deswegen ließe sich der Inhalt leichter erfassen. Bei einem großen Bildschirm mag das noch nicht ganz so nervig sein. Wenn der aber etwas kleiner ist, dann mit Sicherheit.

Grundsätzlich verwende ich auch Kombinationen von Befehlen in einer Zeile. Ich tue das aber nur, wenn die Zeile trotzdem kurz bleibt. So etwas würde ich z. b. schreiben:

Code: Alles auswählen

[ -d $VERZEICHZNIS ] || mkdir "$VERZEICHNIS"
... oder das schon erwähnte ...

Code: Alles auswählen

check_process "metabase.jar" || exit
If-Abfragen sind komplett in einer Zeile

Das sorgt auch dafür, dass man länger braucht, um den Inhalt unmittelbar zu erfassen. Was gehört jetzt zum Then-Zweig? Was gehört zum Else-Zweig? Bei einer Aufteilung in einzelne Zeilen kann man das schneller erfassen

Vergleicht selbst!

In einer Zeile:

Code: Alles auswählen

if [ -z ${MB_DB_CONNECTION_URI+x} ]; then export MB_DB_CONNECTION_URI="jdbc:mysql://server:3306/metabase?user=dbuser_meta&password=geheim"; else echo "var is set to '$MB_DB_CONNECTION_URI'"; fi
Aufgeteilt:

Code: Alles auswählen

if [ -z ${MB_DB_CONNECTION_URI+x} ]; then 
	export MB_DB_CONNECTION_URI="jdbc:mysql://server:3306/metabase?user=dbuser_meta&password=geheim"; 
else 
	echo "var is set to '$MB_DB_CONNECTION_URI'"
fi
Befehlsverkettung per && kombiniert mehrere Befehle in einer Zeile

Das Verketten von Befehlen führt auch zur Zeilenverlängerung und führt zusätzlich eine weitere Fehlerquelle ein: Befehle, die keine Ausführungsprüfung erfordern, werden jetzt geprüft:

Code: Alles auswählen

check_process "metabase.jar"
[ $? -eq 0 ] && echo "$(date) : Metabase not running, restarting..." &&  $(/home/user/bin/jdk-23.0.2/bin/java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar ) &
Wenn der echo Befehl fehlschlägt, wird der anschließende Java-Aufruf nicht ausgeführt. Ist hier nicht schlimm, weil echo wahrscheinlich nicht fehlschlagen wird. Aber wenn man sich so etwas angewöhnt, dann kommt irgendwann der Punkt, an dem so etwas bricht.

Wenn man das so haben möchte, könnte man das so coden - also mit geschweiften Klammern als Gruppierungsmethode (habe ich auch schon so gemacht):

Code: Alles auswählen

[ $? -eq 0 ] && { echo "..." ; java ... ; }
Oder als normale If-Abfrage:

Code: Alles auswählen

if check_process "metabase.jar" ; then
   echo "$(date) : Metabase not running, restarting..."
   /home/user/bin/jdk-23.0.2/bin/java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar
fi
Überflüssige Konstrukte

So ein Konstrukt empfinde ich als umständlich:

Code: Alles auswählen

[ $(pgrep -f $1) ] && return 1 || return 0
Es wird unnötigerweise ein zusätzlicher Prozess erzeugt. Der Rückgabewert wird explizit abgefragt und neu gesetzt. Das folgende hätte den fast gleichen Effekt:

Code: Alles auswählen

pgrep -f $1 &>/dev/null
Da der Befehl am Ende der Funktion steht, wird sein Exit-Code als Exit-Code der Funktion zurück gegeben. Die Ausgabe wird unterdrückt. Fast gleich bedeutet, dass im Original nur 0 oder 1 zurück gegeben wird, während meine Version den Exit-Code von pgrep zurück liefert und der kann 0, 1, 2 oder 3 sein. Das dürfte aber keinen Unterschied machen, da die Unix-Philosophie hier ist: 0 => OK !0 => Fehler

Damit der Code wartbarer wird, schreibe ich meist:

Code: Alles auswählen

pgrep -f $1 &>/dev/null
return $?
Damit wird er implizite Rückgabewert von pgrep explizit. Nicht alle Funktionen nutzen Rückgabewerte. So wird man darauf aufmerksam gemacht, dass der Rückgabewert wichtig ist und wenn man die Funktion später erweitert, fällt einem das sofort auf. Ansonsten hängt man vielleicht einen Befehl an und übersieht, dass der wichtige Rückgabewert dabei überschrieben wird.

(Es gäbe grundsätzlich noch mehr zu schreiben...)

Benutzeravatar
oln
Beiträge: 553
Registriert: 05.01.2021 09:41:24

Re: [erledigt]Script zum checken und neu starten beendet sich nicht

Beitrag von oln » 20.02.2025 09:14:00

heisenberg hat geschrieben: ↑ zum Beitrag ↑
19.02.2025 12:25:39
Auch wenn es Dich - ole - vermutlich nicht interessiert und Du das Script auch nicht erstellt hast, möchte ich zu dem Script unabhängig von der Hauptfragestellung hier nochmal kommentieren als
Danke für deine Einordnung des Scriptes. Du hast recht, dass ich es nicht geschrieben habe. Aber woraus war das ersichtlich?

Ich habe das Script jetzt etwas aufgeräumt und den Fehler bei der Variablenzuweisung gefixt. Das ist noch überhaupt nicht aufgefallen. Somit konnte das Starten von Metabase niemals funktionieren. Denn ohne ConnectionUri startet das nicht. Ich wende mich mal an den User der das benötigt.
Danke.
Gruß Ole
AbuseIPDB

tobo
Beiträge: 2457
Registriert: 10.12.2008 10:51:41

Re: [erledigt]Script zum checken und neu starten beendet sich nicht

Beitrag von tobo » 20.02.2025 11:10:42

Will man das selbst überprüfen, dann funktioniert das detailreich mit Shellcheck:

Code: Alles auswählen

$ shellcheck skript.sh
Neben Position, Fehlerindex und Kurzbeschreibung aller Fehler im Skript finden sich dort abschließend auch Links zu ausführlicheren Beschreibungen. Wiki+Fehlerindex bei z.B. dem "&"-Fehler:
https://www.shellcheck.net/wiki/SC1132

Benutzeravatar
heisenberg
Beiträge: 4158
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: [erledigt]Script zum checken und neu starten beendet sich nicht

Beitrag von heisenberg » 20.02.2025 14:56:46

oln hat geschrieben: ↑ zum Beitrag ↑
20.02.2025 09:14:00
Du hast recht, dass ich es nicht geschrieben habe. Aber woraus war das ersichtlich?
Du schriebst, dass das ein Managed-Server ist und dass Du dieses metabase nicht (ungefragt|unbezahlt) auf systemd umschreiben (darfst|willst). Da vermutete ich, dass Du das auch nicht selbst aufgesetzt hast.

Antworten