Ich möchte so etwas wie dieses Q/A implementieren, aber für eine Sub-Shell. Hier ist ein minimales Beispiel für das, was ich versuche:
(subshell=$BASHPID
(kill $subshell & wait $subshell 2>/dev/null) &
sleep 600)
echo subshell done
Wie kann ich es so machen, dass nur subshell done
gibt statt:
./test.sh: line 4: 5439 Terminated ( subshell=$BASHPID; ( kill $subshell && wait $subshell 2> /dev/null ) & sleep 600 )
subshell done
Bearbeiten:Ich kann mich in der Terminologie hier irren, mit Subshell meine ich den Prozess innerhalb der ersten Klammern.
Aktualisierung:
Ich möchte das Snippet aus dem eigentlichen Programm für den Kontext posten, oben ist eine Vereinfachung:
# If subshell below if killed or returns error connected variable won't be set
(if [ -n "$2" ];then
# code to setup wpa configurations here
# If wifi key is wrong kill subshell
subshell=$BASHPID
(sudo stdbuf -o0 wpa_supplicant -Dwext -i$wifi -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1 \
| grep -m 1 "pre-shared key may be incorrect" \
&& kill -s PIPE "$subshell") &
# More code which does the setup necessary for wifi
) && connected=true
# later json will be returned based on if connected is set
Akzeptierte Antwort:
Hinweis:
wait $subshell
funktioniert nicht als$subshell
ist kein untergeordnetes Element des Prozesses, den Siewait
ausführen in. Wie auch immer, Sie würden nicht auf den Prozess warten, der daswait
ausführt also spielt es keine Rolle.kill $subshell
wird die Subshell beenden, aber nichtsleep
wenn es der Subshell bis zum Zeitpunktkill
gelungen wäre, sie zu starten gelaufen war. Sie könnten jedochsleep
ausführen im selben Prozess mitexec
- Sie können SIGPIPE anstelle von SIGTERM verwenden, um die Meldung zu vermeiden
- Eine Variable in Listenkontexten ohne Anführungszeichen zu lassen, hat in
bash
eine ganz besondere Bedeutung .
Nachdem Sie das alles gesagt haben, können Sie Folgendes tun:
(
subshell=$BASHPID
kill -s PIPE "$subshell" &
sleep 600
)
echo subshell done
(ersetze sleep 60
mit exec sleep 60
wenn du den kill
willst um sleep
zu beenden und nicht nur die Subshell, die in diesem Fall möglicherweise nicht einmal Zeit hat, sleep
auszuführen bis Sie es töten).
Mir ist jedenfalls nicht klar, was du damit erreichen willst.
sleep 600 &
wäre ein zuverlässigerer Weg, sleep
zu starten im Hintergrund, wenn Sie das möchten (oder (sleep 600 &)
wenn Sie diesen sleep
verstecken wollten Prozess von der Haupt-Shell)
Jetzt mit Ihrem aktuellen
sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf
beachten Sie, dass sudo
erzeugt einen untergeordneten Prozess, um den Befehl auszuführen (wenn auch nur, weil er möglicherweise seinen Status protokollieren oder danach einige PAM-Sitzungsaufgaben ausführen muss). stdbuf
wird jedoch wpa_supplicant
ausführen im selben Prozess, also haben Sie am Ende drei Prozesse (zusätzlich zum Rest des Skripts) in wpa_supplicant
Vorfahren:
- die Unterschale
- sudo als Kind von 1
- wpa_supplicant (auf dem früher stdbuf ausgeführt wurde) als Kind von 2
Wenn Sie 1 töten, tötet das nicht automatisch 2. Wenn Sie jedoch 2 töten, es sei denn, es handelt sich um ein Signal wie SIGKILL, das nicht abgefangen werden kann, wird das 3 als sudo
töten passiert, um die empfangenen Signale an den Befehl weiterzuleiten, den es ausführt.
Auf jeden Fall ist das nicht die Subshell, die Sie hier töten möchten, es ist 3 oder mindestens 2.
Nun, wenn es als root
ausgeführt wird und der Rest des Skripts nicht ist, können Sie es nicht so einfach beenden.
Du brauchst den kill
als root
auszuführen , also benötigen Sie:
sudo WIFI="$wifi" bash -c '
(echo "$BASHPID" &&
exec stdbuf -o0 wpa_supplicant -Dwext -i"$WIFI" -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1
) | {
read pid &&
grep -m1 "pre-shared key may be incorrect" &&
kill -s PIPE "$pid"
}'
Auf diese Weise wpa_supplicant
wird in derselben $BASHPID
ausgeführt process als Subshell, wie wir das mit exec
machen .
Wir bekommen die PID durch die Pipe und führen kill
aus als root.
Beachten Sie Folgendes:Wenn Sie bereit sind, etwas länger zu warten,
sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1 |
grep -m1 "pre-shared key may be incorrect"
Hätte wpa_supplicant
nächstes Mal automatisch mit einem SIGPIPE (vom System, also kein Berechtigungsproblem) getötet es schreibt etwas in diese Pipe nach grep
ist weg.
Einige Shell-Implementierungen würden nicht auf sudo
warten nach grep
zurückgekehrt ist (wobei es im Hintergrund läuft, bis es SIGPIPEd erhält), und mit bash
, das geht auch mit grep ... <(sudo ...)
Syntax, wobei bash
wartet nicht auf sudo
entweder nach grep
ist zurückgekehrt.
Mehr bei Grep wird langsam beendet, nachdem eine Übereinstimmung gefunden wurde?