GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Subshell stillschweigend töten?

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:

zurück
./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 Sie wait ausführen in. Wie auch immer, Sie würden nicht auf den Prozess warten, der das wait ausführt also spielt es keine Rolle.
  • kill $subshell wird die Subshell beenden, aber nicht sleep wenn es der Subshell bis zum Zeitpunkt kill gelungen wäre, sie zu starten gelaufen war. Sie könnten jedoch sleep ausführen im selben Prozess mit exec
  • 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:

  1. die Unterschale
  2. sudo als Kind von 1
  3. wpa_supplicant (auf dem früher stdbuf ausgeführt wurde) als Kind von 2
Verwandt:Schaltfläche „Kill den größten Prozess“?

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?


Linux
  1. So beenden Sie einen Zombie-Prozess unter Linux

  2. So beenden Sie laufende Prozesse in Linux

  3. bash:Hintergrundfunktionsprozess stillschweigend beenden

  4. Beenden Sie den angehängten Bildschirm unter Linux

  5. Timeout für wget erzwingen

So beenden Sie einen Prozess in Linux

Kill-Befehl unter Linux

Wie man einen Prozess unter Linux beendet

Was ist Subshell in Linux?

Was ist der Kill-Befehl in Linux?

Was macht kill -- -0?