Je veux implémenter quelque chose comme ce Q/A mais pour un sous-shell. Voici un exemple minimal de ce que j'essaie :
(subshell=$BASHPID
(kill $subshell & wait $subshell 2>/dev/null) &
sleep 600)
echo subshell done
Comment puis-je faire en sorte que seul subshell done
renvoie au lieu de :
./test.sh: line 4: 5439 Terminated ( subshell=$BASHPID; ( kill $subshell && wait $subshell 2> /dev/null ) & sleep 600 )
subshell done
Modifier :je me trompe peut-être sur la terminologie ici, par sous-shell, je veux dire le processus dans le premier ensemble de crochets.
Mise à jour :
Je veux poster l'extrait du programme réel pour le contexte, ci-dessus est une simplification :
# 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
Réponse acceptée :
Remarque :
wait $subshell
ne fonctionnera pas comme$subshell
n'est pas un enfant du processus que vous exécutezwait
dans. Quoi qu'il en soit, vous n'attendriez pas le processus en faisant lewait
donc ça n'a pas beaucoup d'importance.kill $subshell
va tuer le sous-shell mais passleep
si le sous-shell avait réussi à le démarrer au momentkill
Était dirigé. Vous pouvez cependant lancersleep
dans le même processus avecexec
- vous pouvez utiliser SIGPIPE au lieu de SIGTERM pour éviter le message
- laisser une variable sans guillemets dans les contextes de liste a une signification très spéciale dans
bash
.
Après avoir dit tout cela, vous pouvez faire :
(
subshell=$BASHPID
kill -s PIPE "$subshell" &
sleep 600
)
echo subshell done
(remplace sleep 60
avec exec sleep 60
si vous voulez le kill
tuer le sleep
et pas seulement le sous-shell, qui dans ce cas n'a peut-être même pas le temps d'exécuter sleep
au moment où vous le tuez).
En tout cas, je ne suis pas sûr de ce que vous voulez réaliser avec ça.
sleep 600 &
serait un moyen plus fiable de commencer à sleep
en arrière-plan si c'est ce que vous vouliez faire (ou (sleep 600 &)
si vous vouliez cacher ce sleep
processus depuis le shell principal)
Maintenant avec votre réel
sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf
commande, notez que sudo
génère un processus enfant pour exécuter la commande (ne serait-ce que parce qu'il peut avoir besoin de consigner son état ou d'effectuer certaines tâches de session PAM par la suite). stdbuf
exécutera cependant wpa_supplicant
dans le même processus, donc au final vous aurez trois processus (en plus du reste du script) dans wpa_supplicant
l'ascendance de :
- le sous-shell
- sudo en tant qu'enfant de 1 ans
- wpa_supplicant (qui exécutait auparavant stdbuf) en tant qu'enfant de 2
Si vous tuez 1, cela ne tue pas automatiquement 2. Si vous tuez 2 cependant, à moins que ce ne soit avec un signal comme SIGKILL qui ne peut pas être intercepté, cela tuera 3 comme sudo
arrive à transmettre les signaux qu'il reçoit à la commande qu'il exécute.
Dans tous les cas, ce n'est pas le sous-shell que vous voudriez tuer ici, c'est 3 ou au moins 2.
Maintenant, s'il s'exécute en tant que root
et le reste du script ne l'est pas, vous ne pourrez pas le tuer aussi facilement.
Vous auriez besoin du kill
à faire en tant que root
, vous aurez donc besoin :
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"
}'
De cette façon, wpa_supplicant
sera exécuté dans le même $BASHPID
traiter en tant que sous-shell comme nous en faisons avec exec
.
Nous obtenons le pid à travers le tuyau et exécutons kill
en tant que root.
Notez que si vous êtes prêt à attendre un peu plus longtemps,
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"
Aurait wpa_supplicant
tué automatiquement avec un SIGPIPE (par le système, donc pas de problème d'autorisation) la prochaine fois il écrit quelque chose dans ce tube après grep
est parti.
Certaines implémentations de shell n'attendraient pas sudo
après grep
est revenu (le laissant fonctionner en arrière-plan jusqu'à ce qu'il soit SIGPIPEd), et avec bash
, vous pouvez également le faire en utilisant le grep ... <(sudo ...)
syntaxe, où bash
n'attend pas sudo
soit après grep
est de retour.
Plus chez Grep lent à sortir après avoir trouvé une correspondance ?