GNU/Linux >> Znalost Linux >  >> Linux

Tiše zabít Subshell?

Chci implementovat něco takového Q/A, ale pro sub-shell. Zde je minimální příklad toho, co se snažím:

(subshell=$BASHPID
  (kill $subshell & wait $subshell 2>/dev/null) &
sleep 600)

echo subshell done

Jak to mohu udělat tak, aby subshell done vrátí místo:

./test.sh: line 4:  5439 Terminated              ( subshell=$BASHPID; ( kill $subshell && wait $subshell 2> /dev/null ) & sleep 600 )
subshell done

Edit:Možná se mýlím v terminologii zde, podslupkou myslím proces v první sadě hranatých závorek.

Aktualizace:

Chci zveřejnit úryvek ze skutečného programu pro kontext, výše je zjednodušení:

# 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

Přijatá odpověď:

Poznámka:

  • wait $subshell nebude fungovat jako $subshell není potomkem procesu, který spouštíte wait v. Každopádně byste nečekali, až proces provede wait takže na tom moc nezáleží.
  • kill $subshell se chystá zabít subshell, ale ne sleep pokud se subshell podařilo spustit jej do doby kill byl spuštěn. Můžete však spustit sleep ve stejném procesu jako exec
  • můžete použít SIGPIPE místo SIGTERM, abyste se vyhnuli zprávě
  • nechat proměnnou bez uvozovek v kontextu seznamu má v bash velmi zvláštní význam .

Takže když jste to všechno řekli, můžete udělat:

(
  subshell=$BASHPID
  kill -s PIPE "$subshell" &
  sleep 600
)
echo subshell done

(nahraďte sleep 60 s exec sleep 60 pokud chcete kill zabít sleep a nejen subshell, který v tomto případě nemusí mít ani čas spustit sleep v době, kdy ho zabijete).

V každém případě si nejsem jistý, čeho tím chcete dosáhnout.

sleep 600 &

by byl spolehlivější způsob, jak začít sleep na pozadí, pokud jste to chtěli udělat (nebo (sleep 600 &) pokud jste chtěli skrýt ten sleep proces z hlavního prostředí)

Nyní s vaším skutečným

sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf

příkaz, všimněte si, že sudo spustí podřízený proces pro spuštění příkazu (i když jen proto, že může potřebovat zaprotokolovat svůj stav nebo poté provést některé úlohy relace PAM). stdbuf nicméně spustí wpa_supplicant ve stejném procesu, takže nakonec budete mít tři procesy (kromě zbytku skriptu) v wpa_supplicant 's předky:

  1. podshell
  2. sudo jako dítě 1
  3. wpa_supplicant (který dříve spouštěl stdbuf) jako dítě 2
Související:Tlačítko „Zabít největší proces“?

Pokud zabijete 1, nezabije to automaticky 2. Pokud však zabijete 2, pokud to není signálem jako SIGKILL, který nelze zachytit, zabije to 3 jako sudo se stane, že předá signály, které obdrží, příkazu, který spustí.

V každém případě to není podshell, který byste zde chtěli zabít, je to 3 nebo alespoň 2.

Nyní, pokud běží jako root a zbytek skriptu není, nebudete ho moci tak snadno zabít.

Potřebovali byste kill provést jako root , takže budete potřebovat:

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"
  }'

Tímto způsobem wpa_supplicant poběží ve stejném $BASHPID proces jako subshell, jak jej vytváříme pomocí exec .

Provedeme pid potrubím a spustíme kill jako root.

Všimněte si, že pokud jste připraveni počkat o něco déle,

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"

Měl by wpa_supplicant automaticky zabit pomocí SIGPIPE (systémem, takže žádný problém s oprávněním) příště zapíše něco do této roury za grep je pryč.

Některé implementace shellu by nečekaly na sudo za grep se vrátil (ponechává jej běžet na pozadí, dokud se nespustí SIGPIPE) a s bash , můžete to udělat také pomocí grep ... <(sudo ...) syntaxe, kde bash nečeká na sudo buď za grep se vrátil.

Více na Grep se po nalezení shody pomalu ukončuje?


Linux
  1. Jak zabít proces zombie na Linuxu

  2. Přesměrování výstupu subshell do procesu?

  3. Procesní potomci?

  1. Jak zabít běžící procesy v Linuxu

  2. Příklady příkazů kill v Linuxu

  3. kill:příkaz nenalezen

  1. Zabijte relaci oddělené obrazovky

  2. linux:úkol zabít pozadí

  3. Spánek na milisekundy