Este artículo fue publicado originalmente en go2linux.org. El dominio ya no me pertenece, pero soy el autor original. Lo republico aquí en garron.me con correcciones y mejoras.

Cuando cierras una terminal o se corta una conexión SSH, el kernel envía la señal de colgado (SIGHUP) a los procesos iniciados desde esa sesión, y la mayoría termina. nohup ejecuta un comando que ignora esa señal, de modo que un trabajo largo sobrevive al cierre de sesión.

Uso básico

nohup comando &

nohup hace que el comando sea inmune a SIGHUP. El & lo envía a segundo plano para que recuperes el prompt. Son dos cosas distintas: sin & el comando igual ignora el colgado, pero mantiene ocupada tu terminal.

Ejemplo — un respaldo largo que no quieres quedarte vigilando:

nohup tar -czf /backup/home.tar.gz /home &

El shell muestra el número de trabajo y el ID del proceso:

[1] 48213
nohup: ignoring input and appending output to 'nohup.out'

Ya puedes cerrar la sesión. El respaldo sigue ejecutándose.

A dónde va la salida

Si no rediriges nada, nohup agrega tanto stdout como stderr a nohup.out en el directorio actual. Si no se puede escribir en ese directorio, usa $HOME/nohup.out.

En la práctica es mejor elegir el archivo tú mismo:

nohup ./trabajo-largo.sh > trabajo-largo.log 2>&1 &

> trabajo-largo.log redirige stdout, y 2>&1 envía stderr al mismo lugar. Sin 2>&1 los mensajes de error terminan en otro sitio y los pierdes justo cuando más los necesitas.

Para descartar la salida por completo:

nohup ./trabajo-largo.sh > /dev/null 2>&1 &

Lanzar un trabajo por SSH

Cuando inicias un trabajo en segundo plano con un comando SSH de una sola línea, ssh espera hasta que se cierren todos los descriptores de archivo asociados a la sesión. Redirige los tres, incluido stdin, o el comando parecerá colgado:

ssh usuario@servidor 'nohup ./trabajo-largo.sh > trabajo-largo.log 2>&1 < /dev/null &'

Revisar el trabajo más tarde

Seguir el log:

tail -f trabajo-largo.log

Encontrar el proceso:

pgrep -af trabajo-largo.sh

Detenerlo:

kill 48213

nohup solo bloquea SIGHUP. Un kill normal (que envía SIGTERM) detiene el proceso igual.

Bajar la prioridad

Un trabajo largo puede compartir mejor la máquina si combinas nohup con nice:

nohup nice -n 10 ./trabajo-largo.sh > trabajo-largo.log 2>&1 &

Olvidaste nohup — usa disown

Si el comando ya está en ejecución, no hace falta empezar de nuevo. Suspéndelo, envíalo a segundo plano y sepáralo del shell:

Ctrl+Z
bg
disown -h %1

disown -h le indica a Bash que no envíe SIGHUP a ese trabajo cuando el shell termine. Sin embargo, la salida sigue conectada a la terminal, así que un trabajo que escribe mucho después de que la terminal desaparece puede fallar. Para algo importante, nohup con un archivo de log es más seguro.

Cuando nohup no alcanza

El proceso muere de todos modos. En sistemas donde KillUserProcesses=yes está definido en /etc/systemd/logind.conf, systemd mata todos los procesos del usuario al cerrar la sesión, con nohup o sin él. La mayoría de las distribuciones lo traen desactivado, pero si tus trabajos desaparecen al salir, revisa esa opción. En ese caso usa systemd-run (más abajo) o activa la persistencia del usuario con loginctl enable-linger.

El programa maneja SIGHUP por su cuenta. Algunos programas instalan su propio manejador de SIGHUP (muchos demonios recargan su configuración al recibirla), lo que anula lo que nohup configuró.

Necesitas volver a interactuar con él. nohup separa el proceso de forma definitiva. No puedes volver a conectarte a él para escribirle algo.

Alternativas

Herramienta Úsala cuando
nohup cmd & Es un trabajo puntual que no necesita entrada y basta con un archivo de log
disown -h El trabajo ya está en ejecución y olvidaste nohup
setsid cmd Quieres el comando en una sesión nueva, totalmente separado de la terminal
tmux / screen Quieres volver más tarde para ver o controlar el programa
systemd-run Quieres límites de recursos, registro en el journal y una unidad formal

Con tmux:

tmux new -s respaldo
./trabajo-largo.sh

Sepárate con Ctrl+B y luego D, cierra la sesión, y más tarde vuelve a conectarte con tmux attach -t respaldo.

Con systemd-run, como unidad transitoria de usuario:

systemd-run --user --unit=respaldo ./trabajo-largo.sh
journalctl --user -u respaldo -f

Ver también

man nohup — referencia completa.