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.