GNU/Linux >> Linux Esercitazione >  >> Linux

Uccidi silenziosamente Subshell?

Voglio implementare qualcosa come questo Q/A ma per una sub-shell. Ecco un esempio minimo di quello che sto provando:

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

echo subshell done

Come posso renderlo così solo subshell done restituisce invece di:

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

Modifica:potrei sbagliarmi sulla terminologia qui, per subshell intendo il processo all'interno della prima serie di parentesi.

Aggiornamento:

Voglio pubblicare lo snippet dal programma effettivo per il contesto, sopra è una semplificazione:

# 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

Risposta accettata:

Nota:

  • wait $subshell non funzionerà come $subshell non è figlio del processo che stai eseguendo wait in. Ad ogni modo, non stavi aspettando il processo facendo il wait quindi non importa molto.
  • kill $subshell ucciderà la subshell ma non sleep se la subshell fosse riuscita ad avviarla entro il tempo kill è stato eseguito. Potresti comunque eseguire sleep nello stesso processo con exec
  • puoi usare SIGPIPE invece di SIGTERM per evitare il messaggio
  • lasciare una variabile senza virgolette nei contesti di elenco ha un significato molto speciale in bash .

Quindi, detto tutto questo, puoi fare:

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

(sostituisci sleep 60 con exec sleep 60 se vuoi il kill per uccidere sleep e non solo la subshell, che in questo caso potrebbe non avere nemmeno il tempo di eseguire sleep prima che lo uccidi).

In ogni caso, non sono sicuro di cosa vuoi ottenere con quello.

sleep 600 &

sarebbe un modo più affidabile per iniziare a sleep in background se è quello che volevi fare (o (sleep 600 &) se volevi nascondere quel sleep processo dalla shell principale)

Ora con il tuo reale

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

comando, nota che sudo genera un processo figlio per eseguire il comando (se non altro perché potrebbe essere necessario registrare il suo stato o eseguire in seguito alcune attività della sessione PAM). stdbuf tuttavia eseguirà wpa_supplicant nello stesso processo, quindi alla fine avrai tre processi (oltre al resto dello script) in wpa_supplicant ascendenza:

  1. la subshell
  2. sudo da bambino di 1 anno
  3. wpa_supplicant (che in precedenza eseguiva stdbuf) da bambino di 2 anni
Correlati:pulsante "Uccidi il processo più grande"?

Se ne uccidi 1, ciò non uccide automaticamente 2. Se invece ne uccidi 2, a meno che non sia con un segnale come SIGKILL che non può essere intercettato, ciò ucciderà 3 come sudo capita di inoltrare i segnali che riceve al comando che esegue.

In ogni caso, non è la subshell che vorresti uccidere qui, è 3 o almeno 2.

Ora, se è in esecuzione come root e il resto della sceneggiatura non lo è, non sarai in grado di ucciderlo così facilmente.

Avresti bisogno del kill da fare come root , quindi avresti bisogno di:

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

In questo modo, wpa_supplicant verrà eseguito nello stesso $BASHPID process come subshell mentre lo stiamo facendo con exec .

Prendiamo il pid attraverso la pipe ed eseguiamo kill come root.

Tieni presente che se sei pronto ad aspettare ancora un po',

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"

Avrebbe wpa_supplicant ucciso automaticamente con un SIGPIPE (dal sistema, quindi nessun problema di autorizzazione) la la prossima volta scrive qualcosa in quella pipe dopo grep è sparito.

Alcune implementazioni della shell non aspetterebbero sudo dopo grep è tornato (lasciandolo in esecuzione in background fino a quando non ottiene SIGPIPed) e con bash , puoi anche farlo usando grep ... <(sudo ...) sintassi, dove bash non aspetta sudo o dopo grep è tornato.

Altro su Grep lento ad uscire dopo aver trovato la corrispondenza?


Linux
  1. Come uccidere un processo zombie su Linux

  2. Processo discendenti?

  3. Come eliminare i processi in esecuzione in Linux

  4. Uccidi la sessione dello schermo indipendente

  5. linux:termina l'attività in background

Come uccidere un processo in Linux

Kill Command in Linux

Come KILL un processo su Linux

Reindirizzamento di un output di una subshell a un processo?

Che cos'è Subshell in Linux?

Qual è il comando kill in Linux?