––» HOME «––

tmux
what I like about using tmux

Table of Contents

1. Things I like about using tmux

If you are using the shell often - maybe because you log into one of your servers in a datacenter or because you use it for your daily tasks - you might know the problem that your shell only runs one command at a time1 and you'd have to wait for it to finish, before typing in the next one. Or you want to see two outputs simulaneously… You'd like to run a task and log out of the ssh session but revisit it later. There are a lot of scenarios where splitting the screen a couple of times or detach and reattach to a session would be handy.

That's where tmux or any other terminal multiplexer comes in. It allows you to do all these nice things and even more :)

1.1. Installation

On my gentoo machine I run:

thinkpad ~ # emerge -va tmux

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild   R    ] app-misc/tmux-3.1c::gentoo  USE="-debug (-selinux) -utempter -vim-syntax" 0 KiB

Total: 1 package (1 reinstall), Size of downloads: 0 KiB

Would you like to merge these packages? [Yes/No]

On a debian or ubuntu machine you'd likely run something like sudo apt install tmux or sudo apt-get install tmux.

And on a arch based distro you would say pacman -S tmux, I guess…

You can get the source code from github.

1.2. Usage

You can simply run tmux after installing it, to start a new session. tmux has a lot of options for you, but I'll only go through a few here.

One of them is -2 which enables 256 colors.

Another one is: if you start a new session you can name the session with tmux new-session -s <name_of_the_session>.

Since you can have multiple sessions, it is wise to name them, so you know what is running where :)

Incase you'd like to see all of your sessions at once you can list them like this:

$ tmux list-sessions
session_1: 9 windows (created Thu Aug 12 12:45:31 2021)
another_session: 4 windows (created Mon Aug 16 09:39:16 2021)
yet_another: 6 windows (created Fri Aug  6 18:50:33 2021) (attached)

I found this really handy little function:

tm ()
{
    [[ -n "$TMUX" ]] && change="switch-client" || change="attach-session";
    if [ $1 ]; then
        tmux $change -t "$1" 2> /dev/null || ( tmux new-session -d -s $1 && tmux $change -t "$1" );
        return;
    fi;
    session=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | fzf --exit-0) && tmux $change -t "$session" || tmux attach-session -t $session
}

(it was stolen from the fzf example page)2

I use this function to start or attach to a tmux-session. It's very handy - I'd reccomend it :>

tmux is also great for scripting. You can script multiple screens, split them up the way you like it and run commands in each one of them. For example you could write a script like this:

#!/bin/bash
#
# a simple tmux start-up-script
# to bring some monitoring tools up
SESSION="monitoring"

# open a new session named "monitoring"
tmux -2 new-session -s $SESSION -n top -d

# start top
tmux select-window -t $SESSION:0
tmux send-keys 'top' 'C-m'

# open a new window
tmux new-window -t $SESSION:1 -n platten
tmux select-window -t $SESSION:1

# run ncdu
tmux send-keys 'cd ~ && ncdu' 'C-m'
tmux split-window -h

# split the window vertical and fire up df -h and acpi -V
tmux send-keys 'watch df -h' 'C-m'
tmux split-window -v
tmux select-pane -t 2
tmux send-keys 'watch acpi -V' 'C-m'

# create a new window for bmon
tmux new-window -t $SESSION:2 -n bmon
tmux select-window -t $SESSION:2

# fire up bmon and show additional infos
tmux send-keys 'bmon' 'C-m'
tmux send-keys 'd' 'C-m'
tmux send-keys 'i' 'C-m'

# create a new window for bmon
tmux new-window -t $SESSION:3 -n atop
tmux select-window -t $SESSION:3

# split window and fire up apachetop
tmux send-keys 'atop' 'C-m'

# create a new window for bmon
tmux new-window -t $SESSION:4 -n iotop
tmux select-window -t $SESSION:4

# split window again and fire iotop
tmux send-keys 'su -c iotop' 'C-m'
tmux split-window -h
tmux send-keys 'watch who' 'C-m'
tmux split-window -v
tmux send-keys 'watch free -h' 'C-m'

# create a new window for bmon
tmux new-window -t $SESSION:5 -n netstat
tmux select-window -t $SESSION:5
tmux send-keys 'watch netstat -tulpen' 'C-m'

# attach to the session
tmux attach-session -t $SESSION

This script opens a few screens and splits them, to run informative commands with watch, so the output refreshes every 2 seconds.

The script starts with setting a variable called $SESSION:

SESSION="monitoring"

Then it goes on by starting a new session:

# open a new session named "monitoring"
tmux -2 new-session -s $SESSION -n top -d

The given arguments -2 (for 256 colors) and -n (for the window name) are optional.

First the script selects the screen from the new session, then it fires up top by sending the keys top to the tmux session.

After sending the keys, the scripts spawns a new screen, selects it and sends again some keys as input. This time cd ~ && ncdu. Which will change the current directory and visit the $HOMEDIR, then runs ncdu.

# start top
tmux select-window -t $SESSION:0
tmux send-keys 'top' 'C-m'

# open a new window
tmux new-window -t $SESSION:1 -n platten
tmux select-window -t $SESSION:1

# run ncdu
tmux send-keys 'cd ~ && ncdu' 'C-m'

Then we split the screen horizontal and send the keys watch df -h. If you know df and watch you propably know that this will show you the ssds (or harddrives) and updates the view every two seconds.

tmux split-window -h

# split the window vertical and fire up df -h and acpi -V
tmux send-keys 'watch df -h' 'C-m'

Which kinda looks like this:

Filesystem      Size  Used Avail Use% Mounted on
udev            3.9G     0  3.9G   0% /dev
tmpfs           798M   20M  779M   3% /run
/dev/sda2       195G   49G  137G  27% /
tmpfs           3.9G     0  3.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
/dev/sda1       922M  164M  695M  20% /boot
tmpfs           798M     0  798M   0% /run/user/0

…maybe :)

Then the script moves on and splits the screen vertical and runs watch acpi -V to see a verbose acpi output.

tmux split-window -v
tmux select-pane -t 2
tmux send-keys 'watch acpi -V' 'C-m'

After creating another screen (called window) and selecting it, the script runs bmon and types some keys (d and i) to adjust the view, which is very nice, too :)

# create a new window for bmon
tmux new-window -t $SESSION:2 -n bmon
tmux select-window -t $SESSION:2

# fire up bmon and show additional infos
tmux send-keys 'bmon' 'C-m'
tmux send-keys 'd' 'C-m'
tmux send-keys 'i' 'C-m'

This is repeated a couple of times and some programs are run. At last it attaches you to the tmux-session with:

# attach to the session
tmux attach-session -t $SESSION

It's not a big script but it may give you a hint where to start, though.

1.3. Screen vs tmux?

If I am not mistaking, then tmux and screen are the most popular terminal multiplexers out there (but I could be totally wrong). Comparing the two is a thing of personal taste, I guess. I use screen a lot when I am on a remote server in an ssh session and tmux on my personal laptop. Really don't know why… but it kinda worked out like this :)

So after all they're both great and I use both. (:

1.4. Simple example configuration

You can keep a .tmux.conf in your $HOME directory to configure tmux. Mine looks like this:

───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: .tmux.conf
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ run-shell "powerline-daemon -q"
   2   │ source "/home/marc/git/powerline/build/lib/powerline/bindings/tmux/powerline.conf"
   3   │ bind u send-keys C-l \; run-shell "sleep 0.3" \; clear-history
   4   │ bind o run "tmux split-window -l 12 'bash -ci ftpane'"
   5   │ set -g default-terminal "screen-256color"
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

I haven't configured much, as you can see. Only one or two key-bindings3, and I'm setting the $TERM envvar to screen-265color. And if you are looking at the two top lines, you can see that I use powerline whithin tmux by adding run-shell powerline-daemon -q I'm staring the powerline daemon (which one can guess from the line itself). The next one 'soureces' (reads the file and executes it's content) the powerline conf from my git directory. Which brings us to the last point of interest:

1.5. Extensions/ Plugins

There are lots of plugins for tmux. But I only use powerline myself. Feel free to browse the plugins and remember to have the right fonts installed to see all of the nice icons for battery or stuff like this. Sometimes a plugin doesn't work out of the box. that's a great way to learn how these plugins work. Examine the error you get and lear how to fix it ;) Sure will be fun :)

Footnotes:

1

…mostly when you are not running an X-server where you can press ctr+shift+t to open a new tab or you don't use ctr+z and bg to run it in the background… hope you know what I mean :>

2

See the fzf article.

3

The first one bind u send-keys C-l \; run-shell "sleep 0.3" \; clear-history executes when I'm pressing ctr+b and (letting the two go) u. Then it send the keys ctr+l to the window (to clear the screen), then it waits 0.3 seconds and clears the tmux history with clear-history. That way I can quickly clear my screen and my tmux history :).

The other one was an experiment from the fzf example page. It splits the window and fires up this function:

ftpane ()
{
    local panes current_window current_pane target target_window target_pane;
    panes=$(tmux list-panes -s -F '#I:#P - #{pane_current_path} #{pane_current_command}');
    current_pane=$(tmux display-message -p '#I:#P');
    current_window=$(tmux display-message -p '#I');
    target=$(echo "$panes" | grep -v "$current_pane" | fzf +m --reverse) || return;
    target_window=$(echo $target | awk 'BEGIN{FS=":|-"} {print$1}');
    target_pane=$(echo $target | awk 'BEGIN{FS=":|-"} {print$2}' | cut -c 1);
    if [[ $current_window -eq $target_window ]]; then
        tmux select-pane -t ${target_window}.${target_pane};
    else
        tmux select-pane -t ${target_window}.${target_pane} && tmux select-window -t $target_window;
    fi
}

Which lets you fzf-ish select a tmux pane :)

Date: 2021-09-01 Mi 13:37