En algunas ocasiones puede ser necesario ejecutar un script en segundo plano; ya sea porque tarde mucho en finalizar o porque el programa tiene que ejecutarse de forma indefinida y al mismo tiempo se quieren analizar sus salidas/salidas en tiempo real, o cuando, en el caso de conexiones remotas, por el motivo que sea, se pueda producir una desconexión.
Analizaremos 3 posibilidades:
& y bg
Si añadimos un ampersand (&) al final del comando o del script que queremos ejecutar, éste se ejecutará en segundo plano.
$ ./my-shell-script.sh &
[1] 10233
Si ejecutamos un comando de la forma habitual (en primer plano o
foreground) y, después de pasado un cierto tiempo, nos damos cuenta que hubiera sido mejor ejecutarlo en segundo plano o
background, lo podemos hacer sin necesidad de tener que matar el proceso y volver a ejecutarlo de nuevo con el ampersand. Esto se hace presioando "CTRL+Z" para suspender la ejecución del comando actual, y después invocando el comando bg.
$ ./my-shell-script.sh
^Z
[2]+ Detenido my-shell-script.sh
$ bg
[2]+ my-shell-script.sh &
Este proceso que se acaba de pasar al segundo plano, también se puede volver al primer plano con el comando fg.
$ fg 2
my-shell-script.sh
nohup y &
Al finalizar una sesion en un terminal se envía un signal (
SIGHUP) a todos los procesos que esté ejecutando nuestro usuario. Como resultado, dichos procesos se mueren (aunque les hayamos puesto & al final)
Para evitar esto utilizamos el comando nohup. Este comando hace que un proceso ignore la señal SIGHUP, y redirige la salida de nuestro script a un archivo nohup.out que es creado en el directorio actual.
$ nohup ./my-shell-script.sh &
Una buena practica sería redireccionar stdin, stdout y stderr. Básicamente, por dos razones: i) rastrear la salida de nuestro script en caso de producirse algún error, y ii) evitar problemas al terminar nuestra sesión ssh, si es que la ejecutamos en un servidor remoto.
$ nohup ./my-shell-script.sh > foo.out 2> foo.err < /dev/null &
Esta opcion es muy útil cuando necesitamos ejecutar un proceso largo y no nos interesa saber nada de él hasta que finalice. Podemos desconectarnos irnos, regresar al día siguiente y analizar el resultado del proceso.
screen
Si invocamos un comando en segundo plano (usando
nohup y
&), éste se ejecutará incluso después de que cerremos nuestra sesión. Pero, en ninguno de los casos anteriores, podemos conectarnos a la misma sesión otra vez y ver exactamente qué es lo que está pasando en la pantalla, como si no nos hubieramos desconectado. Para lograr esto, usaremos el comando
screen.
El primer paso es ejecutar el script que necesitamos como parametro del comando screen.
$ screen ./my-shell-script.sh
Si después de ejecutar la linea anterior tecleamos “CTRL+A d”, el sistema nos separara de la sesión actual (en la que estamos ejecutando my-shell-script.sh) y nos retornará a la terminal a la espera de teclear un nuevo comando.
Llegados a este punto, podemos cerrar la sesión, irnos, regresar, iniciar una nueva sesión y recuperar la pantalla (
screen) que esta corriendo nuestro script. Para ello, invocaremos el comando screen con el parámetro -ls para obtener un listado de las sesiones actuales:
$ screen -ls
[detached from 1788.ttys000.milleniumfalcon]
A continuación, mediante el parámetro -r y el identificador de la sesión recuperamos la pantalla que necesitemos:
$ screen -r 1788.ttys000.milleniumfalcon
¿Qué opcion usar?
Bueno, pues eso dependerá de cada caso, habrá veces que con el ampersand será suficiente y otras en las que tenemos que optar por una opción diferente. Para saber más acerca de
nohup y
screen recomiendo leer las páginas del manual.