$ tmux — corso in 10 lezioni
Lezione 09 di 10

tmux sopra SSH

È il caso d'uso per cui tmux esiste, ed è anche quello che crea i grattacapi specifici: due tmux uno dentro l'altro, le chiavi che scadono, il prefix che non si sa più a chi arriva.

Teoria

Chi gira dove

La domanda da farsi prima di ogni altra cosa è: tmux gira sulla macchina locale o su quella remota? Le due scelte danno comportamenti diversi e servono a scopi diversi.

DoveCosa ottieni
solo in localepannelli e finestre comodi; ma se cade la rete, le sessioni SSH dentro muoiono e i processi remoti con loro
solo in remotoi processi remoti sopravvivono a tutto; ma resti con un terminale solo in locale
in tutti e duela soluzione vera, al prezzo di dover gestire l'annidamento

In pratica la regola è semplice: tmux gira dove stanno i processi che non devono morire. Se lanci un'importazione da tre ore su un server, tmux va lì. Se dividi lo schermo per guardare due file locali, tmux sta in locale. Spesso servono entrambi, e allora bisogna decidere a quale dei due parlano i tasti.

web-01 1:deploy* 2:log remoto · 15:02

L'annidamento, e il tasto che lo attraversa

Con due tmux sovrapposti, il prefix viene intercettato da quello esterno: il remoto non lo riceve mai. Le tre soluzioni, in ordine di diffusione:

MetodoCome funziona
prefix due voltebind C-a send-prefix (lezione 2): il secondo passa al livello sotto
prefix diversiCtrl+a in locale, Ctrl+b sul server: nessuna ambiguità, ma va ricordato
tasto di passaggioun tasto che «spegne» il tmux locale finché non lo riaccendi — vedi il trucco
Per capire dove stai, guarda la status bar. Con due livelli ne vedi due, una sopra l'altra. Dare loro colori diversi — verde in locale, magenta o rosso sui server — è il modo più efficace di non sbagliare macchina, molto più di qualunque scorciatoia mnemonica.
Pratica

Le cose che si rompono, e come si aggiustano

Le variabili d'ambiente invecchiano

Una sessione tmux tiene l'ambiente che aveva quando è nata. Ti stacchi, chiudi l'SSH, rientri il giorno dopo: SSH_AUTH_SOCK punta a un agente che non esiste più, e ogni git push chiede la password.

il socket stabile, la soluzione classica
# nel .tmux.conf del server: tmux aggiorna queste variabili al riattacco
set -g update-environment "SSH_AUTH_SOCK SSH_CONNECTION DISPLAY"

# nel .bashrc del server: un collegamento fisso che punta all'agente attuale
if [ -n "$SSH_AUTH_SOCK" ] && [ "$SSH_AUTH_SOCK" != ~/.ssh/agent.sock ]; then
  ln -sf "$SSH_AUTH_SOCK" ~/.ssh/agent.sock
fi
export SSH_AUTH_SOCK=~/.ssh/agent.sock

Il meccanismo: ogni nuova connessione aggiorna il collegamento simbolico, e tutto dentro tmux continua a usare lo stesso percorso fisso. Il rimedio rapido, se ti trovi nel problema adesso: eval $(tmux show-env -s SSH_AUTH_SOCK) nel pannello.

La connessione cade comunque

tmux salva i processi ma non la connessione: se la rete è instabile ti ritrovi ogni volta a rifare l'SSH. Due soluzioni complementari:

~/.ssh/config e mosh
# ~/.ssh/config — riuso della connessione e keepalive
Host *
  ServerAliveInterval 30
  ServerAliveCountMax 3
  ControlMaster auto
  ControlPath ~/.ssh/cm-%r@%h:%p
  ControlPersist 10m

# attaccarsi direttamente, in un comando solo
Host web
  HostName 203.0.113.10
  RequestTTY yes
  RemoteCommand tmux new -A -s main

Per reti davvero mobili c'è mosh, che sostituisce il trasporto di SSH con un protocollo tollerante alle interruzioni e ai cambi di indirizzo IP: mosh web -- tmux new -A -s main. Mosh non ha scrollback proprio, ma con tmux sotto non serve — la cronologia la tiene tmux.

Con RemoteCommand, scp e rsync smettono di funzionare verso quell'host, perché si aspettano una shell pulita. Definisci due voci: web con tmux per il lavoro interattivo e web-raw senza, con lo stesso HostName, per i trasferimenti.

Caratteri strani, cornici spezzate

SintomoRimedio
bordi fatti di qqqq e xxxxlocale non UTF-8: export LANG=it_IT.UTF-8 sul server, o tmux -u
colori sbagliati o assentidefault-terminal non adatto (lezione 6) · verifica con echo $TERM
schermo disallineato dopo un ridimensionamentoprefix r se lo hai mappato su refresh-client, oppure tmux refresh-client -S
i tasti Home e Fine scrivono caratteridiscrepanza di terminfo tra locale e remoto: allinea $TERM
Trucco

Un tasto che spegne il tmux locale

La soluzione più elegante all'annidamento non è ricordarsi di premere il prefix due volte: è dire al tmux locale di ignorare tutti i suoi tasti finché non glielo dici tu. Mentre è spento, ogni cosa passa dritta al remoto — che si comporta come se fosse l'unico.

~/.tmux.conf della macchina locale
bind -T root F12 \
  set prefix None \;\
  set key-table off \;\
  set status-style "bg=colour238,fg=colour245" \;\
  set status-left "#[bg=colour238,fg=colour245] LOCALE OFF " \;\
  refresh-client -S

bind -T off F12 \
  set -u prefix \;\
  set -u key-table \;\
  set -u status-style \;\
  set -u status-left \;\
  refresh-client -S

Premi F12: la status bar locale si spegne di colore e il prefix smette di rispondere. Lavori sul server con i suoi tasti, senza prefissi doppi. Premi F12 di nuovo e torni al livello locale.

PezzoChe cosa fa
bind -T rootassegna il tasto senza prefix, nella tabella normale
set key-table offmanda tutti i tasti in una tabella vuota: tmux non risponde più
bind -T off F12l'unico tasto definito in quella tabella: la via del ritorno
set -urimuove l'impostazione riportandola al valore ereditato
refresh-client -Sridisegna subito la status bar, senza aspettare l'intervallo
Scegli un tasto che il remoto non usa. F12 è libero quasi ovunque; evita le combinazioni con Ctrl, che Vim e la shell si contendono. Se lavori su tre livelli — locale, bastione, server finale — questo schema regge meglio del prefix ripetuto, che diventerebbe da premere tre volte.