Tmux - čo to je a ako ho používam
27.03.2021
Tmux je skratkou terminal-multiplexer a nikto nevie, čo to znamená. Je to nástroj pre terminál, ktorý nám umožňuje v ňom mať "taby" a panely a okrem toho nás zachráni v prípade, keď niečo robíme na serveri a spadne nám internet. Mne pomáha aj veľmi rýchlo si jedným príkazom spustiť všetko, čo potrebujem k práci. Tmux sa pre mňa stal úplne základným nástrojom a bol som celkom prekvapený, keď som zistil, že kolegovia ho nepoznajú.
Nudné predstavenie
Tmux je modernejším a myšlienkovým nástupcom programu, ktorý sa volá screen. Oboje sú aplikácie, ktoré umožňujú mať taby (v ich terminológii sú to "okná") v termináloch a okrem toho je možné sa od nich odpojiť, pričom oni a programy v nich spustené bežia ďalej. Keď sa dokážete odpojiť, tak sa viete aj naspäť pripojiť.
Toto je užitočné napríklad aj pre administráciu serveru. Pripojím sa na server, spustím tmux (alebo screen), v ňom naštartujem nejaký dlhotrvajúci skript. Odpojím sa z tmux-u, odpojím sa zo serveru a idem domov. Doma sa opäť pripojím a pozriem, ako môj dlhotrvajúci skript napreduje.
Tmux má oproti screen-u aj panely, čo vlastne znamená, že viete okno rozdeliť na viacero častí a v každej mať samostatný shell.
Killer feature tmux-u je však podľa mňa to, že umožňuje programovo zasielať príkazy a simulovať písanie do hociktorej svojej session a hociktorého okna 🤯.
K čomu je to dobré?
Ja mám tmux rád, pretože jeho taby sú nezávislé na termináli a zaberajú menej miesta na výšku. Ale najmä tmux používam na rýchle naštartovanie projektov a setup pracovných nástrojov.
Keď chcem ísť programovať Wareenu, čo je jeden z mojich projektov s PHP backendom a React-om na frontende, tak potrebujem urobiť kopec vecí na to, aby som mohol pohodlne vyvíjať a všetko mal na dosah ruky. Konkrétne:
- spustiť docker kontajnery
- prihlásiť sa do kontajneru s PHP, aby som mohol spúšťať napr. composer
- prihlásiť sa do kontajneru s node, aby som tam hneď spustil HMR
- prihlásiť sa do kontajneru s PHP a pripraviť si tam príkaz na spustenie PHPUnit-u
- prihlásiť sa do kontajneru s databázou a otvoriť pripojenie
- prihlásiť sa do kontajneru s fixtúrovou databázou a otvoriť pripojenie
- prihlásiť sa do kontajneru s node a spustiť websocket server
- nastaviť sa do adresáru s projektom, aby som odtiaľ ľahko spúšťal príkazy (napr. git)
- nastaviť sa do adresáru s projektom, aby som odtiaľ spustil editor
Keby som nemal tmux, tak by som pri týchto požiadavkách skončil s tým, že sa mi otvorí 8 samostatných terminálových okien. Trochu lepšia situácia by bola v prípade, keby som používal terminál umožňujúci programovo otvárať nové taby a spustiť v nich príkaz, ale taký nepoznám.
S pomocou tmux-u si však viem k tomuto napísať skript a potom to spúšťať jediným príkazom (alebo aj klávesovou skratkou).
Základy práce v tmux-e
Inštalácia
Tmux sa na Linuxe inštaluje klasicky cez balíčkovací manažér (napr. apt install tmux
), na Mac-u
cez Homebrew (brew install tmux
) alebo MacPorts (port install tmux
).
Na Windowse ho nepotrebujeme, lebo Windows je predsa pre programátora hernou konzolou a nie
pracovným nástrojom 😃. (Ak ale máte na Windowse WSL, tak inštalujte cez balíčkovací systém
distribúcie.)
Spustenie a okná
Tmux spustíme v konzole príkazom tmux
. (Kto by to bol povedal.)
tmux
Týmto príkazom sa spustí nová tmux session. Session môžete mať viac a každá je samostatná so svojimi oknami. Ak však chceme, tak sa vieme z jednej session pozrieť do druhej.
Pre konfigurovanie je dôležité vedieť, že prvá session na pozadí spustí aj tmux server, s ktorým komunikujú všetky session a ktorý zaniká s poslednou ukončenou. Tento server si drží konfiguráciu. Ak sa teda budeme hrať s konfiguračným súborom pre tmux, tak zmeny sa nám neprejavia, kým bude bežať aspoň jedna session. Musíme ich najskôr všetky vypnúť a naštartovať tmux odznova.
V spustenom tmux-e máme rovno otvorené prvé okno (má číslo 0). Ak chceme otvoriť ďalšie, tak sa to robí klávesovou skratkou CTRL+B C, čo znamená, že najskôr stlačíme CTRL+B, potom uvoľníme oba klávesy a stlačíme C.
Všetky klávesové skratky v tmux-e začínajú prefixom, ktorý je defaultne nastavený na CTRL+B. Je však možné ho zmeniť buď pre aktuálnu session alebo rovno v konfiguračnom súbore na stálo. Ja osobne som si prefix zmenil na CTRL+A, pretože tak to bolo v screen-e a zvykol som si a zároveň mi to je príjemnejšie.
Ďalej budem namiesto CTRL-B
alebo CTRL-A
uvádzať {prefix}
a vy tam budete stláčať to,
čo ste si nakonfigurovali.
Medzi oknami sa prepíname skratkou {prefix} číslo-okna. Ak je okien viac, ako desať, tak ich zoznam si zobrazíme skratkou {prefix} W
Zoznam základných skratiek, vyskúšajte si:
Skratka | Čo robí |
---|---|
{prefix} C | vytvorenie ďalšieho okna |
{prefix} číslo | prepnutie do okna s danýmn číslom |
{prefix} W | zobrazenie zoznamu okien (pohyb šípkami, potvrdenie Enter) |
{prefix} , | premenovanie aktuálneho okna |
{prefix} " | vertikálne rozdelenie aktuálneho panelu na dve časti |
{prefix} % | horizontálne rozdelenie aktuálneho panelu na dve časti |
{prefix} ! | vytvorenie nového okna z aktuálneho panelu |
{prefix} šípka | pohyb medzi panelmi |
{prefix} : | zadanie konfiguračného príkazu |
{prefix} d | odpojenie sa od session |
Príkazy
Tmux má hrozne veľa príkazov. Viete ich zadávať ako parametre príkazu tmux
alebo priamo v
bežiacom tmux-e do príkazového riadku zobrazenom po stlačení {prefix} :. A tie isté
príkazy zapisujete aj do konfiguračného súboru (defaultne ~/.tmux.conf
).
Ak je možné príkaz jednoznačne identifikovať aj z časti jeho názvu, tak ho nemusíme písat celý. Napríklad nemusíme písať list-sessions
a úplne postačí list-s
.
Zoznam niektorých užitočných príkazov:
Príkaz | Čo robí |
---|---|
set {premenná} {hodnota} |
nastaví konfiguračnú premennú, napr. set prefix C-a zmení prefix na CTRL+A |
set -g {premenná} {hodnota} |
nastaví premennú globálne pre session a okná (takto to píšte v konfiguračnom súbore) |
new-session |
vytvorí novú session |
list-sessions |
vypíše zoznam všetkých bežiacich session a ich názvov |
new-window |
vytvorí nové okno |
send-keys -t {názov-session}:{názov-okna} |
odošle "klávesy" do okna v danej session |
attach-session -t {názov-session} |
pripojí sa do session s daným názvom |
rename-session {názov} |
premenuje session |
source "cesta" |
načíta konfiguráciu z iného súboru |
run-shell "príkaz" |
spustí konzolový príkaz |
Príkazy môžu mať vlastné prepínače (klasicky unixovské písmenkové flagy začínajúce pomlčkou).
Pre detaily je dobré si pozrieť dokumentáciu (príkaz man tmux
v konzole).
Moja konfigurácia
Tmux sa konfiguruje v súbore ~/.tmux.conf
.
U mňa tmux vyzerá takto:
Spodný riadok je "tabbar". Úplne naľavo je názov session, potom nasleduje zoznam okien, uptime, systémový load, dátum a čas a názov počítača.
Dosiahol som to touto konfiguráciou:
# prefix bude CTRL+A
set -g prefix C-a
# Chvíľku čakáme na escape sekvencie.
# Vysvetlenie viď https://unix.stackexchange.com/questions/608142/whats-the-effect-of-escape-time-in-tmux
set -g escape-time 10
# Chceme pekné farby
set -g default-terminal "tmux-256color"
set -ga terminal-overrides ",*256col*:Tc"
# O vizuál tmux-u sa mi stará powerline
run-shell "powerline-daemon -q"
source "/usr/share/powerline/bindings/tmux/powerline.conf"
Ak sa vám nepáči defaultný vzhľad tmux-u, tak existuje veľa možností na to, aby ste si to nastavili
podľa svojho gusta (pozrite man tmux
). Ak to chcete mať rovnaké ako ja, tak si potrebujete
nainštalovať powerline a k tomu ešte fonty (na Ubuntu apt install powerline fonts-powerline
).
Zázračný skript pre spustenie projektu
Spomínal som, že mám vytvorené skripty pre jednoduché spúšťanie projektov. Jeden taký mám pre projekt Wareenu a po spustení skriptu sa mi naštartujú docker kontajnery, rovno ma do niektorých prihlási a všetko je pripravené tak, aby som len otvoril neovim a mohol programovať.
Takto to vyzerá po spustení skriptu:
Do konzoly iba napíšem start-wareena.sh
, pár sekúnd počkám (lebo docker kontajnery chvíľku
štartujú) a môžem pracovať.
Skript samotný vyzerá takto, kľudne sa inšpirujte a upravte pre svoje potreby. Nezabudnite mu dať práva na spúšťanie.
#!/bin/bash
# názov tmux-ovej session
SESSION_NAME=wareena
# ak už session s týmto názvom existuje, tak sa do nej len pripojíme
if tmux has-session -t=$SESSION_NAME 2>/dev/null; then
tmux attach -t $SESSION_NAME
exit;
fi
# adresár, kde sú zdrojáky projektu
TARGET_DIR="/home/perun/projects/wareena/src/web"
# adresár, kde je umiestnený docker-compose.yml k projektu
DOCKER_DIR="/home/perun/projects/wareena"
# id aktuálneho používateľa (aby som sa do docker neprihlásil ako root)
USER_ID=`id -u $USER`
# aktuálny počet riadkov a stĺpcov v termináli (docker občas hnevá a nevie to správne detekovať)
LINES=`tput lines`
COLUMNS=`tput cols`
# Príkaz na prihlásenie sa do web kontajneru.
# V tomto projekte mám ten istý kontajner pre PHP aj pre node
WEB_LOGIN_CMD="cd $DOCKER_DIR; docker exec --user $USER_ID -it -e COLUMNS=$COLUMNS -e LINES=$LINES wareena_php_1 bash"
# Príkaz pre prihlásenie do databázového kontajneru
DB_LOGIN_CMD="cd $DOCKER_DIR; docker exec -it -e COLUMNS=$COLUMNS -e LINES=$LINES wareena_db_1 bash"
# Príkaz pre prihlásenie do kontajneru s fixtúrovou databázou
FIXTURE_DB_LOGIN_CMD="cd $DOCKER_DIR; docker exec -it -e COLUMNS=$COLUMNS -e LINES=$LINES wareena_fixture_db_1 bash"
# Naštartovanie kontajnerov
cd $DOCKER_DIR
docker-compose up -d
# Občas nejaký kontajner nenaštartuje, vtedy nechcem pokračovať
read -p "Continue with a new tmux session [Y/n]?" yn
case $yn in
[Nn]* ) exit;;
* ) echo "OK";;
esac
# Vytvorím novú tmux session:
# - nechcem sa do nej hneď pripnúť (-d parameter), inak by sa zvyšné príkazy spustili az po jej ukončení :)
# - so zvoleným názov (-s parameter)
# - vytvorím aj nový tab/okno a rovno ho pomenujem (-n parameter)
tmux new-session -d -s $SESSION_NAME -n webserver
# Povytváram zvyšné taby
tmux new-window -n node
tmux new-window -n src
tmux new-window -n misc
tmux new-window -n test
tmux new-window -n db
tmux new-window -n fixture_db
tmux new-window -n ws
# V tabe webserver sa prihlásim do web kontajneru.
# Parameter -t určuje cieľovú session a okno
tmux send-keys -t $SESSION_NAME:webserver "$WEB_LOGIN_CMD" Enter
# V tabe pre node sa prihlásim do kontajneru a spustím HMR
tmux send-keys -t $SESSION_NAME:node "$WEB_LOGIN_CMD" Enter
tmux send-keys -t $SESSION_NAME:node "yarn dev" Enter
# V tomto tabe spúšťam neovim, len sa prepnem do adresáru so zdrojákmi
tmux send-keys -t $SESSION_NAME:src "cd $TARGET_DIR" Enter
# Tu spúšťam kadejaké príkazy (napr. git), len sa prepnem do adresáru so zdrojákmi
tmux send-keys -t $SESSION_NAME:misc "cd $TARGET_DIR" Enter
# Pripravím si tab pre spúšťanie testov pre PHPUnit
tmux send-keys -t $SESSION_NAME:test "$WEB_LOGIN_CMD" Enter
tmux send-keys -t $SESSION_NAME:test "export SYMFONY_DEPRECATIONS_HELPER=disabled=1" Enter
tmux send-keys -t $SESSION_NAME:test "bin/phpunit"
# Prihlásim sa do databázy
tmux send-keys -t $SESSION_NAME:db "$DB_LOGIN_CMD" Enter
tmux send-keys -t $SESSION_NAME:db "sleep 5; mysql -u root wareena" Enter
# Prihlásim sa do fixtúrovej databázy
tmux send-keys -t $SESSION_NAME:fixture_db "$FIXTURE_DB_LOGIN_CMD" Enter
tmux send-keys -t $SESSION_NAME:fixture_db "sleep 5; mysql -u root wareena" Enter
# V poslednom tabe spustím websocket server
tmux send-keys -t $SESSION_NAME:ws "$WEB_LOGIN_CMD" Enter
tmux send-keys -t $SESSION_NAME:ws "node bin/ws-server.js" Enter
# Pripojím sa do vytvorenej session a do tabu, kde chcem spustiť neovim
tmux attach -t $SESSION_NAME:src