¿Cómo puedo separar un proceso de un script bash?

18

Estoy tratando de separar un proceso de un script bash para que SIGINT no se reenvíe al proceso cuando salga del script.

He utilizado el disowncomando en la terminal directamente, sin embargo, en bash, disownno impide que SIGINT se reenvíe. El propósito de este script es iniciar openocd y luego gdb con una sola invocación. Dado que el script nunca sale (está ejecutando gdb) SIGINT todavía se reenvía desde gdb a openocd, lo cual es un problema ya que SIGINT se usa como comando de detención en gdb.

En la terminal se vería así:

$ openocd &    # run openocd demonized
$ disown $!    # disown last pid
$ gdb          # invoke GDB

cuando se invoca en la terminal en este orden, SIGINT no se pasa de gdb a openocd. Sin embargo, si esta misma invocación estaba en un script bash, se pasa el SIGINT.

Cualquier ayuda sería muy apreciada.

PD: este problema está en OS X, pero estoy tratando de usar herramientas que también son portátiles para todas las herramientas de Unix.

usuario2328113
fuente
nohupNo es la respuesta correcta. Debe agregar algún pseudocódigo o código de ejemplo para mostrar con mayor precisión lo que desea.
Bruce Ediger
1
¿Estás abierto a usar una herramienta como screen?
Eric Renouf

Respuestas:

17

Para separar un proceso de un script bash:

nohup ./process &

Si detiene su script bash con SIGINT(ctrl + c), o el shell sale del envío, SIGHUPpor ejemplo, el proceso no será molestado y continuará ejecutándose normalmente. stdoutY stderrserá redirigido a un archivo de registro: nohup.out.

Si desea ejecutar un comando separado mientras puede ver la salida en el terminal, utilice tail:

TEMP_LOG_FILE=tmp.log
> "$TEMP_LOG_FILE"
nohup ./process &> "$TEMP_LOG_FILE" & tail -f "$TEMP_LOG_FILE" &
bagazo
fuente
¿Por qué es nohupnecesario? ¿Cuál es la diferencia entre nohup COMMAND &y COMMAND &si su objetivo es solo ejecutar el comando en segundo plano y liberar el terminal?
James Wierzba
@JamesWierzba Una de las diferencias es que si necesita que el comando continúe ejecutándose incluso después de salir del shell, entonces nohup es el camino a seguir. Hay miles de explicaciones extensas en la web. Por ejemplo stackoverflow.com/questions/15595374/…
marzo
10

Para mí esto funciona perfectamente bien con Disown

command & disown
ManuelSchneid3r
fuente
4

La solución que encontré involucra un programa llamado 'separar' escrito por Annon Inglorion y descargable desde su sitio web

Una vez compilado, se puede usar en un script de la siguiente manera:

$ ./detach -p debug.pid openocd <args> # detach openocd
$ gdb <args>                           # run gdb
$ kill -9 $(cat debug.pid)             # end openocd process
$ rm debug.pid                         # remove file containing process id

Esta primera línea crea un nuevo proceso (ejecutando openocd) y almacena la identificación del proceso en el archivo (debug.pid) para su uso posterior. Esto evita los problemas con grepping para el pid como se proporciona en la respuesta de Oliver. Al salir del siguiente programa de bloqueo (gdb), el archivo que almacena el pid se usa para eliminar el proceso separado directamente.

usuario2328113
fuente
Puede confirmar, detachhace maravillas.
COMO
2

Una solución simple y portátil:

echo "openocd" | at now #openocd starts now, but via the at daemon, not the current shell!
pid=$(ps -ef | grep "[o]penocd" | awk '{print $1}')  
echo "openocd is running with pid: $pid"
gdb

Algunas advertencias de portabilidad: ¡las psopciones dependen del sistema operativo! en su lugar podría utilizar una variante de: { ps -ef || ps aux ;} | grep '[o]penocd | cut -f 1. atno pudo estar disponible (raro, pero esto sucede ...). $(...)necesita un caparazón no muy viejo, de lo contrario, use backticks.

Olivier Dulac
fuente
Esto parece peligroso, la búsqueda de pid puede hacer cosas inesperadas si se está ejecutando más de un proceso con el mismo nombre, o incluso, si otro proceso contiene la palabra openocd.
orion
1
@orion: doy un ejemplo simple para dar las ideas, esas preocupaciones que menciona son fáciles de eliminar: atinicie un script que inicie el programa y dé su pid en su lugar en un archivo, y haga que el script principal espere eso archivo para aparecer y luego leer el pid de él.
Olivier Dulac
por supuesto, debe reemplazar en mi (demasiado simple) ejemplo el grep con una prueba dentro de awk, en la columna derecha ($ 8, generalmente) (las columnas dependen de su sistema operativo y la versión / opciones de ps)
Olivier Dulac