En el último artículo expliqué cómo mantener procesos en ejecución en segundo plano utilizando la herramienta nohup. Veamos ahora cómo lograr el mismo efecto empleando disown, y al mismo tiempo comprender el uso de los comandos bg, fg y jobs en Bash



Bash, como la mayoría de las shells, tiene la capacidad de controlar trabajos en segundo plano. Particularmente, en Bash es posible iniciar un trabajo en segundo plano terminando el comando con &; detener un trabajo en primer plano con Ctrl+Z; resumir un trabajo en segundo plano con bg; y resumir un trabajo en primer plano (interactivo) con fg. A tal fin, se mantiene una tabla con los trabajos actualmente en ejecución (o detenidos), los cuales pueden ser listados con el comando interno (builtin) jobs.

Los procesos en primer plano son sincrónicos a la terminal interactiva que lo controla, y son los que reciben las señales generadas por la entrada estándar asociada a la misma (típicamente el teclado). Los procesos en segundo plano son asincrónicos y no pueden leer de la entrada estándar, aunque sí escribir en la salida estándar (típicamente la pantalla) asociada a la terminal interactiva que lo controla.

Cada trabajo de una terminal tiene asociado un número de trabajo (jobspec). Cuando se inicia un proceso en segundo plano (finalizando el comando con &), Bash muestra una línea indicando el número de trabajo y PID del proceso asociado. Esto permite referirse a un trabajo a través de su número o a través del PID de su proceso cuando se trabaja con los comandos bg y fg. En tal caso, el número de trabajo debe anteponerse con un caracter porcentual (%).

El comando fg, permite resumir un trabajo en primer plano. Esto hace que se vuelva el proceso interactivo y sincrónico a la sesión actual. Por ejemplo el comando fg %1 indica que el trabajo cuyo jobspec es igual a 1 sea puesto en primer plano nuevamente.

El comando bg es similar pero se utiliza para resumir un proceso en segundo plano. Por ejemplo, si hemos lanzado un proceso en primer plano pero deseamos que continúe en segundo plano (como si hubiese sido lanzado con &), es posible detener el proceso con Ctrl+Z y luego resumirlo en segundo plano con bg pasando como parámetro el número de trabajo o PID.

Ambos comandos (bg y fg) son internos de Bash, al igual que jobs.

Cuando se cierra una terminal, al recibir una señal de hangup (SIGHUP), si se trata de una sesión interactiva reenviará esta señal SIGHUP a todos los trabajos (procesos hijos de dicha terminal). Si deseamos mantener un proceso en segundo plano en ejecución a pesar de que se cierre la terminal que lo controla, es posible utilizar nohup. Sin embargo, si el proceso ya fue lanzado sin nohup, es posible utilizar disown.

disown es otro comando interno de Bash que permite eliminar un proceso o trabajo pasado como parámetro de la lista de trabajos de la sesión actual.

Para entender el manejo de las señales SIGHUP en la terminal, es conveniente analizar un ejemplo del funcionamiento de disown. Primero, veamos qué ocurre con los trabajos corriendo en segundo plano al momento de cerrar la terminal que los controla:

En la ventana derecha se ha lanzado un proceso en segundo plano (notar que el comando finaliza con &). Corresponde con el PID 5271 y jobspec igual a 1. Su estado es "Running", lo que significa que está en ejecución. En la ventana izquierda se observa la salida de ps desde otra terminal.

Veamos qué ocurre al cerrar la terminal que controla al proceso ping:

El proceso desaparece. Ha finalizado junto con la terminal que lo controlaba. Estaba en ejecución en segundo plano y no fue terminado explícitamente por el usuario enviando una señal con la herramienta kill.

Ahora el mismo ejemplo, pero utilizando disown:

En la ventana de la derecha se ha lanzado el comando en segundo plano, se lista con jobs, y finalmente se hace el disown. Esto provoca que el proceso deje de ser controlado por la terminal (ya no aparece listado cuando se ejecuta jobs -l) a pesar de que el proceso siga siendo hijo del proceso que corresponde con la sesión actual (PID 5343 en el ejemplo).

Ahora se cierra la terminal (que lo controlaba, porque ya no al haber hecho disown) nuevamente:

El proceso sigue en ejecución, a pesar de que terminó la terminal que lo lanzó.

Además, se observa que ahora el proceso es hijo de init (proceso inicial con PID igual a 1). Notar en la segunda columna PPID (Parent Process ID es igual a 1).

Más allá de esto, el proceso puede ser terminado, como cualquier otro, enviando la señal SIGHUP (1, pues no fue lanzado con nohup), SIGTERM (15) o SIGKILL (9):

Una opción interesante de disown es -h, que permite mantener el trabajo en la tabla pero no enviarle SIGHUP al terminar. Esto da la posibilidad de seguir controlando el proceso y garantizar de que "sobreviva" al cierre de la terminal que lo controla.

Referencias


Tal vez pueda interesarte


Compartí este artículo