tmux: sesiones de terminal persistentes en servidores remotos

Cuando ejecutas un comando largo en un servidor remoto sin protección alguna —una migración de base de datos, una compilación pesada, un rsync de terabytes— y la conexión SSH se cae, el proceso muere. El kernel manda SIGHUP al shell, el shell lo propaga a sus hijos, y todo termina. Esto no es un bug: es el comportamiento esperado cuando el terminal controlador desaparece. tmux rompe esa dependencia interponiendo un proceso servidor entre tu shell y la conexión SSH.

La arquitectura es la clave para entender por qué funciona. Cuando lanzas tmux, no estás simplemente abriendo una ventana; estás arrancando un servidor tmux en el servidor remoto (/tmp/tmux-<uid>/default es el socket Unix que lo representa). Ese servidor vive como proceso independiente del SSH. Tu cliente tmux —el que ves en pantalla— se conecta a ese servidor y actúa como cliente. Cuando cae el SSH, el cliente desaparece, pero el servidor y todas las sesiones que gestiona siguen ejecutándose tranquilamente. Reconectas, tmux attach, y el estado es exactamente el que dejaste: cursor en la misma posición, historial del buffer, procesos corriendo.

Úsalo en cualquier tarea remota que pueda superar los dos minutos, o siempre que no controles la estabilidad de la red. También es útil en sesiones de trabajo colaborativo (dos terminales conectadas a la misma sesión) y para organizar el trabajo en múltiples paneles sin abrir conexiones SSH paralelas.

Lo que se rompe si no lo usas ya lo mencionamos: el proceso muere con el SIGHUP. Pero hay otro error frecuente: usar tmux mal. Si te conectas con tmux attach y esa sesión ya está abierta en otro cliente, ambos ven lo mismo y el tamaño del terminal se fuerza al más pequeño de los dos. Para evitarlo, usa tmux attach -d para desconectar el cliente anterior, o tmux attach -x que hace lo mismo de forma más explícita.

# ── Instalación (suele venir preinstalado, pero por si acaso) ──────────
sudo apt install tmux

# ── Configuración mínima antes de empezar ─────────────────────────────
cat > ~/.tmux.conf << 'EOF'
# El prefix por defecto es Ctrl+B. Lo dejamos, pero añadimos comodidades.

# Numeración de ventanas desde 1, más intuitivo con el teclado
set -g base-index 1
setw -g pane-base-index 1

# Aumentar el buffer de scroll (por defecto son solo 2000 líneas)
set -g history-limit 50000

# Recargar la config sin salir: prefix + r
bind r source-file ~/.tmux.conf \; display "Config recargada"

# Splits más memorables: | para vertical, - para horizontal
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"

# Navegar entre paneles con prefix + hjkl (estilo vim)
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# Modo de copia con teclas vim
setw -g mode-keys vi
bind -T copy-mode-vi v send -X begin-selection
bind -T copy-mode-vi y send -X copy-selection-and-cancel
EOF

# ── Crear una sesión con nombre para una tarea concreta ───────────────
tmux new -s migracion

# A partir de aquí, todo lo que sigue se ejecuta DENTRO de tmux.
# Si la conexión SSH cae, este proceso sigue vivo en el servidor.

# Lanzamos la tarea larga en el panel principal
pg_dump -h localhost -U app produccion | gzip > /backup/prod_$(date +%F).sql.gz

# ── Dividir la ventana para monitorizar mientras espera ───────────────
# (esto es un comando tmux, no de shell — se escribe después del prefix)
# prefix + |   → abre un panel a la derecha (con nuestra config)
# En ese panel nuevo:
watch -n 2 'du -sh /backup/*.gz | tail -5'

# ── Navegar entre ventanas ────────────────────────────────────────────
# Crear una segunda ventana para no tocar el panel del pg_dump:
# prefix + c   → nueva ventana
# prefix + 1   → volver a la ventana 1
# prefix + n   → siguiente ventana
# prefix + p   → ventana anterior

# ── Desconectarse SIN matar nada ──────────────────────────────────────
# prefix + d   → detach. El servidor tmux y el pg_dump siguen corriendo.

# ── Desde otra conexión SSH (o después de reconectar) ─────────────────
tmux ls
# migracion: 1 windows (created Mon Jun  2 14:23:01 2025)

tmux attach -t migracion
# Si quieres forzar que otros clientes se desconecten al reconectar:
tmux attach -d -t migracion

# ── Copiar texto del buffer de scroll ─────────────────────────────────
# prefix + [        → entrar en modo copia
# v                 → iniciar selección (con nuestra config vi)
# y                 → copiar y salir del modo copia
# prefix + ]        → pegar en el panel actual

# ── Listar y matar sesiones ───────────────────────────────────────────
tmux ls
tmux kill-session -t migracion
# O desde dentro: prefix + :kill-session

Lo que está pasando en cada decisión

El ~/.tmux.conf que generamos con el heredoc establece la base antes de crear la primera sesión. history-limit 50000 es probablemente el ajuste más ignorado: con el valor por defecto de 2000 líneas, un comando que genere salida abundante te dejará sin poder hacer scroll hasta el error que ocurrió hace tres pantallas. En producción, ese buffer es tu única forma de revisar qué pasó si no tienes logging externo.

Los atajos | y - para splits parecen cosmética, pero el argumento -c "#{pane_current_path}" es lo que realmente importa: hace que el nuevo panel abra en el mismo directorio que el panel actual. Sin ese argumento, tmux abre el panel en $HOME, y tienes que navegar de nuevo hasta donde estabas.

tmux new -s migracion no es solo organización. Un nombre descriptivo te permite hacer tmux attach -t migracion directamente desde un alias en tu .bashrc local (alias tmig='ssh servidor -t "tmux attach -t migracion || tmux new -s migracion"'). Ese patrón —conectar y reconectar a una sesión nombrada en un solo comando— elimina por completo el overhead de gestión.

El detach con prefix + d es lo que activa la persistencia. Mucha gente cierra el terminal directamente: si tmux no tiene la opción remain-on-exit activa, eso también mata la sesión. El flujo correcto siempre es detach primero, cerrar el terminal después.

El modo copia con mode-keys vi cambia cómo navegas el buffer de scroll: prefix + [ para entrar, Ctrl+u/Ctrl+d para subir/bajar media pantalla, ? para buscar hacia atrás, n/N para siguiente/anterior coincidencia. En un servidor remoto donde no tienes ratón configurado o prefieres no depender de él, esto es la forma de inspeccionar logs largos sin herramientas adicionales.

El comando watch -n 2 en el segundo panel ilustra el uso más común de los splits en trabajo real: una tarea bloqueante en un panel, observación del efecto en otro, sin necesidad de abrir una segunda conexión SSH que podría también caerse.

Dejar un comentario

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

Scroll al inicio