GNU/Linux >> Tutoriales Linux >  >> Linux

¿Matar silenciosamente a Subshell?

Quiero implementar algo como este Q/A pero para un sub-shell. Aquí hay un ejemplo mínimo de lo que estoy intentando:

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

echo subshell done

¿Cómo puedo hacer que solo subshell done? devuelve en lugar de:

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

Editar:puede que me equivoque con la terminología aquí, por subcapa me refiero al proceso dentro del primer paréntesis.

Actualización:

Quiero publicar el fragmento del programa real para el contexto, arriba hay una simplificación:

# 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

Respuesta aceptada:

Nota:

  • wait $subshell no funcionará como $subshell no es un elemento secundario del proceso que está ejecutando wait in. De todos modos, no esperaría el proceso haciendo wait así que no importa mucho.
  • kill $subshell va a eliminar la subcapa pero no sleep si el subshell hubiera logrado iniciarlo en el momento kill fue corrido. Sin embargo, podría ejecutar sleep en el mismo proceso con exec
  • puede usar SIGPIPE en lugar de SIGTERM para evitar el mensaje
  • dejar una variable sin comillas en contextos de lista tiene un significado muy especial en bash .

Habiendo dicho todo eso, puedes hacer:

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

(reemplace sleep 60 con exec sleep 60 si quieres el kill matar sleep y no solo el subshell, que en este caso podría no tener tiempo para ejecutar sleep para cuando lo mates).

En cualquier caso, no estoy seguro de lo que quieres lograr con eso.

sleep 600 &

sería una forma más confiable de iniciar sleep en segundo plano si eso es lo que querías hacer (o (sleep 600 &) si quisieras ocultar ese sleep proceso desde el shell principal)

Ahora con tu

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

comando, tenga en cuenta que sudo genera un proceso secundario para ejecutar el comando (aunque solo sea porque puede necesitar registrar su estado o realizar algunas tareas de sesión PAM después). stdbuf sin embargo, ejecutará wpa_supplicant en el mismo proceso, por lo que al final tendrás tres procesos (además del resto del script) en wpa_supplicant ascendencia:

  1. la subcapa
  2. sudo como un niño de 1
  3. wpa_supplicant (que antes ejecutaba stdbuf) como hijo de 2
Relacionado:¿Botón "Eliminar el proceso más grande"?

Si matas a 1, eso no mata automáticamente a 2. Sin embargo, si matas a 2, a menos que sea con una señal como SIGKILL que no puede ser interceptada, eso matará a 3 como sudo pasa a reenviar las señales que recibe al comando que ejecuta.

En cualquier caso, esa no es la subcapa que querrías eliminar aquí, son 3 o al menos 2.

Ahora, si se está ejecutando como root y el resto del script no lo es, no podrás matarlo tan fácilmente.

Necesitarías el kill para hacerse como root , entonces necesitarías:

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 esa forma, wpa_supplicant se ejecutará en el mismo $BASHPID proceso como el subshell como lo estamos haciendo con exec .

Obtenemos el pid a través de la tubería y ejecutamos kill como raíz.

Tenga en cuenta que si está listo para esperar un poco más,

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"

Tendría wpa_supplicant eliminado automáticamente con un SIGPIPE (por el sistema, por lo que no hay problema de permisos) la próxima vez escribe algo en esa tubería después de grep se ha ido.

Algunas implementaciones de shell no esperarían sudo después de grep ha regresado (dejándolo ejecutándose en segundo plano hasta que obtiene SIGPIPEd), y con bash , también puede hacerlo usando grep ... <(sudo ...) sintaxis, donde bash no espera sudo ya sea después de grep ha regresado.

¿Más en Grep lento para salir después de encontrar una coincidencia?


Linux
  1. ¿Redirigiendo una salida de un subshell a un proceso?

  2. Descendientes del proceso?

  3. Cómo matar procesos en ejecución en Linux

  4. Ejemplos de comandos kill en Linux

  5. matar:comando no encontrado

Cómo matar un proceso zombie en Linux

Cómo matar un proceso en Linux

Comando matar en Linux

Cómo MATAR un proceso en Linux

¿Qué es Subshell en Linux?

¿Qué es el comando matar en Linux?