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 eseguendowait
in. Ad ogni modo, non stavi aspettando il processo facendo ilwait
quindi non importa molto.kill $subshell
ucciderà la subshell ma nonsleep
se la subshell fosse riuscita ad avviarla entro il tempokill
è stato eseguito. Potresti comunque eseguiresleep
nello 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?