staging.inyokaproject.org

wird ein bash-script bei internen Programmaufruf "sauber" beendet?

Status: Gelöst | Ubuntu-Version: Kubuntu 22.04 (Jammy Jellyfish)
Antworten |

kdeNoob

Anmeldungsdatum:
9. Oktober 2018

Beiträge: 63

Hallo, ich vermute, mein Script ist keine "saubere" Lösung für den automatischen Start von smb4k? Das nachfolgende Script habe ich dem Autostart hinzugefügt. (Systemeinstellung>Starten und Beenden>Autostart>Hinzufügen>Anwendung-–>ScriptName [Eigentümer rwx]).

Wird das Script wieder geschlossen,trotz offenem "smb4k" und macht eine echo-Ausgabe im Script ohne Terminal überhaupt Sinn? Kann das mit dem Code funktionieren oder benötige ich einen anderen Ansatz?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash -e

# Skript-Name: XConnectHost.sh
# Startabfrage, ob Netzgerät aktiv ist oder im standby-Modus
# wenn ja, wird smb4k ausgeführt und das Netzlaufwerk per smb4k-Lesezeichen eingebunden

Host="192.168.178.45"
# explizite IPV4-Adresse vom Netzlaufwerk
sleep 5
# verzögere die Anfrage bis Linux alle Dienste vollständig geladen hat, da Skript im Autostart steht!

ping -c1 $Host  &&> /dev/null
pingReturn=$?
#echo "Rückgabewert: $pingReturn"

# ($?-übergibt den Status 0 oder 1)
if [ $pingReturn == 0 ]
 then
   /usr/bin/smb4k &
#   smb4k mit "&" im Hintergrund
#   bei mount.cifs $Host /"lokaler Pfad" ist user+pw erforderlich, smb4k holt das aus KWallet!
   exit 0
 else
   echo  "do nothing"
   exit 1
fi

Dank im Voraus für hilfreiche Kommentare Noob

Bearbeitet von rklm:

Syntaxhighlighting

wxpte

Anmeldungsdatum:
20. Januar 2007

Beiträge: 1388

Zwar kenne ich das spezielle Programm smb4k nicht, aber ein paar allgemeine Hinweise hätte ich schon:

Erstens:
Die Umleitung &&> ist nicht korrekt, vielmehr muss es

ping -c1 $Host > /dev/null

heißen.

Zweitens:
Insgesamt halte ich das Skript für etwas zu umständlich: es ist gar nicht nötig, zunächst mit den Rückgabewerten herumzuhantieren. Vielmehr reicht ein

1
2
3
if ping -c1 $Host > /dev/null
 then
   ...

vollkommen aus. Außerdem: wofür benötigst du exit 0 und exit 1?

Drittens:
Ja, das Skript wird geschlossen, sobald es durchgelaufen ist, da du smb4k ja im Hintergrund startest.

Viertens:
So, wie du echo hier verwendest, ergibt es in der Tat keinen Sinn: wenn ein Skript über Autostart (oder Cronjob, oder Timer Unit) gestartet wird, dann siehst du ja nichts davon. Du könntest die Ausgabe statt dessen aber in ein Logfile umleiten, zum Beispiel in dieser Weise:

Zunächst eine Variable mit dem Arbeitsverzeichnis definieren:

1
arbeitsverzeichnis=/pfad/zum/arbeitsverzeichnis

Danach erfolgt die Umleitung:

1
2
3
echo "$(date +%F)" >> $arbeitsverzeichnis/logfile.log
echo 'Das Programm smb4k wurde gestartet.' >> $arbeitsverzeichnis/logfile.log
echo >> $arbeitsverzeichnis/logfile.log

bzw. nach else:

1
2
3
echo "$(date +%F)" >> $arbeitsverzeichnis/logfile.log
echo 'Nichts zu tun.' >> $arbeitsverzeichnis/logfile.log
echo >> $arbeitsverzeichnis/logfile.log

, wobei du die jeweils erste und dritte Zeile auch vor bzw. hinter die if-Verzweigung schreiben könntest; so sparst du Redundanz.

Oder du lässt dich direkt benachrichtigen. Für solche Fälle habe ich mir für meine Skripte ein paar Grafikdateien gebastelt, die ich im Ereignisfall wie folgt aufrufe:

DISPLAY=:0 feh --geometry +810+460 -x $arbeitsverzeichnis/Benachrichtigung.png

Den Bildbetrachter feh müsstest du dir allerdings vorher installieren.

trollsportverein

Avatar von trollsportverein

Anmeldungsdatum:
21. Oktober 2010

Beiträge: 5232

Host existiert nicht:

ping -c1 nichts  &> /dev/null && echo "Online" || echo "Offline"
Offline

Host existiert:

ping -c1 google.com &> /dev/null && echo "Online" || echo "Offline"
Online

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

M.E. reicht da ein Einzeiler

1
2
3
#!/bin/sh

ping -qc 1 192.168.178.45 >/dev/null 2>&1 && { /usr/bin/smb4k & }

Der liefert sogar einen Exit-Status != 0 zurück, wenn der Dienst nicht da ist.

Das scheint sich ja um eine Startautomatisierung zu handeln. Möglicherweise wäre deshalb eine noch bessere Lösung das als Systemd-Unit mit den entsprechenden Abhängigkeiten zu machen.

kdeNoob

(Themenstarter)

Anmeldungsdatum:
9. Oktober 2018

Beiträge: 63

besten Dank für jeden Beitrag,

besonderer Dank an "wxpte", Fragen verständlich erklährt. Die Syntax-Fehler resultieren aus Copy&Past, sowie derzeit viele mit Halbwissen haussieren gehen(ich demzufolge auch). Sorry, aber die Einzeiler sind zwar elegant,effektiv aber auch etwas elitär und verbessern für "Gelegenheits-Skripter" nicht die Verständlichkeit.

Das warten mit "sleep 5" macht dann auch keinen Sinn, da das Skript im Autostart steht und alle Systemprozesse ab User-Login bereits gestartet wurden? Ich verlängere nur das User-Login.

Nochmals Danke

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

kdeNoob schrieb:

Sorry, aber die Einzeiler sind zwar elegant,effektiv aber auch etwas elitär und verbessern für "Gelegenheits-Skripter" nicht die Verständlichkeit.

Ich erkläre es gerne. Was ist denn unklar?

kdeNoob

(Themenstarter)

Anmeldungsdatum:
9. Oktober 2018

Beiträge: 63

gerne rklm,

...sprengt jedoch den Rahmen der eigentlichen Frage? Ich hoffe andere Noob's können partizipieren.

Wenn ich es richtig verstehe, dann wird nur der Befehl "ping" ausgewertet, if-Anweisung nicht notwendig. "/dev/null"==Null, bei err=2 oder stdout=1(ping hat Erfolg) befolge Anweisung danach {}, also nur Fall=1 ?

Ich habe "$>:man bash" versucht zu lesen, würde die Syntax wegen fehlendem Verständnis leider so nicht hinbekommen.

@wxpte: Kann man die Nachricht aus dem Skript nicht auch direkt an die System-Benachrichtigung in der Kontrollleiste senden?

kdeNoob

wxpte

Anmeldungsdatum:
20. Januar 2007

Beiträge: 1388

kdeNoob schrieb:

@wxpte: Kann man die Nachricht aus dem Skript nicht auch direkt an die System-Benachrichtigung in der Kontrollleiste senden?

Über zenity ließe sich da auch etwas bauen. Mit dieser Anwendung könnte man zum Beispiel die Zeile

DISPLAY=:0 zenity --notification --text "Das Programm smb4k wurde gestartet."

in das Skript einbauen. Dann würde nach dem Start für einige Sekunden eine entsprechende Hinweisbox auf dem Bildschirm erscheinen. Wie das mit der System-Benachrichtigung in der Kontrollleiste funktioniert, weiß ich nicht (das habe ich auch noch nicht ausprobiert).

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Für Notifikationen aus der crontab nutze ich notify-send (sudo apt install libnotify-bin). Da der Crontabuser keine Hoheit über x11 hat, muss man bei crontab diesen String XDG_RUNTIME_DIR=/run/user/1000 voransetzen, das könnte bei systemd ähnlich sein.

1
XDG_RUNTIME_DIR=/run/user/1000 notify-send -u critical "Das Wasser kocht über!"

Das läuft jedoch bei mir unter Xubuntu - KDE hat vielleicht eigene Benachrichtigungen?

trollsportverein

Avatar von trollsportverein

Anmeldungsdatum:
21. Oktober 2010

Beiträge: 5232

user_unknown schrieb:

KDE hat vielleicht eigene Benachrichtigungen?

Ja. Hier eine Wechselschaltung als Beispiel, die das bequeme Firewall ein- und auschalten per Shortcut ermöglicht. Dabei muss das Script mit pkexec voran gestellt in den eigenen Kurzbefehlen in den KDE-Systemeinstellungen eingetragen sein:

#!/bin/bash
[[ -n $(ufw status | awk '/Aktiv/{ print $2 }') ]] && ufw disable || ufw enable && ufw status | \
grep Status | sudo -u <USERNAME> DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<USER_ID>/bus /usr/bin/notify-send  -i /var/lib/swcatalog/icons/ubuntu-lunar-universe/48x48/plasma-firewall_preferences-security-firewall.png "Firewall `xargs`"

pkexec fragt dann beim Nutzen der Shortcut Tastenkombination das Passwort ab, und ruft dann bei korrekter Passworteingabe das Script mit root Rechten auf. Dort im Script muss dann für den Aufruf von notify-send wieder auf die Rechte des Desktop Users herunter gegangen werden, um die Benachrichtigung per Pop-up auf dem Desktop zu ermöglichen.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

kdeNoob schrieb:

...sprengt jedoch den Rahmen der eigentlichen Frage?

Nee.

Wenn ich es richtig verstehe, dann wird nur der Befehl "ping" ausgewertet, if-Anweisung nicht notwendig.

Genau. Man kann Befehle auch mit && und || verknüpfen ("und" und "oder"). Je nach Ergebnis auf der linken Seite wird die rechte ausgeführt oder nicht. Im aktuellen Fall wird die rechte Seite nur ausgeführt, wenn der ping erfolgreich war.

"/dev/null"==Null, bei err=2 oder stdout=1(ping hat Erfolg) befolge Anweisung danach {}, also nur Fall=1 ?

Nein >/dev/null 2>&1 sind nur Ausgabeumleitungen (ggf. sogar überflüssig wegen Option "-q"). Erst wird Stdout (FD 1) nach /dev/null umgeleitet (= wegschmeißen) und dann Stderr (FD 2) auf Stdout (also /dev/null, also auch wegschmeißen).

Die Sache mit den geschweiften Klammern ist wirklich etwas trickreich. Vergleiche

1
2
a && b &
a && { b & }

Das letzte Ampersand in der Zeile schickt einen Prozess in den Hintergrund. In der ersten Zeile wird, wegen der Vorrangregeln der Operatoren, die gesamte Zeile in den Hintergrund geschickt. Aber Du wolltest ja, dass der Rückgabewert des Skriptes das Ergebnis des ping widerspiegelt. Also nimmt man die Klammern, die einen höheren Vorrang vor && haben und schickt nur das Kommando b (also in Deinem Fall /usr/bin/smb4k) in den Hintergrund.

Ich habe "$>:man bash" versucht zu lesen, würde die Syntax wegen fehlendem Verständnis leider so nicht hinbekommen.

Üben und ausprobieren. 😉

Noch ein Tipp: üblicherweise kennt man ja den Port, auf dem ein Dienst lauscht. In dem Fall eignet sich nc besser. Man würde das dann so machen:

1
2
3
#!/bin/sh

nc -zw 5 192.168.178.45 1234 && { /usr/bin/smb4k & }

Die "5" ist der Timeout, "1234" ist der Port (vermutlich 139 oder 445, siehe hier und in /etc/services). Wenn man beide Ports prüfen will:

1
2
3
#!/bin/sh

nc -zw 5 192.168.178.45 139 && nc -zw 5 192.168.178.45 445 && { /usr/bin/smb4k & }

wxpte

Anmeldungsdatum:
20. Januar 2007

Beiträge: 1388

user_unknown schrieb:

KDE hat vielleicht eigene Benachrichtigungen?

Aus meiner Zeit mit Kubuntu kenne ich noch KDialog

kdeNoob

(Themenstarter)

Anmeldungsdatum:
9. Oktober 2018

Beiträge: 63

Danke für all die Tipp's,

@rklm:netcut [nc] ist wohl die sauberste Lösung, um direkt den SMB Port 139 zu checken. 445 ist von Synology nur die Web-Oberfläche(?), da will ich nicht hin!

@wxpte:KDialog wäre in dem Fall sehr tricky, wenn der SMB Port nicht erreicht ist. Habe auch schon mit "kdialog --msgbox 'nicht erreichbar'" im Script rumgestümpert, jedoch keine Peilung, wie ich dass vor/nach dem && Operator sauber einbinde.

nc -zw 3 192.168.178.45 139 && { /usr/bin/smb4k & } && &1<1 kdialog --msgbocx 'Netzlaufwerk nicht erreichbar'

bis zum 2ten "&&" erfüllt die Zeile den beabsichtigten Zweck ja schon. Danach ist "schöner Wohnen"

Grüße kdeNoob

wxpte

Anmeldungsdatum:
20. Januar 2007

Beiträge: 1388

kdeNoob schrieb:

Habe auch schon mit "kdialog --msgbox 'nicht erreichbar'" im Script rumgestümpert, jedoch keine Peilung, wie ich dass vor/nach dem && Operator sauber einbinde.

Die Einzeiler-Konstrukte mit dem Operator && sind auch eher für einfache Fälle gedacht. Bei Verzweigungen mit mehreren Befehlen für die jeweilige Alternative bietet sich dagegen die klassische if - then - else-Konstruktion an, sonst wird es schnell unübersichtlich (abgesehen davon, dass die Entsprechung von else auch der Operator || wäre).

Edit: und &1<1 ist wieder so eine "Umleitung", von der ich nicht weiß, was du damit erreichen willst. Wo hast du das her? Schau dir am besten mal die Hilfeseite Umleitungen an: das &-Zeichen taucht nur dann auf, wenn mehrere Ausgabekanäle zusammengeführt werden sollen, oder wenn bestimmte Kanäle explizit geschlossen werden sollen. Das alles willst du aber nicht, wie sich aus dem Kontext deiner Beiträge ergibt.

Darüber hinaus: auch kdialog musst du mit DISPLAY=:0 einleiten, damit es auf der grafischen Oberfläche erscheint (vor allem, wenn du das Skript über Autostart laufen lässt).

Also:

1
2
3
4
5
6
if nc -zw 3 192.168.178.45 139; then
   /usr/bin/smb4k &
   DISPLAY=:0 kdialog --msgbox 'Das Programm smb4k wurde gestartet.'
else
   DISPLAY=:0 kdialog --msgbox 'Netzlaufwerk nicht erreichbar'
fi

kdialog habe ich mangels Kubuntu-Umgebung jetzt nicht getestet. Aber du solltest schon darauf achten, dass du die Syntax (z. B. --msgbox) im Code auch richtig schreibst. Falls du im Erfolgsfall keine Meldung benötigst, kannst du die Zeile 3 auch weglassen.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

kdeNoob schrieb:

@rklm:netcut [nc] ist wohl die sauberste Lösung, um direkt den SMB Port 139 zu checken.

"nc" == "netcat" - lass Dir kein U für ein A vormachen. 😉

Antworten |