tmux è un linguaggio di comandi
Ogni scorciatoia che hai imparato finora è solo un tasto legato a un comando. Gli stessi comandi si scrivono dalla shell, si mettono in uno script, si indirizzano a un pannello che non stai nemmeno guardando.
La stessa cosa, da tre parti
prefix c non «crea una finestra»: esegue
new-window. Puoi verificarlo con tmux list-keys | grep
new-window. La conseguenza è che ogni funzione di tmux ha tre accessi
equivalenti, e il terzo è quello che apre le porte.
| Da dove | Come |
|---|---|
| tasto | prefix c |
| riga di comando di tmux | prefix : poi new-window -n log |
| shell | tmux new-window -n log — anche da fuori, anche da uno script |
La riga di comando di tmux ha il completamento con Tab e la cronologia con le frecce. Ed è il posto dove provare un comando prima di metterlo nel file di configurazione: se funziona lì, funzionerà legato a un tasto.
Gli indirizzi
Il pezzo che rende tutto questo utile è l'opzione -t, che dice
su cosa agire. La sintassi è gerarchica e si legge da sinistra:
sito:2.1 # pannello 1 della finestra 2 della sessione "sito" sito:log # la finestra chiamata "log", ovunque sia sito: # la finestra attiva della sessione "sito" :2 # finestra 2 della sessione corrente .1 # pannello 1 della finestra corrente =sito # corrispondenza esatta, non per prefisso # abbreviazioni speciali: -t ! # l'ultima finestra / il pannello precedente -t {last} # l'ultima usata -t {next} # la successiva -t {end} # l'ultima in ordine
sito.it rende ambiguo sito.it:1, e
tmux prova a interpretare .it come indice di pannello. Trattini e
trattini bassi: sempre.
send-keys: scrivere in un pannello da fuori
send-keys inserisce testo nell'input di un pannello come se lo
avessi battuto tu. È il comando che trasforma tmux da interfaccia a strumento di
automazione.
$ tmux send-keys -t sito:server 'npm run dev' C-m # └── C-m = Invio $ tmux send-keys -t sito:2.1 'tail -f /var/log/nginx/error.log' C-m $ tmux send-keys -t deploy C-c # manda un Ctrl-C, interrompe $ tmux send-keys -t sito:1 'clear' C-m # lo stesso comando in tutti i pannelli della finestra: $ tmux list-panes -F '#{pane_id}' | xargs -I{} tmux send-keys -t {} 'date' C-m
Le chiavi speciali si scrivono con i nomi che tmux conosce: C-m o
Enter per l'invio, C-c per l'interruzione,
C-d, Escape, Up. Senza C-m
finale il comando compare nel pannello ma non parte: è l'errore che si fa tutti
la prima volta.
send-keys scrive nel
pannello, qualunque cosa ci sia dentro: se c'è Vim aperto e non una shell, il tuo
comando diventa testo nel file. Prima di automatizzare, verifica con
tmux list-panes -a -F '#{session_name}:#{window_index}.#{pane_index}
#{pane_current_command}'.
Il pannello sincronizzato
prefix : setw synchronize-panes on # ora ogni tasto va in tutti i pannelli della finestra. # Con quattro pannelli, ognuno in ssh su una macchina diversa, # aggiorni quattro server scrivendo una volta sola. # nel .tmux.conf, con un tasto e un segnale visibile: bind S setw synchronize-panes \; display "sync: #{?pane_synchronized,ON,off}"
È potentissimo e va spento subito dopo. Dimenticarlo acceso significa lanciare per
sbaglio lo stesso comando distruttivo su quattro macchine: il
display nella riga qui sopra esiste apposta.
Uno script che costruisce l'ambiente di lavoro
Se ogni mattina apri le stesse quattro finestre nella stessa disposizione, quel lavoro si scrive una volta. Lo script qui sotto crea la sessione staccata, la riempie, e alla fine ci si attacca — e se la sessione esiste già non fa nulla, si limita a entrare.
#!/usr/bin/env bash set -euo pipefail SES=sito DIR=~/progetti/sito-cliente if ! tmux has-session -t "=$SES" 2>/dev/null; then # finestra 1: editor, con un pannello per git sotto tmux new-session -d -s "$SES" -n codice -c "$DIR" tmux send-keys -t "$SES:codice" 'vim .' C-m tmux split-window -v -p 25 -t "$SES:codice" -c "$DIR" # finestra 2: server di sviluppo, acceso tmux new-window -t "$SES" -n server -c "$DIR" tmux send-keys -t "$SES:server" 'npm run dev' C-m # finestra 3: due log affiancati tmux new-window -t "$SES" -n log -c "$DIR" tmux send-keys -t "$SES:log" 'tail -f storage/logs/app.log' C-m tmux split-window -h -t "$SES:log" tmux send-keys -t "$SES:log" 'tail -f /var/log/nginx/error.log' C-m tmux select-window -t "$SES:codice" tmux select-pane -t "$SES:codice.1" fi # attacca da fuori, cambia client se sei già dentro tmux if [ -z "${TMUX:-}" ]; then tmux attach -t "=$SES" else tmux switch-client -t "=$SES" fi
-d su
new-session costruisce tutto senza attaccarsi, così i comandi
successivi non vengono interrotti; -p 25 su
split-window assegna al pannello nuovo il 25 per cento dello spazio;
has-session con = davanti al nome evita di trovare una
sessione dal nome simile.
Se preferisci un file di descrizione
Esistono strumenti che fanno la stessa cosa a partire da un file YAML invece che
da uno script: tmuxinator (Ruby) e tmuxp (Python) sono i
due più diffusi. Sono comodi se hai molti progetti dalla struttura simile; per
due o tre ambienti, lo script di venti righe si legge meglio e non ha dipendenze
da installare sul server.
session_name: sito
start_directory: ~/progetti/sito-cliente
windows:
- window_name: codice
layout: main-horizontal
panes:
- vim .
- git status
- window_name: server
panes:
- npm run dev