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:
…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 :>
See the fzf article.
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 :)