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.
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.
| Dove | Cosa ottieni |
|---|---|
| solo in locale | pannelli e finestre comodi; ma se cade la rete, le sessioni SSH dentro muoiono e i processi remoti con loro |
| solo in remoto | i processi remoti sopravvivono a tutto; ma resti con un terminale solo in locale |
| in tutti e due | la 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.
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:
| Metodo | Come funziona |
|---|---|
| prefix due volte | bind C-a send-prefix (lezione 2): il secondo passa al livello sotto |
| prefix diversi | Ctrl+a in locale, Ctrl+b sul server: nessuna ambiguità, ma va ricordato |
| tasto di passaggio | un tasto che «spegne» il tmux locale finché non lo riaccendi — vedi il trucco |
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.
# 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 — 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.
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
| Sintomo | Rimedio |
|---|---|
bordi fatti di qqqq e xxxx | locale non UTF-8: export LANG=it_IT.UTF-8 sul server, o tmux -u |
| colori sbagliati o assenti | default-terminal non adatto (lezione 6) · verifica con echo $TERM |
| schermo disallineato dopo un ridimensionamento | prefix r se lo hai mappato su refresh-client, oppure tmux refresh-client -S |
| i tasti Home e Fine scrivono caratteri | discrepanza di terminfo tra locale e remoto: allinea $TERM |
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.
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.
| Pezzo | Che cosa fa |
|---|---|
| bind -T root | assegna il tasto senza prefix, nella tabella normale |
| set key-table off | manda tutti i tasti in una tabella vuota: tmux non risponde più |
| bind -T off F12 | l'unico tasto definito in quella tabella: la via del ritorno |
| set -u | rimuove l'impostazione riportandola al valore ereditato |
| refresh-client -S | ridisegna subito la status bar, senza aspettare l'intervallo |