GNU/Linux >> Tutoriels Linux >  >> Linux

Tuer le sous-shell en silence ?

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écutez wait dans. Quoi qu'il en soit, vous n'attendriez pas le processus en faisant le wait donc ça n'a pas beaucoup d'importance.
  • kill $subshell va tuer le sous-shell mais pas sleep si le sous-shell avait réussi à le démarrer au moment kill Était dirigé. Vous pouvez cependant lancer sleep dans le même processus avec exec
  • 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 :

  1. le sous-shell
  2. sudo en tant qu'enfant de 1 ans
  3. wpa_supplicant (qui exécutait auparavant stdbuf) en tant qu'enfant de 2
Connexe :bouton "Tuer le plus gros processus" ?

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 ?


Linux
  1. Rediriger une sortie d'un sous-shell vers un processus ?

  2. Comment tuer les processus en cours d'exécution sous Linux

  3. kill Exemples de commandes sous Linux

  4. kill :commande introuvable

  5. Linux :supprimer la tâche en arrière-plan

Comment tuer un processus sous Linux

Commande Kill sous Linux

Comment tuer un processus sous Linux

Qu'est-ce que le sous-shell sous Linux ?

Qu'est-ce que la commande kill sous Linux ?

Que fait kill -- -0 ?