Captura 'Ctrl + c' para script bash pero no para proceso abierto en este script


11

Traté de tener un programa interactivo en un script bash:

my_program

Y deseo poder cerrarlo con 'Ctrl + c'. Pero cuando lo hago, mi guión también se está cerrando.

Se acerca de.

trap '' 2
my_program
trap 2

Pero en este caso, simplemente no puedo cerrar my_programcon Ctrl + c.

¿Tienes alguna idea de cómo permitir Ctrl + c en un programa, pero no cerrar el script que lo ejecuta?

EDITAR: agregar ejemplo

#!/bin/bash
my_program
my_program2

Si uso Ctrl + c para cerrar my_program, my_program2nunca se ejecuta porque se sale de todo el script.

Respuestas:


13

Deberías usar trap true 2o en trap : 2lugar de trap '' 2. Eso es lo que "trampa de ayuda" en un shell de bash dice al respecto:

Si ARG es la cadena nula, cada SIGNAL_SPEC es ignorado por el shell y por los comandos que invoca .

Ejemplo:

$ cat /tmp/test
#! /bin/sh
trap : INT
cat
echo first cat killed
cat
echo second cat killed
echo done
$ /tmp/test
   <press control-C>
^Cfirst cat killed
   <press control-C>
^Csecond cat killed
done

2
¿Qué tal matar tails en lugar de matar gatos la próxima vez?
kubanczyk

12

Puede restablecer una trampa a su valor predeterminado dando el comando de trampa -como argumento de acción. Si hace esto en un subshell , no afectará la trampa en el shell principal. En su script, puede hacer esto para cada comando que necesita ser interrumpible con Ctrl-C:

#!/bin/bash
# make the shell (and its children) ignore SIGINT
trap '' INT
.
.
.
# but this child won't ignore SIGINT
(trap - INT; my_program)
# the rest of the script is still ignoring SIGINT
.
.
.

1
Si bien la respuesta aceptada es probablemente mejor y más canónica para shell, esta es una gran respuesta en sí misma, ya que introduce el principio general (no específico de shell) sobre cómo hacer este tipo de enmascaramiento / ignoración de señales de forma segura.
R .. GitHub DEJA DE AYUDAR AL HIELO

Supongo que puedes exec my_programen la subshell, para ser un poco más eficiente.
Toby Speight

@R ... eso no es absolutamente específico del shell: si establece una señal en SIG_IGN (eso es lo que está haciendo la trampa con una cadena vacía), ese estado se heredará a través de exec (), excepto SIGCHLD. Ese es el comportamiento obligatorio de POSIX. Consulte también la respuesta a stackoverflow.com/questions/32708086/…
mosvy

@mosvy: No veo con qué parte de mi comentario no estás de acuerdo. Todo mi punto era que "enmascarar / ignorar antes de fork, desenmascarar / ignorar en el niño antes de exec" es un principio general que es útil saber fuera del contexto de la programación de shell.
R .. GitHub DEJA DE AYUDAR AL HIELO

1
Esta es una respuesta muy útil. Como usuario experimentado de Linux, puedo decir que nunca antes había oído hablar de esto. Tiene muchos usos ... tienes mi voto a favor y mi marcador.
Dev

-1


Cuando usa Crtl+ C, interrumpe el programa ("lo mata ").
Lo que probablemente esté buscando es suspender su programa (" pausarlo "). Para esto, puedes usar Crtl+ Z.
Una vez que su programa está en pausa, puede verlo usando jobs. Por ejemplo:
[1]+ Stopped ./foobar
Aquí solo tengo un trabajo, el trabajo n. ° 1, pero puede haber más de uno: cada trabajo tiene su propio número.
Puede controlar su proceso suspendido utilizando una serie de comandos, por ejemplo bg, fgy kill.
bg %1reiniciará trabajo # 1 en el b ack g ronda
fg %1reinicio voluntad trabajo # 1 en el f mineralg round
kill %1matará el trabajo # 1
Tenga en cuenta que puede usar bgy fgsin argumentos si solo tiene un trabajo activo.


Gracias pero no, deseo hacer Ctrl + c.
bob dylan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.