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 $subshellnon funzionerà come$subshellnon è figlio del processo che stai eseguendowaitin. Ad ogni modo, non stavi aspettando il processo facendo ilwaitquindi non importa molto.kill $subshellucciderà la subshell ma nonsleepse la subshell fosse riuscita ad avviarla entro il tempokillè stato eseguito. Potresti comunque eseguiresleepnello stesso processo conexec- 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:
- la subshell
- sudo da bambino di 1 anno
- wpa_supplicant (che in precedenza eseguiva stdbuf) da bambino di 2 anni
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?