[gelöst] shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
smutbert
Beiträge: 8342
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

[gelöst] shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von smutbert » 12.06.2020 23:53:39

Hallo liebe Shellfreunde,


bei einem interaktiven Skript möchte ich verhindern, dass es mehrmals gleichzeitig läuft. Deshalb lege ich eine Datei an und überprüfe beim Start ob sie bereits existiert und versuche dafür zu sorgen, das bei allen Eventualitäten, die zum Beenden des Skripts führen, die Datei gelöscht wird

Code: Alles auswählen

mypid=${$}
pidfile="${XDG_RUNTIME_DIR}/meinSkript.pid"

function exit_script {
	rm "${pidfile}"
	kill -s TERM ${mypid}
}

trap "exit_script" TERM

test -f "${pidfile}" && exit 1
echo "${mypid}" > "${pidfile}"
Soweit bekäme ich das noch ohne Hilfe zum Laufen, aber es gibt noch eine Anforderung:
Am Ende des Skripts soll ein Befehl gestartet werden und zwar so, dass sich Skript/Shell und Terminalemulator beenden, aber der Befehl weiterläuft.

Immer funktioniert irgendein Teil des ganzen nicht, abhängig davon ob ich den Befehl mit exec, &, &+nohup oder Subshell+& und zum Teil zusätzlich mit disown versuche. Einzig die Kombination

Code: Alles auswählen

(nohup "${befehl}" &)
rm "${pidfile}"
exit
hat bis jetzt funktioniert, aber auch nur solange ich die Ausgabe nicht umleite und in der nohup.out kann ich damit eigentlich nichts anfangen (sogar /dev/null wäre mir lieber, aber es muss halt verlässlich funktionieren sowohl für grafische Anwendungen wie auch für Befehle wie zB systemctl reboot).

Ich verstehe nicht wieso ich beim Starten von $befehl eine Subshell brauche.
Gibt es außerdem möglicherweise eine einfachere Möglichkeit beim Beenden aufzuräumen, als ein Signal abzufangen?


lg Philipp
Zuletzt geändert von smutbert am 15.06.2020 11:15:37, insgesamt 1-mal geändert.

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

Re: shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von MSfree » 13.06.2020 00:02:58

Ich werfe mal flock in die Runde.

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

Re: shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von tobo » 13.06.2020 12:47:04

Ich glaube, ich habe da einiges noch nicht verstanden:
-Ist diese kill-Zeile im exit_script nicht überflüssig oder sogar kontraproduktiv?
-Das 2. Quoting ist dann praktisch der neue Inhalt von exit_script?
-Wo schließt sich bei dir der Terminalemulator?
-Mit Ausgabe umleiten ist die Ausgabe von ${befehl} gemeint?
-Wenn ich jetzt z.B. so eine exit_script-Funktion habe:

Code: Alles auswählen

function exit_script {
    nohup  find / -type f -exec grep "asdf" {} \; > "${HOME}/test.txt" &
    rm "${pidfile}"
    kill -9 $PPID
   # kill -s TERM ${mypid} ## ist das nicht unnötig?
}
dann funktioniert das warum nicht?

Benutzeravatar
smutbert
Beiträge: 8342
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von smutbert » 13.06.2020 15:00:16

tobo hat geschrieben: ↑ zum Beitrag ↑
13.06.2020 12:47:04
[...]
-Ist diese kill-Zeile im exit_script nicht überflüssig oder sogar kontraproduktiv?
ich bin für jegliche Vorschläge offen, aber wüsste nicht wie ich sonst aus einer Funktion heraus das ganze Skript beenden könnte - exit würde ja nur die Funktion beenden.
tobo hat geschrieben: ↑ zum Beitrag ↑
13.06.2020 12:47:04
-Das 2. Quoting ist dann praktisch der neue Inhalt von exit_script?
Nein, das ist eine Variante der letzten Zeilen meines Skriptes, die ein Programm starten sollen (das weiterläuft), die pid-Datei löschen und das Skript beenden sollen.
tobo hat geschrieben: ↑ zum Beitrag ↑
13.06.2020 12:47:04
-Wo schließt sich bei dir der Terminalemulator?
Er soll sich am Ende schließen. Zuerst hatte ich es am Ende mit exec zum Start des Programms ($befehl) versucht, aber das beendet die Shell ja nicht normal sondern ersetzte die Shell sozusagen durch $befehl und das hat, zumindest beim Gnome-Terminal, zur Folge das das Terminal weiterläuft bis $befehl beendet wird.
tobo hat geschrieben: ↑ zum Beitrag ↑
13.06.2020 12:47:04
-Mit Ausgabe umleiten ist die Ausgabe von ${befehl} gemeint?
Ja, zum Beispiel funktioniert das hier im Prinip, aber erstellt mir aber wie gesagt die unerwünschte nohup,out

Code: Alles auswählen

(nohup "${befehl}" &)
aber das hier funktioniert nicht mehr, sondern $befehl wird mit dem Ende des Skripts sofort wieder geschlossen:

Code: Alles auswählen

(nohup "${befehl}" > dev/null &)
tobo hat geschrieben: ↑ zum Beitrag ↑
13.06.2020 12:47:04
-Wenn ich jetzt z.B. so eine exit_script-Funktion habe:
Das versteh ich nicht auf Anhieb, das muss ich erst noch einmal durchdenken. Auf Anhieb ist mir das Killen von $PPID unklar, das ist ja der Eltern-/Vater/Mutterprozess vom Skript (keine Ahnung wer das ist, vielleicht gnome-terminal oder irgendein gnome-eigener Dämon falls ich mein Skript per hotkey aufrufe)?


flock sieht aber sehr praktisch aus. Das werde ich gleich versuchen und ich ahne, dass ich damit zumindest einen Großteil meines Problems automatisch los bin.

Edit:
Könnte mir vielleicht jemand dieses Beispiel von https://blog.famzah.net/2013/07/31/usin ... -subshell/ erklären. Ich steige gleich bei der Zeile mit exec {lock_fd}>... aus (der Rest wär kein Problem).

Code: Alles auswählen

#!/bin/bash
 
exec {lock_fd}>/var/lock/mylockfile || exit 1
flock -n "$lock_fd" || { echo "ERROR: flock() failed." >&2; exit 1; }
 
# ... commands executed under lock ...
 
flock -u "$lock_fd"

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

Re: shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von tobo » 13.06.2020 16:24:18

smutbert hat geschrieben: ↑ zum Beitrag ↑
13.06.2020 15:00:16
Edit:
Könnte mir vielleicht jemand dieses Beispiel von https://blog.famzah.net/2013/07/31/usin ... -subshell/ erklären. Ich steige gleich bei der Zeile mit exec {lock_fd}>... aus (der Rest wär kein Problem).
Schau' mal (im Link) in den Kommentaren darunter.
ich bin für jegliche Vorschläge offen, aber wüsste nicht wie ich sonst aus einer Funktion heraus das ganze Skript beenden könnte - exit würde ja nur die Funktion beenden.
Hier liegt vermutlich mein Verständnisfehler!? Ich hatte TERM ergänzt mit exit, da stand dann also dann sowas: trap "exit_script" TERM exit und dachte, dass in einer Endversion eher noch sowas da steht: trap "exit_script" 0 1 2 3 6 15. Sprich, das ist die Funktion, die aufgerufen wird, wenn das Skript beendet. Somit wird dort auch 1. aufgeräumt (rm PidFile), 2. Elternprozess abgeschossen (sagtest du) und 3. $befehl ausgeführt (in meinem Beispiel find). Ich hatte das so verstanden, dass diese 3 Dinge dann passieren, wenn das Programm beendet (egal wie).

Aber womöglich hat sich das ja alles mit diesem flock erledigt. Keine Ahnung, was das so kann!?

Benutzeravatar
Tintom
Moderator
Beiträge: 3069
Registriert: 14.04.2006 20:55:15
Wohnort: Göttingen

Re: shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von Tintom » 13.06.2020 17:17:13

smutbert hat geschrieben: ↑ zum Beitrag ↑
12.06.2020 23:53:39
Am Ende des Skripts soll ein Befehl gestartet werden und zwar so, dass sich Skript/Shell und Terminalemulator beenden, aber der Befehl weiterläuft.
Also möchtest du vereinfacht gesagt ein Programm, dass losgelöst von der jeweiligen Sitzung läuft? Ähnlich wie ein Systemdämon? Dafür würde ich start-stop-daemon aus den init-Skripten mit dem Schalter -b missbrauchen, z.B.:

/sbin/start-stop-daemon --start --quiet --oknodo -b --pidfile <pidfile> --exec <skript>

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

Re: shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von uname » 13.06.2020 17:47:53

Schau dir screen und tmux an. Z.B. wie Minecraft-Server laufen.

Benutzeravatar
smutbert
Beiträge: 8342
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von smutbert » 13.06.2020 23:30:09

Mit Dämonen hat mein Anwendungsfall eigentlich nichts zu tun. Das Skript soll vor allem Anwendungen starten, ungefähr so
  1. eine Tastenkombination startet ein Terminal, das das Skript ausführt
  2. das Skript listet ausführbare Dateien aus $PATH zwischen denen gewählt werden kann
  3. auf <Enter> wird das ausgewählte Element der Liste ausgeführt und Skript und Terminal verschwinden wieder (beenden sich)
Da dürfte dann auch klar sein wieso ich nicht will, dass eine zweite Instanz von dem Skript startet, aber das lässt sich mit flock wirklich einfach verhindern.

Mit dem letzten Schritt kämpfe ich immer noch. Was mir momentan nicht einleuchten will, ist dass zwar

Code: Alles auswählen

(nohup systemd-cat "$befehl" &)
disown
funktioniert (und eine unerwüschnte nohup.out erstellt), nicht aber

Code: Alles auswählen

(nohup systemd-cat "$befehl" > /dev/null &)
disown
(und auch wieso keines von beidem ohne Subshell funktioniert)
(ich habe für den letzten Schritt jetzt sogar start-stop-daemon ausprobiert und das funktioniert, kommt mir aber sehr merkwürdig vor)

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

Re: shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von Meillo » 14.06.2020 15:40:30

smutbert hat geschrieben: ↑ zum Beitrag ↑
13.06.2020 23:30:09
  1. eine Tastenkombination startet ein Terminal, das das Skript ausführt
  2. das Skript listet ausführbare Dateien aus $PATH zwischen denen gewählt werden kann
  3. auf <Enter> wird das ausgewählte Element der Liste ausgeführt und Skript und Terminal verschwinden wieder (beenden sich)
Diese Beschreibung hoert sich fuer mich wie dmenu an (in Debiansuckless-tools) ...
Use ed once in a while!

Benutzeravatar
smutbert
Beiträge: 8342
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von smutbert » 14.06.2020 23:45:15

Stimmt, aber meine Beschreibung war unvollständig ☺

Ich wollte etwas wayland-natives und außerdem bietet das Skript glaube ich mehr Funktionen als sie mit dmenu möglich wären (die Einträge der Liste werden entsprechend der Eingabe gefiltert und das Eingeben von Kommandozeilen wie »systemctl restart« funktioniert genauso.)
Das Skript habe ich bei meinen Abenteuern mit sway kennengelernt, es ist einfach genug, dass ich es fast vollständig verstehe und ich wollte es jetzt unter Gnome ausprobieren. sway bietet aber einen eigenen Befehl zum Starten von Programmen (losgelöst von der Sitzung), der mir unter Gnome fehlt.

Hier habe ich ein sehr ähnliches Skript gefunden: https://github.com/Biont/sway-launcher-desktop das mindestens genausogut aussieht und unabhängig vom Windowmanager funktioniert. Den Befehl zum Starten des Programms habe ich mir nun „ausgeborgt“, er sieht (angepasst, bei mir) so aus

Code: Alles auswählen

(exec setsid /bin/sh -c "$befehl" &>/dev/null &)
disown
(ich finde es fast beunruhigend welche Umwege notwendig sind, damit das von der Sitzung losgelöste Starten einwandfrei funktioniert)

Vielen Dank für eure Hilfe und Vorschläge und ganz besonders fürs Bekanntmachen mit flock.
Ich lese aber gerne noch interessiert, falls mir jemand eine Idee hat warum das mit nohup und disown nur ohne Ausgabeumleitung funktioniert ☺

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

Re: shell, bash - launcher Skript mit Funktion zum Beenden des Skripts

Beitrag von Meillo » 15.06.2020 09:50:43

smutbert hat geschrieben: ↑ zum Beitrag ↑
14.06.2020 23:45:15
Stimmt, aber meine Beschreibung war unvollständig ☺

Ich wollte etwas wayland-natives und außerdem bietet das Skript glaube ich mehr Funktionen als sie mit dmenu möglich wären (die Einträge der Liste werden entsprechend der Eingabe gefiltert und das Eingeben von Kommandozeilen wie »systemctl restart« funktioniert genauso.)
Filterung kann dmenu, auch kann man die Befehle um Parameter ergaenzen oder was ganz anderes eingeben. Diese Features waeren erfuellt. Das aber nur nebenbei.
Use ed once in a while!

Antworten