nohup

Llevo un tiempo metido en la migración de una base de datos. No solo se trata de dos bases de datos distintas, sino que además sus motores son también distintos. En este sentido, estoy utilizando Python para migrar los datos de una a la otra. Durante estos días estoy haciendo diversas pruebas, antes de crear un servicio. Sin embargo, quería dejar un proceso corriendo durante horas, en concreto durante toda la noche, pero evidentemente no quería quedarme yo a vigilarla. Así, necesitaba salir del terminal desde el que había lanzado el proceso, sin detenerlo. En este sentido, he echado mano de nohup que ya he utilizado en otras ocasiones, como en el caso de convertir archivos de vídeo.

Así este artículo va dedicado a nohup para que puedas sacarle partido cuando lo necesites.

nohup

nohup

Seguro que en mas de una ocasión te ha sucedido que estabas ejecutando algún proceso en el terminal, y por salirte de él, has terminado el trabajo que se estaba haciendo. Por supuesto, en ese preciso momento, has echado por tu boca sacos y culebras, y te has acordado de todo lo que uno se puede acordar.

Tener un servidor, como puede ser perfectamente una Raspberry Pi, y no poder dejar un proceso en marcha, porque tienes que cerrar la conexión, es desaprovechar las posibilidades que te ofrece cualquier servidor. En este sentido tienes diferentes opciones para dejar el proceso corriendo en segundo plano, como pueden ser tmux o screen.

Sin embargo, como he comentado en la introducción, hace poco me sucedió, que quería dejar un proceso corriendo, y no tenía ninguna de estas herramientas. Y lo que es peor, tampoco tenía posibilidad de instalarlas. Así que recordé sobre nohup y quise sacarle el máximo partido posible.

Alternativas

Probablemente te preguntas porque no utilizo otras herramientas como puede ser tmux o screen. La cuestión es que en el equipo donde estoy haciendo la migración, no solo no tengo ninguna de estas dos herramientas, sino que además no tengo oportunidad de instalarlas. Me tengo que conformar con lo que tengo. O mejor dicho, tengo que aprovechar todo lo que tengo.

Esta es una de las razones por las que agradezco que en el mundo Linux haya tal cantidad de herramientas. Es posible, que en alguna ocasión te hayas preguntado, para que tantas duplicidades de herramientas. Pues como se dice, siempre hay un roto para un descosido. Y aquí tienes una clara justificación.

Utilizando nohup

Ahora que ya tienes una justificación, para el uso de nohup, ahora es el momento de adentrarse. Lo primero es indicarte que nohup es un comando que permite obviar la señal HUP. Esta señal se envía a los diferentes procesos que están corriendo en un terminal para que se cierren y finalicen sus trabajos. Sin embargo, en ocasiones, te interesa dejar un proceso corriendo aunque tu salgas del terminal. Te interesa dejar un proceso corriendo en segundo plano. Aquí es donde interviene nohup que lo que hace es interceptar esta señal, de forma que nunca llegará a tu proceso, y quedará corriendo en segundo plano por los siglos de los siglos o hasta que termine el proceso.

El uso es realmente sencillo. Tan solo tienes que anteponer nohup al comando que quieres que se quede en ejecución en segundo plano. Por ejemplo,

nohup comando &

Simplemente indicarte que si quieres guardar la salida del terminal en un archivo tienes que indicarlo. Por ejemplo, nohup comando > archivo. En caso de que no se lo indiques, el guardará un archivo nohup.out con la salida estándar. Igualmente, si quieres que también los errores vayan allí, tendrás que seguir las indicaciones del capítulo sobre redirigir entrada y salida en Linux del tutorial sobre el terminal, que resumiendo sería algo como lo que ves a continuación,

nohup comando > archivo 2>&1 &

Y si quieres estar al tanto de lo que se produce en tu comando, puedes utilizar tail, tal y como te indico en el artículo sobre procesar texto con tail, que corresponde también al tutorial sobre el terminal, que resumiendo sería algo como,

tail -f archivo

Un ejemplo

Para que puedas probar todo esto en primer plano, he escrito un sencillo script en Python, test.py, que puedes ver a continuación,

import time
import datetime

counter = 0
while True:
    counter += 1
    print('{0} - {1}'.format(counter, datetime.datetime.now()))
    time.sleep(1)

Lo único que hace este script es imprimir un número consecutivo cada segundo seguido de la fecha y hora a la que lo ha hecho. Esto de forma ininterrumpida hasta que tu lo detengas. Así, por ejemplo la salida puede ser algo como lo que ves a continuación,

1 - 2019-05-30 20:34:42.583360
2 - 2019-05-30 20:34:43.584496
3 - 2019-05-30 20:34:44.585719

De esta manera si lo que quieres es dejarlo corriendo es segundo plano, debes ejecutar la siguiente instrucción,

nohup python -u test.py > salida.out 2>&1 &

La opción -u es para que la salida estándar y el error no tengan un buffer o memoria intermedia, de forma que conforme lo puedas ver en tiempo real.

Trabajando con procesos en segundo plano

Llegados a este punto, es posible que hayas mandado un proceso a segundo plano y ahora lo quieras recuperar. Primero partimos de que continuas en el mismo terminal, es decir, no has salido de la sesión que iniciaste.

En este sentido, te recomiendo que leas el artículo sobre procesos en segundo plano en Linux.

Si quieres ver todos los procesos que has enviado a segundo plano, tan solo tienes que ejecutar la orden jobs. Así, por ejemplo, en mi caso, he puesto en marcha diferentes procesos, de forma que al ejecutar jobs el resultado es el siguiente,

[1]+  Detenido                python test.py
[2]   Detenido                python test.py
[3]-  Detenido                python test.py
[4]   Ejecutando              nohup python -u test.py > salida.out 2>&1 &

Como ves el proceso con nohup lo tienes en segundo plano, y lo tienes en funcionamiento. Ahora podrías recuperarlo de forma sencilla utilizando fg %4, tal y como te expliqué en el artículo que te he mencionado anteriormente sobre procesos en segundo plano.

El problema, seguramente lo encuentres en el caso de que salgas de la sesión de terminal en la que te encuentras, o abras otra sesión en otro terminal, y quieras recuperar el proceso. Si bien es cierto, que hay diferentes herramientas que aparentemente deberían de ayudarte a traer el proceso a primero plano, lo cierto es que, hasta la fecha, no he conseguido que ninguna me funcione. En el momento en que salgo de la sesión no puedo recuperar el proceso.

Sin embargo, llegados a este punto me pregunto, ¿de verdad necesitas traer el proceso a primer plano?. Dado que has redirigido tanto la salida como los errores a un archivo ¿para que necesitas traer el proceso a primer plano?

Perfectamente puedes consultar la salida de tu proceso en el archivo salida.out, y en su caso finalizar el proceso.

¿Y como finalizar el proceso? Si estás en el mismo terminal, tan solo necesitas un kill %4. En el caso de que estés de regreso, tendrás que buscar el proceso con ps -ef | grep python y posteriormente, con el número del proceso directamente matarlo kill -9 <PID>.

Conclusiones

Se trata de una herramienta muy interesante para el caso que te he comentado anteriormente, si bien, en un futuro artículo, tengo intención de abordar screen por todas las posibilidades que ofrece.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *