[gelöst] Problem mit wait in Shellskript

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] Problem mit wait in Shellskript

Beitrag von smutbert » 16.06.2013 15:35:11

Hallo,

also ich starte 2 Prozesse, die einander "brauchen". Wenn einer der beiden beendet wird soll sich auch der andere beenden. Folgendes habe ich versucht

Code: Alles auswählen

befehl1 &
PID1=$!
befehl2 &
PID2=$!
{ wait $PID1; kill $PID2;} &
{ wait $PID2; kill $PID1;} & 
Das Problem ist, dass die geschwungenen Klammern offensichtlich (an diese Möglichkeit habe ich gar nicht gedacht) eine neue Shell starten und deshalb wait nicht funktioniert sondern nur mitteilt, dass die Prozesse mit den beiden PIDs von einer anderen Shell aus gestartet wurden. Das ganze spielt sich in der bash ab.

Hat jemand eine (vorzugsweise einfache) Idee?

lg smutbert
Zuletzt geändert von smutbert am 19.06.2013 21:40:09, insgesamt 1-mal geändert.

Benutzeravatar
peschmae
Beiträge: 4844
Registriert: 07.01.2003 12:50:33
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: nirgendwo im irgendwo

Re: (lächerliches) Problem mit wait in Shellskript

Beitrag von peschmae » 16.06.2013 17:34:49

Das ist ein Problem, weil die entsprechenden posix-syscalls das einfach nicht hergeben.

Das einfachste und sicherste ist die Holzhammermethode denke ich mal:

Code: Alles auswählen

while [ -e /proc/$PID1 -a -e /proc/$PID2 ]; do sleep 1; done
kill $PID1
kill $PID2
Alternativ könntest du dir natürlich auch einfach die jeweiligen Gruppen anders zusammenstellen, aber da hast du dann unschönen Kommunikationsbedarf den man irgendwie lösen muss:

Code: Alles auswählen

{ befehl1 & 
PID=$!
echo $PID > /tmp/befehl1
wait $PID
kill $(cat /tmp/befehl2)
rm /tmp/befehl*
} &
und analog für befehl2&

MfG Peschmä
"er hätte nicht in die usa ziehen dürfen - die versauen alles" -- Snoopy

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

Re: (lächerliches) Problem mit wait in Shellskript

Beitrag von smutbert » 16.06.2013 18:47:40

Danke vielmals, dann verwende ich die erste Variante.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: (lächerliches) Problem mit wait in Shellskript

Beitrag von Cae » 17.06.2013 03:40:13

smutbert hat geschrieben:Das Problem ist, dass die geschwungenen Klammern offensichtlich (an diese Möglichkeit habe ich gar nicht gedacht) eine neue Shell starten
Das tun sie nicht, bei {} ist's definitiv dieselbe Shell, erst () wuerde eine Subshell starten. Da du aber alles per & in Jobs verwandelst, sehen die sich gegenseitig nicht:

Code: Alles auswählen

$ sleep 999 &
$ jobs
[1] + Running                    sleep 999
$ { jobs; }
[1] + Running                    sleep 999
$ { jobs; } &
$ 
Ich hab' da ein bisschen rumprobiert und man bekommt offensichtlich auch nicht "ohne weiteres" irgendwelche Daten zwischen den beiden Hintergrundprozessen ausgetauscht. Das kann man z.B. ueber den Umweg "Dateisystem" machen:

Code: Alles auswählen

#!/bin/sh

dir="$(mktemp -d)"
trap 'rm -r "$dir"' EXIT;

echo init;

{
	echo one started;
	sleep 3;
	echo one killing;
	kill "$(cat "$dir/two")";
} &
echo $! >"$dir/one";

{
	echo two started;
	sleep 5;
	echo two killing;
	kill "$(cat "$dir/one")";
} &
echo $! >"$dir/two";

wait %1 %2;
echo fini;
Der Code verwendet keine Features, wofuer's die bash braeuchte und laeuft in der dash einwandfrei. Die bash schreibt einen Hinweis, dass die langsamere Job abgeschossen wurde ("Terminated") und das darauffolgende wait meckert, wenn der zweite Job schon gekillt ist (interessanterweise nicht, wenn der erste fehlt...).

Und vielleicht gibt's ja noch eine simplere Variante wie ein externes wait, was einfach blockt, bis es die als Argument uebergebene PID nicht mehr gibt. Die wait*()-Syscalls scheinen sich aber allesamt auf Kindprozesse des eigenen Prozesses zu beschraenken, vermutlich muss man tatsaechlich regelmaessig pollen, wie's die Loesung von peschmae vorsieht.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

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

Re: (lächerliches) Problem mit wait in Shellskript

Beitrag von rendegast » 17.06.2013 14:29:12

Ich hab noch einen

Code: Alles auswählen

#!/bin/sh

befehl1 &
PID1=$!
befehl2 &
PID2=$!

export PID1 PID2
( tail -f --pid=$PID1 /dev/null; kill $PID2; ) &
( tail -f --pid=$PID2 /dev/null; kill $PID1; ) &

Potentielles Problem,
daß hier ein (oder mehrere) 'kill' auf nicht mehr gültige PID angesetzt ist/sind.
Bsp.

Code: Alles auswählen


PIDS=" $PID1 $PID2 $PID....."
export PID1 PID2 ... PIDS
( tail -f --pid=$PID1 /dev/null; kill $PIDS; ) &
...
Fehlt also noch ein Test auf die Gültigkeit der zu killenden PIDs.
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

wanne
Moderator
Beiträge: 7550
Registriert: 24.05.2010 12:39:42

Re: (lächerliches) Problem mit wait in Shellskript

Beitrag von wanne » 17.06.2013 16:32:59

wait funktioniert glaube ich über SIGCHLD das Funktionieren nur zwieschen Eltern und Kindprozessen.
Der saubere Weg für Interprozesskomunikation geht über shared Memory oder UNIX-Sockets.
Ersteres kann man unter Debian relativ einfach nutzen indem man eine Datei in /dev/shm anlegt. Mittlerweile gibt's das auch unter tmp oder
rot: Moderator wanne spricht, default: User wanne spricht.

Antworten