*gelöst* selbst aufrufendes script - verlassen der shell

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Durruti
Beiträge: 207
Registriert: 16.04.2006 01:54:44

*gelöst* selbst aufrufendes script - verlassen der shell

Beitrag von Durruti » 27.04.2011 18:21:56

Äh ja, verzeiht, mir ist jetzt kein aussagekräftigerer Titel eingefallen, ich werd ihn ggf. zwecks besserer Indizierbarkeit nachträglich abändern.

Ich habe Verständnisprobleme, die ich anhand des folgenden Beispiels schildern möchte.

Wie es der Teufel will, versagt mir sporadisch der Treiber für die WLAN-Karte, woran das liegt weiß ich nicht und ist nochmal ein anderes Thema.

Ich habe nen Einzeiler geschrieben, der aus /var/log/syslog die Fehlermeldung grept und dann die Karte neu initialisiert. Nach erfolgreichem erneuten "ifup", soll mein script wieder an den Anfang zurückkehren, und wieder nach dem Fehler greppen.

Das script sieht folgendermassen aus:

Code: Alles auswählen

#!/bin/bash

# tg2

tail -f -n0 /var/log/syslog | grep -m1 "MAC suspend failed" && echo "Ausfall um" $( date ) >> /var/log/netzlog && ifdown wlan0 && ifup wlan0 && tg2;

exit 0 
was zur Folge hat, daß jedes Mal eine neue shell mit neuer pid aufgerufen wird.

Wie kann ich denn entweder

- die ursprüngliche shell beenden, den neuen Aufruf aber trotzdem leben lassen (ich vermute, der Tod der aufrufenden Shell tötet den "child"-Prozeß gleich mit). Ich hab das script mal mit

Code: Alles auswählen

nohup tg2 &
gestartet, was aber dennoch vielerlei bash-Kinder erzeugt hat.

oder

- unter der selben pid bleiben und innerhalb des scripts wieder an den Anfang springen. Ich nehme an mit einer "while" Konstruktion und/oder dem Verpacken des Ganzen in eine Funktion würde das Funktionieren. Geht es auch ohne das?



Sicher ein Problem der simpelsten Programmierlogik, aber eine Lösung hab ich über die Suchmaschinenrecherche noch keine gefunden, auch das Einlesen in die Grundlagen gestaltet sich eher zäh.
An der Stelle hielt ich es für nen brauchbaren Schritt, mal die konkrete Situation hier darzustellen, muß ja niemand antworten ;)

Cheers :)


P.S.: das ist kein "fortgeschrittenes Thema", aber ich hab keine passendere Rubrik gefunden. Ist auch nicht debianspezifisch...
Zuletzt geändert von Durruti am 28.04.2011 22:51:10, insgesamt 1-mal geändert.

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: sich selbst aufrufendes script - verlassen der shell

Beitrag von rendegast » 27.04.2011 19:39:48

Ein anderer Ansatz,
ein Filter in rsyslog "... wlan0 ... MAC suspend failed ..." schreibt die Nachricht in eine eigene Datei,
zBsp /var/log/WLAN_FAILED.
Diese dann überwachen lassen, in etwa so:

Code: Alles auswählen

#!/bin/sh
while /usr/bin/inotifywait [-m] -e modify /var/log/WLAN_FAILED; do
  ifdown wlan0 && ifup wlan0
done
angereichert mit Tests auf tatsächlichen wlan-Verlust,
Dämpfung um allzuhäufige Ausführung zu verhindern,
usw.

Mit dnotify sah das einfacher aus, ohne while-Schleife:

Code: Alles auswählen

#!/bin/sh
/usr/bin/dnotify -M /var/log/WLAN_FAILED_DIR/ -e wlan-restart-Skript
(dabei die Log-Datei in eigenem Verzeichnis angelegt)
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

Benutzeravatar
Durruti
Beiträge: 207
Registriert: 16.04.2006 01:54:44

Re: sich selbst aufrufendes script - verlassen der shell

Beitrag von Durruti » 27.04.2011 20:16:30

Hi rendegast. An eine Schleife, die die Existenz einer Datei überprüft, hatte ich auch schon gedacht.
Dnotify ist mir unbekannt, habe fam auch nicht installiert. Aber fam heißt, soviel weiß ich noch, file alter(n?)ation monitor, von daher klingt der Ansatz mit dnotify ganz gut.
Ich hatte mir so vorgestellt, daß ich eben keine Schleife laufen lassen möchte, sondern es kam mir "eleganter" äh, oder sparsamer, minimalistischer vor, nur wenn ein Ereignis eintritt (begriff rausgegreppt, datei angelegt, evtl. signal ge"trapt") eine Aktion auszulösen.

Aber ehrlicherweise geht es mir um die Lösung der Aufgabe nur in zweiter Linie ;). Ich kapiere z.B. nicht, wie ich eine shell aufrufen kann, und dabei die ursprüngliche beenden ODER in der gleichen shell bleiben (sagt man da überhaupt shell? prozess halt).

Ist eine Lösung auf dem Weg über trap, so daß bei erfolgreichem grep irgendein signal geschickt wird, denkbar?

Aber den Ansatz mit dnotify werde ich nachher gleich mal noch ausprobieren, das sieht auch interessant aus.

Cheers

lhfloss
Beiträge: 261
Registriert: 07.10.2007 21:02:15
Lizenz eigener Beiträge: MIT Lizenz

Re: sich selbst aufrufendes script - verlassen der shell

Beitrag von lhfloss » 27.04.2011 20:43:25

Durruti hat geschrieben:in der gleichen shell bleiben
Einfach einen Punkt gefolgt von einem Leerzeichen vor den Scriptaufruf setzen:

Code: Alles auswählen

. script

Benutzeravatar
Durruti
Beiträge: 207
Registriert: 16.04.2006 01:54:44

Re: sich selbst aufrufendes script - verlassen der shell

Beitrag von Durruti » 27.04.2011 22:05:00

Ah, das war's. Mit source bleibt man im gleichen Prozeß? Läßt sich das einem Dummie wie mir in ein, zwei Worten erklären?

Also, falls es interessiert, oder falls jemand mal das gleiche Problem hat, meine (erste) Lösung sieht jetzt so aus:

Code: Alles auswählen

#!/bin/bash
# tgt
grep -m1 "suspend failed" <(tail -f -n0 /var/log/syslog) && echo $( date ) >> /var/log/netlog && 
ifdown wlan0; ifup wlan0 && . tgt
Auf die Idee, grep aus dieser subshell raus zu füttern, bin ich gestern irgendwann gestossen, das führt dazu, wenn ich das richtig sehe, daß kein "tail" prozeß weiterläuft, wenn grep sich beendet hat. Zumindest meine ich das so bestätigen zu können.
(edit: mittlerweile denke ich eher, daß die subshell, in welcher tail läuft, einem mittels nohup von der shell entkoppelten kommando auf diese weise überhaupt noch einen input liefern kann - wenn ich tail mit nohup aufrufe und die ausgabe an grep pipe, kommt dort, wohl wegen nohup, nichts an - versteh ich das richtig? geht ja dann alles direkt in die datei nohup.out)

Mein Problem mit dieser Lösung war, daß der Aufruf "nohup tgt &" zur sofortigen Beendigung geführt hat - dachte ich jedenfalls.
Nun, wie dem auch sei, ich kann das jetzt so aufrufen, kann das Terminal schließen, das script läuft im Hintergrund und öffnet nicht unnötig zusätzliche shells.

Ich werd jetzt trotzdem noch mit dnotify rumspielen und wenn ich zu einer alternativen Lösung komme, die hier noch kurz reinposten, nur so spaßeshalber.

Irgendwelche Anregungen, wie man das eleganter, besser, sonstwie lösen kann?

viele Grüße und auch vielen Dank :)

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

Re: sich selbst aufrufendes script - verlassen der shell

Beitrag von uname » 28.04.2011 08:47:21

Irgendwelche Anregungen, wie man das eleganter, besser, sonstwie lösen kann?
Kannst du nicht einfach eine while-Scheife nutzen?

Code: Alles auswählen

while true; do 
...
done
Auch würde ich noch ein "sleep" einbauen, um etwas CPU-Leistung zu sparen. Reicht vielleicht jede Sekunde oder noch seltener die Abfrage laufen zu lassen. Statt "&&" nutze ich im übrigen auch eher if-Abfragen. Ist zwar mehr Code, sieht aber meist übersichtlicher aus.

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

Re: sich selbst aufrufendes script - verlassen der shell

Beitrag von Meillo » 28.04.2011 09:23:46

Ohne den Thead ganz und genau gelesen zu haben (ich weiß, das sollte man nicht machen), moechte ich `exec' in den Raum werfen. Mit diesem Shell-Builtin kannst du den aktuellen Prozess ersetzen, statt einen neuen Kindprozess abzuforken. Letztendlich laeuft es bei Shellscripten aber auf das gleiche raus wie wenn du das source-Kommando verwendest.

Grundsaetzlich wuerde ich es aber doch auch eher mit einer Schleife machen. Das erscheint mir einfacher.
Use ed once in a while!

Benutzeravatar
Durruti
Beiträge: 207
Registriert: 16.04.2006 01:54:44

Re: sich selbst aufrufendes script - verlassen der shell

Beitrag von Durruti » 28.04.2011 22:44:18

So, meine jetzt endgültige Fassung mit tail und grep:

Code: Alles auswählen

#!/bin/bash
# bcm4312_resq
grep -m1 "suspend failed"  <(tail -f -n0 --pid=$BASHPID /var/log/syslog) && ifdown wlan0; ifup wlan0 && exec bcm4312_resq &
nach etwas Recherche (siehe oben, "$BASHID" :)), habe ich jetzt genau die Funktion, die ich wollte... tail beendet sich, exec bleibt in der gleichen shell, und dann ganze läuft schön im Hintergrund. Das war so meine ursprüngliche Vorstellung.

Der Weg über syslog ist mir im Moment zu aufwendig, weil erst Regel schreiben usw.

Das mit der while-Schleife scheint mir mittlerweile auch nicht mehr so schlecht (ich hatte das sogar bisher schon, nur daß statt "grep", "ping" benutzt hab), zumal ich mittlerweile festgestellt hab, das "tail -f" ja auch nix anderes als eine Schleife mit sleep-Intervall ist. Irgendwie auch logisch... naja.

Jedenfalls nochmal vielen Dank für alle Tips!

Antworten