Shellkonfiguration – Konsolen-Tools

tmux

Hinweis: Ich steige gerade erst von screen auf tmux um, bin damit also noch nicht annähernd so vertraut wie mit den anderen bisherigen Themen auf dieser Website (bash und systemd). Deshalb mag es hier in den nächsten Wochen und Monaten mit größerer Wahrscheinlichkeit als bei den übrigen Inhalten zu Änderungen kommen.

Die von tmux verwalteten "virtuellen" Pseudoterminals unterscheiden sich (potentiell) in folgenden Kategorien:

Ein typischer Fall der tmux-Nutzung (tmux-Konfigurationsdatei, nicht verantwortlich für den Shell-Prompt oder die Terminalfarben):

ec:0   02:09:36  hl@notebook:~
start cmd:>

















C-q  ---  0:local-1- 1:local-2* 2:host-1  3:host-2  4:host-3  5:host-4              

Links in der Statuszeile wird ein abweichender escape key angezeigt (Standard ist Ctrl-b); das ist besonders bei (über SSH hinweg) verschachtelten tmux-Instanzen nützlich, um leichter den Überblick zu behalten.

Die einzelnen Fenster kann man jeweils manuell nach dem Start von tmux erzeugen oder automatisch beim Start erzeugen lassen (in der Konfigurationsdatei).

Aufruf per Shellfunktion

Wenn tmux noch nicht läuft, kann man es einfach mit tmux starten; wenn keine Kommandos übergeben werden, wird new-session angenommen. Wenn es schon läuft, kann man die laufende Session mit tmux attach betreten. Man kann sich aber auch eine kleine Shellfunktion definieren, so dass tmux je nach Situation eine neue Session startet oder sich an die bestehende hängt. Wenn irgendwelche Argumente auf tmux folgen, wird die eingegebene Kommandozeile ausgeführt, unabhängig vom Zustand des Systems.

Der folgende Code ist für bash.

tmux () {
    if [ $# -eq 0 ]; then
        command tmux attach-session;
    else
        command tmux "$@";
    fi
}

verschachtelte Instanzen

Eine platzsparende und in der Navigation sehr effiziente Arbeitsweise ist:

Nach meinem Empfinden ist es besser, wenn der escape key für alle innersten Instanzen derselbe ist. Eine innerste Instanz sollte genauso zu bedienen sein wie eine nicht verschachtelte Instanz. Beide sind die "normale" Situation. Eine tmux-Instanz zu starten, in der (mindestens) eine weitere Instanz laufen soll, ist der Spezialfall, der eine abweichende Steuerung haben sollte. Für einen intuitiven Bezug zwischen der Verschachtelung und der Position der escape keys sollte derjenige der inneren Instanz weiter "oben" auf der Tastatur liegen. Ich nutze Ctrl-q für die innerste Instanz und Ctrl-a für die äußerste. Beides lässt sich sehr gut mit nur der linken Hand drücken.

tmux-Konfigurationsdatei der inneren tmux-Instanz; tmux-Konfigurationsdatei der äußeren tmux-Instanz

ec:0   01:38:48  hl@notebook:~
start cmd:>

















C-q host-1  ---  0:home* 1:systemd  2:scripts                                       
C-a  ---  0:local-1- 1:local-2  2:host-1* 3:host-2  4:host-3  5:host-4              

Die am häufigsten benutzten Systeme und (auf dem entfernten System) Verzeichnisse bzw. Anwendungen auf festen Positionen innerhalb von tmux zu haben, bringt den großen Vorteil mit sich, dass man quasi "blind" (ohne Blick auf den Bildschirm) zwischen den entsprechenden Terminals wechseln kann.

mehrere Sessions

Wenn man (z.B. via SSH) häufig mit denselben Systemen zu tun hat, insbesondere bei häufigen, schnellen Wechseln zwischen den Systemen, ist es hilfreich, wenn sich diese Systeme (also die Konsolen mit der SSH-Verbindung zu dem jeweiligen System) immer an derselben Stelle befinden. Wenn man insgesamt nur mit sehr wenigen (<10) Systemen zu tun hat, kann man in derselben tmux-Ansicht alle diese Systeme unterbringen.

Der häufigere Fall dürfte sein, dass man nicht alle Systeme (plus mindestens eine Konsole für das lokale System) in die maximal zehn leicht erreichbaren tmux-Fenster bekommt (vielleicht möchte man auch nicht zehn Fenster nutzen, weil wegen langer Fensternamen nicht alle gleichzeitig in das Konsolenfenster passen wie in den Beispielen hier).

Eine komfortable Lösung dafür ist, die Systeme in unterschiedlichen Sessions zusammenzufassen. Das Kriterium für die Gruppierung sollte den Komfort des Nutzers maximieren. Eine sinnvolle Möglichkeit ist die Gruppierung nach Umgebungen (plus eine Gruppe für die lokalen Konsolen): Produktion, Integration, Test.

Eine Session ist eine Gruppe von Fenstern (mindestens eins). Auf demselben tmux-Server können mehrere Sessions laufen (zumindest eine). Ein tmux-Client (die Software, deren Ausgabe man unmittelbar sieht und bei der die Tastatureingaben (zuerst) landen) kann nur mit einer Session zur Zeit verbunden sein, aber man kann leicht zwischen mehreren Sessions umschalten (ohne den Client zu beenden). Auf diese Weise kann man die Systeme mit derselben Funktion in Produktion und Integration auf die Position 0 (Window 0) legen, jeweils in den Sessions prod und int. Dadurch kann man problemlos mehr als zehn Systeme auf jeweils derselben Position haben, so dass man "blind" (ohne Blick auf den Bildschirm) umschalten kann. Mit zwei Tastenkombinationen hintereinander (die erste für die Session, die zweite für das Fenster) kann man die gewünschte Konsole erreichen. Wenn die Systeme immer an derselben Position liegen, weiß man nach kurzer Zeit, über welche Fensternummer man ein System erreicht, so dass man nicht in der Statusleiste nachlesen muss.

ec:0   01:38:48  hl@notebook:~
start cmd:>

















C-q prod-host-1  ---  0:home* 1:systemd  2:scripts                                  
C-a Session: prod  ---  0:prod-host-1* 1:prod-host-2  2:prod-host-3-                

Session-Setup in der Konfigurationsdatei

Auch in nicht verschachtelten Setups hat man mindestens eine Session (wenn man keine in der Konfigurationsdatei definiert, wird eine ohne Namen automatisch erzeugt).

Die Option -A für new-session und -S für new-window verhindern, dass tmux beim Neuladen der Konfiguration im laufenden Betrieb eine Fehlermeldung ausgibt, wenn schon eine Session mit demselben Namen existiert. Statt dessen wechselt der tmux-Client zu dieser Session (wie bei attach-session). In ähnlicher Weise wird kein neues Fenster erzeugt, wenn schon eins mit demselben Namen in derselben Session existiert, und (wie bei select-window) das existierende Fenster aktiviert (-d verhindert, dass das Fenster aktiviert wird).

new-session -A -s local -n 'local-1'
set-option status-style bg=brightgreen,fg=black
set-window-option window-status-current-style bg=white
new-window -S -d -n 'local-2'
new-window -S -d -n 'local-3'

new-session -A -s prod -n 'prod-host-1'
set-option status-style bg=yellow,fg=black
set-window-option window-status-current-style bg=white
new-window -S -d -n 'prod-host-2'
new-window -S -d -n 'prod-host-3'

new-session -A -s int -n 'int-host-1'
set-option status-style bg=cyan,fg=black
set-window-option window-status-current-style bg=white
new-window -S -d -n 'int-host-2'
new-window -S -d -n 'int-host-3'

new-session -A -s test -n 'test-host-1'
set-option status-style bg=green,fg=black
set-window-option window-status-current-style bg=white
new-window -S -d -n 'test-host-2'
new-window -S -d -n 'test-host-3'

Session-Umschaltung

Es gibt mehrere Möglichkeiten, zwischen Sessions umzuschalten:

Konfiguration der Bildschirmelemente

Im einfachsten Fall fügt tmux dem Terminal nur eine Statuszeile hinzu. Man kann aber viel mehr als das konfigurieren. Das ist natürlich einerseits sehr subjektiv, andererseits hängt von der Arbeitsweise ab, was sinnvoll erscheint (etwa, ob man mit mehreren Sessions arbeitet). Mein tmux sieht (je nach Situation) ungefähr so aus (bis auf die Farben):

─↓Pane 0 (ID %14 TTY /dev/pts/19) active (zoomed)─────────────────────────────────────────────────
──Pane 0 (ID %0 TTY /dev/pts/1) inactive (sync──┬──Pane 1 (ID %5 TTY /dev/pts/8) active (synced)──
                                                │
ec:0   22:11:55  root@selinux-test:~            │ec:0   22:11:55  root@selinux-test:~
start cmd:> echo foo                            │start cmd:> echo foo
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
                                                │
C-e Host: selinux-test Session: main   1:home* 2:scripts  3:tmp- 4:man  5:bash                    
C-q Host: notebook Session: ssh   1:local  2:selinux-test*Z 3:selinux_laging- 4:selinux_testuser  

Durch die Titelzeile verliert man pro pane eine Zeile, aber bei typischen Terminalgrößen ist das kein Problem. Die Information, dass in einem window eine pane gezoomt oder markiert ist, bekommt man allerdings auch in der Statuszeile. Pane index, ID und TTY brauche ich nur selten, und inzwischen gibt es im pane-Menü einen Eintrag, der das gut anzeigt. Die aktive pane wird farblich hervorgehoben, diese textliche Unterscheidung ist also auch nicht mehr wichtig. Aber ich mag den Hinweis, dass eine pane gezoomt oder Teil der synchronisierten Eingabe ist.

set -g pane-border-status top

set -g pane-border-indicators both

set -g pane-border-format "Pane #{pane_index} (ID #{pane_id} TTY #{pane_tty}) #{?pane_active,active,inactive}#{?window_zoomed_flag, (zoomed),}#{?pane_synchronized, (synced),}#{?pane_marked, (marked),}#{?pane_input_off, (input disabled),}"

set pane-border-style fg=#777777

Man kann eine Tastenkombination an ein Menü binden und über das Menü eins von mehreren Kommandos auswählen (über die Pfeiltasten oder die dem Eintrag zugewiesene Ziffer oder Taste). Soweit praktikabel nehme ich die Standardbelegung als Menü-Auswahltaste, so dass man das Menü auch dafür verwenden kann, die Standardbelegungen nachzulesen.

Menüs eignen sich dafür, mit wenigen Tastenkombinationen viele Kommandos zu erreichen. Meine Empfehlung ist:

Zeicheneingabe

Es gibt Situationen, in denen die Eingabe bestimmter Zeichen(folgen) in der Konsole nicht leicht oder nicht auf dem normalen Weg möglich ist:

Die Übersicht der Zeicheneingabe-Menüs erreicht man bei mir über leaderUEnter.

ec:0   01:38:48  hl@notebook:~
start cmd:>



     ┌─character input menu overview───────────────────────────────────────┐
     │ Control character menu (Enter)                                      │
     │ Escape sequence menu (Backspace)                                    │
     │ (for wrong keyboard layout) shell characters: X                     │
     │ (for wrong keyboard layout) non-shell ASCII special characters: V   │
     │  ----- The Unicode menus are activated via two keys: U + menu index │
     │ space, hyphen, superscripts, subscripts: U 1                        │
     │ quotes, arrows, math symbols: U 2                                   │
     │ ASCII alphabet lowercase: U 5                                       │
     │ ASCII alphabet uppercase: U 6                                       │
     │ language-specific characters - de/German: U 7                       │
     └─────────────────────────────────────────────────────────────────────┘



C-q prod-host-1  ---  0:home* 1:systemd  2:scripts                                  
C-a Session: prod  ---  0:prod-host-1* 1:prod-host-2  2:prod-host-3-                

Steuerzeichen

Ein Menü für die Eingabe von Sonderzeichen (bei mir auf Enter).

Dieses Menü nutze ich häufig (das hat natürlich mit den Umständen meiner Arbeit zu tun und mag bei anderen Linuxern anders aussehen). Man kann es auch dafür nutzen, die Bedeutung der Steuerzeichen und die Zuordnung von backslash escapes zu Steuerzeichen nachzulesen. Ich habe es auf Enter gelegt, weil

ec:0   01:38:48  hl@notebook:~
start cmd:>
                ┌─inserting control characters─────────────┐
                │ exit virsh console / telnet (^])     (]) │
                │ exit qm terminal (^O)                (o) │
                │ abort SSH connection (\n ~ .)        (~) │
                │ detach docker (^P ^Q)                    │
                ├──────────────────────────────────────────┤
                │ tab: (^I)                            (i) │
                │ backspace: (^H)                      (h) │
                │ linefeed / newline: \n (^J)          (j) │
                │ carriage return: \r (^M)             (m) │
                ├──────────────────────────────────────────┤
                │ SIGINT: (^C)                         (c) │
                │ SIGQUIT: (^\)                        (\) │
                │ suspend foreground process(es): (^Z) (z) │
                │ end of file: (^D)                    (d) │
                │ flow control XOFF: (^S)              (s) │
                │ flow control XON: (^Q)               (q) │
                │ input next character literally: (^V) (v) │
                ├──────────────────────────────────────────┤
                │ record separator: (^^)               (^) │
                │ unit separator: (^_)                 (_) │
                │ file separator: (^\)                 (\) │
                │ NUL: (^@)                            (@) │
                │ Escape: (\e / ^[)                    ([) │
                ├──────────────────────────────────────────┤
                │ Ctrl-a: (^A)                         (a) │
                │ Ctrl-b: (^B)                         (b) │
                │ Ctrl-e: (^E)                         (e) │
                │ Ctrl-f: (^F)                         (f) │
                │ Ctrl-g: (^G)                         (g) │
                │ Ctrl-k: (^K)                         (k) │
                │ Ctrl-l: (^L)                         (l) │
                │ Ctrl-n: (^N)                         (n) │
                │ Ctrl-p: (^P)                         (p) │
                │ Ctrl-r: (^R)                         (r) │
                │ Ctrl-t: (^T)                         (t) │
                │ Ctrl-u: (^U)                         (u) │
                │ Ctrl-w: (^W)                         (w) │
                │ Ctrl-x: (^X)                         (x) │
                │ Ctrl-y: (^Y)                         (y) │
                └──────────────────────────────────────────┘
C-q prod-host-1  ---  0:home* 1:systemd  2:scripts                                  
C-a Session: prod  ---  0:prod-host-1* 1:prod-host-2  2:prod-host-3-                

Ein Menü für die Eingabe von Steuerzeichen / Steuersequenzen ist aus mehreren Gründen sinnvoll:

Natürlich kann man Enter nicht als Auswahltaste im Menü definieren, weil das die Menüfunktion ruiniert. Deshalb steht hier (Enter) nur im Text, als Hinweis darauf, dass man Enter benutzen kann, wenn man nicht das Menü nutzt.

Escapesequenzen

Ein Menü für die Eingabe von Escapesequenzen (bei mir auf Backspace):

ec:0   01:38:48  hl@notebook:~
start cmd:>




                         ┌─inserting escape sequence─┐
                         │ F1:  (\eOP)           (1) │
                         │ F2:  (\eOQ)           (2) │
                         │ F3:  (\eOR)           (3) │
                         │ F4:  (\eOS)           (4) │
                         │ F5:  (\e[15~)         (5) │
                         │ F6:  (\e[17~)         (6) │
                         │ F7:  (\e[18~)         (7) │
                         │ F8:  (\e[19~)         (8) │
                         │ F9:  (\e[20~)         (9) │
                         │ F10: (\e[21~)         (0) │
                         │ F11: (\e[23~)             │
                         │ F12: (\e[24~)             │
                         └───────────────────────────┘




C-q prod-host-1  ---  0:home* 1:systemd  2:scripts                                  
C-a Session: prod  ---  0:prod-host-1* 1:prod-host-2  2:prod-host-3-                

Ein Menü für die Eingabe von Escapesequenzen kann aus mehreren Gründen sinnvoll sein:

Shell-Zeichen

Dies ist nicht für normale Situationen gedacht, sondern als Rettungsring, wenn die normale Eingabe nicht möglich ist. Deshalb liegt dieses Menü bei mir auf X, weil dies auf den meisten Tastaturen an derselben Stelle ist. Wenn man ein System, das nicht mehr ordentlich startet (was zugegebenermaßen auch die Funktion von tmux beeinträchtigen kann), reparieren muss, aber die Shell-Zeichen nicht (oder nur sehr aufwendig) eingeben kann, hat man ein ernstes Problem.

ec:0   01:38:48  hl@notebook:~
start cmd:>


      ┌─inserting keys (with wrong keyboard layout): shell───────────────────┐
      │  / : paths: ls -l /var/log                                           │
      │  - : options: ls -l                                                  │
      │  * : dynamic globbing: ls -l *.txt                                   │
      │  ? : 1-char globbing: ls -l app.log.?                                │
      │  [ : character list globbing: ls -l *[^~]                            │
      │  ] : character list globbing: ls -l /proc/[1-9]*/exe                 │
      │  ' : quoting without expansion: echo '$HOME'                         │
      │  " : quoting without expansion: echo "5  +  3 = $((5+3))"            │
      │  $ : parameter expansion / command substitution                      │
      │  | : pipeline / OR list: echo foo | grep oo  /  echo foo || echo bar │
      │  & : background execution / AND list: cmd &  /  echo foo && echo bar │
      │  = : variable assignment: text=foo                                   │
      │  \ : escaping shell characters: echo foo \; bar "foo \$HOME bar"     │
      │  < : input redirection: cat < /path/to/file                          │
      │  > : output redirection: echo foo | grep oo >results.txt             │
      │  ; : end a command: echo foo; echo bar                               │
      │  ( : subshell: ( echo execute in separate environment )              │
      │  ) : command substitution / arithmetic evaluation: $()  /  $((1+1))  │
      │  { : command grouping (start): { echo foo; echo bar; } >output.txt   │
      │  } : command grouping (end): testfunc () { echo foo; }               │
      │  # : start comment: chmod 700 "$HOME" # fix permissions              │
      └──────────────────────────────────────────────────────────────────────┘


C-q prod-host-1  ---  0:home* 1:systemd  2:scripts                                  
C-a Session: prod  ---  0:prod-host-1* 1:prod-host-2  2:prod-host-3-                

sonstige ASCII-Zeichen

Die übrigen ASCII-Sonderzeichen (auf V)

ec:0   01:38:48  hl@notebook:~
start cmd:>


          ┌─inserting non-shell ASCII special characters─┐
          │  ^                                           │
          │  °                                           │
          │  !                                           │
          │  §                                           │
          │  %                                           │
          │  @                                           │
          │  €                                           │
          │  ,                                           │
          │  :                                           │
          │  .                                           │
          │  _                                           │
          │  @                                           │
          │  €                                           │
          │  µ                                           │
          │  `                                           │
          │  ´                                           │
          │  ²                                           │
          │  ³                                           │
          └──────────────────────────────────────────────┘


C-q prod-host-1  ---  0:home* 1:systemd  2:scripts                                  
C-a Session: prod  ---  0:prod-host-1* 1:prod-host-2  2:prod-host-3-                

Unicode-Zeichen

Dieser Teil ist nicht spezifisch für Terminals. Ich hatte immer eine Textdatei, aus der ich Sonderzeichen kopieren kann. Da ich nun sowieso schon eine Eingabefunktion für Zeichen in tmux habe und tmux sowieso immer läuft, liegt es nahe, die Eingabemenüs um Unicode-Zeichen zu erweitern.

Da es sehr viele Unicode-Zeichen gibt (und nicht jeder dieselben wichtig findet), habe ich das Unicode-Menü zweiteilig gestaltet:

bind U switch-client -T multikey_unicode

bind-key -T multikey_unicode Enter display-menu ...

Durch die Definition einer weiteren key binding table kann man mit einer zweistufigen Auswahl arbeiten:

ec:0   01:38:48  hl@notebook:~
start cmd:>

          ┌─inserting unicode characters (1)───────────────────┐
          │  Byte Order Mark little endian (U+FEFF) (BOM):     │
          │  non-breaking space (U+202F)                       │
          │  zero-width space (U+200B)                         │
          │  - ASCII hyphen-minus (U+002D)                     │
          │  ‐ hyphen (U+2010)                                 │
          │  ‑ non-breaking hyphen (U+2011)                    │
          │    soft hyphen (U+00AD) (line break only)          │
          │  – en dash (U+2013) (range; spaced sentence break) │
          │  — em dash (U+2014) (unspaced sentence break)      │
          │  ― horizontal bar (U+2015)                         │
          │  ‒ figure dash (U+2012) (digit seperator)          │
          │  − minus sign (U+2212)                             │
          │  ⁻ superscript minus (U+207B)                      │
          │  ₋ subscript minus (U+208B)                        │
          │  ⁰ (U+2070)                                        │
          │  ¹ (U+00B9)                                        │
          │  ² (U+00B2)                                        │
          │  ³ (U+00B3)                                        │
          │  ⁴ (U+2074)                                        │
          │  ⁵ (U+2075)                                        │
          │  ⁶ (U+2076)                                        │
          │  ⁷ (U+2077)                                        │
          │  ⁸ (U+2078)                                        │
          │  ⁹ (U+2079)                                        │
          │  ₀ (U+2080)                                        │
          │  ₁ (U+2081)                                        │
          │  ₂ (U+2082)                                        │
          │  ₃ (U+2083)                                        │
          │  ₄ (U+2084)                                        │
          │  ₅ (U+2085)                                        │
          │  ₆ (U+2086)                                        │
          │  ₇ (U+2087)                                        │
          │  ₈ (U+2088)                                        │
          │  ₉ (U+2089)                                        │
          └────────────────────────────────────────────────────┘

C-q prod-host-1  ---  0:home* 1:systemd  2:scripts                                  
C-a Session: prod  ---  0:prod-host-1* 1:prod-host-2  2:prod-host-3-                

Vor der Erstellung dieses Menüs hatte ich nur eine sehr unscharfe Vorstellung davon, wann die unterschiedlichen typographischen Striche eingesetzt werden und wie die Zeichen heißen. Ich habe diese Gelegenheit genutzt, das Menü mit entsprechenden Hinweisen zu versehen,

ec:0   01:38:48  hl@notebook:~
start cmd:>

          ┌─inserting unicode characters (2)─┐
          │  ‚ (U+201A)                      │
          │  ‛ (U+201B)                      │
          │  „ (U+201E)                      │
          │  ‟ (U+201F)                      │
          │  ʼ (U+02BC) (apostrophe)         │
          │  « (U+00AB)                      │
          │  » (U+00BB)                      │
          │  ‹ (U+2039)                      │
          │  › (U+203A)                      │
          │  • (U+2022)                      │
          │  → (U+2192)                      │
          │  ← (U+2190)                      │
          │  ↓ (U+2193)                      │
          │  ↑ (U+2191)                      │
          │  ↔ (U+2194)                      │
          │  ± (U+00B1)                      │
          │  + (U+002B)                      │
          │  − (U+2212)                      │
          │  × (U+00D7)                      │
          │  ÷ (U+00D7)                      │
          │  ≠ (U+2260)                      │
          │  ‰ (U+2030)                      │
          │  ☺ (U+263A)                      │
          │  ☐ (U+2610)                      │
          │  … (U+2026)                      │
          └──────────────────────────────────┘

C-q prod-host-1  ---  0:home* 1:systemd  2:scripts                                  
C-a Session: prod  ---  0:prod-host-1* 1:prod-host-2  2:prod-host-3-                
ec:0   01:38:48  hl@notebook:~
start cmd:>



        ┌─inserting unicode characters: de/German─┐
        │  ä                                      │
        │  Ä                                      │
        │  ö                                      │
        │  Ö                                      │
        │  ü                                      │
        │  Ü                                      │
        │  ß                                      │
        └─────────────────────────────────────────┘



C-q prod-host-1  ---  0:home* 1:systemd  2:scripts                                  
C-a Session: prod  ---  0:prod-host-1* 1:prod-host-2  2:prod-host-3-                

Terminalhöhe und variable Menüs

Leider kann tmux gelinde gesagt nicht gut mit Menüs umgehen, die mehr Zeilen benötigen, als das Terminal (in dem Moment) hat. Es wird nicht etwa gescrollt oder in zwei Spalten angezeigt; nein, das Menü wird einfach überhaupt nicht angezeigt. Das kann natürlich extrem problematisch sein, vor allem für diejenigen User, die nicht wissen, wie man die benötigte Funktion anderweitig aufruft, und die dann entweder (potentiell aufwendig) recherchieren müssten oder gleich ganz aufgeben. Zwei Möglichkeiten bieten sich an, wenn man dies vermeiden will; beide setzen voraus, das man sich auf eine Untergrenze festlegt, einen Wert, der nie unterschritten wird. Standard-VGA ist 80×25, aber in einer seriellen Konsole (Proxmox-VM) mit TERM=linux sehe ich 80×24. 24 dürfte eine sinnvolle Untergrenze sein. Da das Menü umrahmt wird, darf es also maximal 22 Zeilen haben.

Beim Start von tmux wird zuerst der Server (inklusive der Menüs) konfiguriert und dann mit dem Client verbunden. Da sich die (standardmäßige) Fenstergröße nach dem Client richtet, führt dies zu dem Problem, dass die oben gezeigte Auswertung dann noch nicht möglich ist – man bekommt immer das kleine Menü (bis man manuell die Konfiguration erneut lädt).

Die einzige mir bekannte passable Lösung ist, die Definition der Menüs in zwei (eine einheitliche und ggf. eine an das System angepasste) Dateien auszulagern und diese Dateien sowohl direkt beim Einlesen der Konfiguration (das ist nötig für den Fall, dass man sie später neu lädt) als auch per hook beim Verbinden eines Clients (das ist für den Start nötig) oder der Änderung der Fenstergröße einzubinden:

source-file ~/.tmux.menus-common.conf
set-hook -g client-attached "source-file ~/.tmux.menus-common.conf"
set-hook -g client-resized  "source-file ~/.tmux.menus-common.conf"

tmux in einer seriellen Konsole

Unabhängig von tmux ärgere ich mich seit langem darüber, dass Zeilenumbrüche in bash (muss nichts mit bash zu tun haben, ich nutze keine andere Shell) in der seriellen Konsole zumeist großes Unheil anrichten. Das Problem ist rein optischer Natur, die Kommandos funktionieren noch, wie sie sollen. Aber das Bearbeiten von langen Kommandozeilen wird dadurch nahezu unmöglich.

Lange dachte ich, dass ein Terminal-Multiplexer wie tmux oder screen diese Probleme nur vergrößern würde, aber es hat sich herausgestellt, dass das nicht der Fall ist. Ich habe immer noch das Problem, dass tmux standardmäßig über die erkannte Terminalgröße hinausschreibt (nur in die Breite). Ein Work-around für dieses Ärgernis ist, das tmux-Window eine Spalte schmaler (und zur Sicherheit eine Zeile niedriger) zu machen:

resize-window -x 79 -y 24

Konfigurationsdatei(en)

Aufteilung in mehrere Konfigurationsdateien

Auf unterschiedlichen (Gruppen von) Systemen und für unterschiedliche User will man wahrscheinlich unterschiedliche tmux-Konfigurationen haben (vor allem für die Session-Konfigurationen), alleine schon für die unterschiedlichen leader keys in verschachtelten tmux-Instanzen. Gleichzeitig will man den Aufwand minimieren, wenn man seine grundsätzliche Konfiguration ändert und diese Änderungen überall ausrollen will.

Eine einfache Lösung dafür ist,

~/.tmux.conf

source-file ~/.tmux.common.conf

unbind C-b
set -g prefix  C-q
set -g prefix2 C-b
bind-key C-q last


# colour is one of: black, red, green, yellow, blue, magenta, cyan, white; (if supported) brightred, brightgreen, brightyellow

new-session -A -s main -n 'home'
set-option status-style bg=brightgreen,fg=black
set-window-option window-status-current-style bg=white
new-window -S -d -n 'vim'
new-window -S -d -n 'tmp'
new-window -S -d -n 'man'
new-window -S -d -n 'bash'

new-session -A -s www -n 'home'
set-option status-style bg=cyan,fg=black
set-window-option window-status-current-style bg=white
new-window -S -d -n 'foo-1'
new-window -S -d -n 'foo-2'
new-window -S -d -n 'bar-1'
new-window -S -d -n 'bar-2'

new-session -A -s ssh -n 'local'
set-option status-style bg=yellow,fg=black
set-window-option window-status-current-style bg=white
new-window -S -d -n 'host-1'
new-window -S -d -n 'host-2'

attach-session -t main

~/.tmux.menus.conf

if-shell '[ #{client_height} -ge 23 ]' {
        bind-key C-s display-menu -T 'Session commands' \
                'List sessions'  '' 'list-sessions' \
                'Show session tree (w)' '' 'choose-tree -Zw' \
                'New session' '' 'command-prompt { new-session -s "%%" }' \
                'Rename session' & 'command-prompt -I "#S" { rename-session "%%" }' \
                'Kill session' '' 'confirm-before -p "kill-session #S? (y/n)" kill-session' \
                '' \
                '     Switch to another session' '' '' \
                'Switch to main' m 'switch-client -t main' \
                'Switch to www' w 'switch-client -t www' \
                'Switch to ssh' s 'switch-client -t ssh' \
                'Switch to previous session' ( 'switch-client -p' \
                'Switch to next session' ) 'switch-client -n' \
                'Switch to next session *' C-s 'switch-client -n' \
                'Switch to other session' '' 'command-prompt -T target { switch-client -t "%%" }' \
                '' \
                'Convert current session to group (for independent sharing)' '' "new-session -A -s #{session_name}2 -t #{session_name} " \
                'Link the current window to another session' '' 'command-prompt -T target { link-window -t "%%" }' \
                'Unlink window from this session' C-u 'unlink-window'
}

Wenn man regelmäßig mit Sessions arbeitet (v.a. mit mehr als zwei), dann bietet es sich an, das allgemeine Session-Menü zu überschreiben, um die in ~/.tmux.conf konfigurierten Sessions direkt aktivieren zu können (ich wähle als Auswahltaste den ersten Buchstaben des Session-Namens).

Allgemeine Konfigurationsdatei

Download