I am a big fan of tmux – a terminal multiplexer. Think of it as a text version of vnc client, with many more powerful features. In this post I will demo some of the tmux techniques that I use quite often.

Assumptions:

1) GNU version of tmux

2) Default shell is BASH

Preparation:

For demo’s purpose I make up a dummytask.sh to simulate the task(s) that we will be running in tmux windows:

#!/bin/bash taskname=$@ ans='' if [ -n "$taskname" ]; then while [ ! "$ans" == "q" -a ! "$ans" == "Q" ]; do read -e -n 1 -p "Running task $taskname, to exit, press q(Q). " ans done echo "Done task $taskname." else echo "Usage: $0 task." echo "Example1: $0 debugging" echo "Example2: $0 importing data" fi

Example: create a tmux session with session name mysess

tmux new-session -s mysess -d

If the option -d (detached) is omitted, you will be taken directly to the first window titled “0:bash” once the command is executed and any commands afterwards will be entered into that window. Therefore it’s a good habit to use option -d whenever creating a new session.

Example: create a new tmux session and change the first default window title to task1

[ type q, Enter, exit, Enter if the sess tmux session is currently attached ]

In the first example, tmux will create a first window titled “0:bash” (could be ksh, csh etc depending on default shell setting) by default, to change to something else, simply using -n (name) option:

tmux new-session -s sess -d -n task1

Example: create tmux session mysess if it has not been created yet

tmux list-session 2>&1 | grep -q "^mysess:" || tmux new-session -s sess -d

Notes: 2>&1 is to suppress error output “failed to connect to server: Connection refused”, which occurs when there are no tmux sessions running. -q is used to suppress the normal output of of grep. It won’t affect the result but using it makes the commands less distracting. Regular expression ^sess: is used to make sure it won’t match session name such as “sessionabc” by mistake. Logical operator || is just a shorthand form of if [ ! condititon ]; then … fi.

Example: create a new window title mywin in an existing tmux session mysess, if the window has not existed yet, create the session first if it hasn’t existed yet

#!/bin/bash sess=mysess wn=mywin tmux list-session 2>&1 | grep -q "^$sess" || tmux new-session -s $sess -d tmux list-window -t $sess 2>&1 | grep -q ": $wn \[" || tmux new-window -t $sess -n $wn

Example: run a script in mysess:mywin in the above example

#!/bin/bash sess=mysess wn=mywin tmux list-session 2>&1 | grep -q "^$sess" || tmux new-session -s $sess -d tmux list-window -t $sess 2>&1 | grep -q ": $wn \[" || tmux new-window -t $sess -n $wn tmux send-keys -t $sess:$wn "./dummytask.sh cooking" Enter

How do we know the above script is doing what we intended to do? Check out the next example.

Example: attach tmux session mysess

tmux a -t mysess

Example: run a script in the first window of the newly created tmux session

tmux new-session -s mysess -n mywin "bash dummytask.sh cooking"

This works but there’s a problem, once you exit the program by pressing q or Q, tmux session also terminates. This gets more annoying when a program crashes and you don’t get any debug info, a better handling of the task will be provided in the following example.

Example: run program in a tmux window and exit to bash shell inside the window if the program exits or crashes

#!/bin/bash sess=mysess wn=mywin # duplicate session or window handling code here # ... tmux send-keys -t $sess:$wn "./dummytask.sh cooking" Enter

Example: how to check if a tmux session is attached

Sometimes it’s desired to run certain command not in a tmux window, use the following code to detect if attempt is made to run some command inside a tmux window:

if [ "$TERM" = "screen" -a -n "$TMUX" ]; then echo "This command should be run when tmux is not attached" fi

Example: attach a tmux session with a specific window selected

#!/bin/bash sess=mysess tmux list-session 2>&1 | grep -q "^$sess" || tmux new-session -s $sess -d wn=win0 tmux list-window -t $sess 2>&1 | grep -q ": $wn \[" || tmux new-window -t $sess -n $wn tmux send-keys -t $sess:$wn "./dummytask.sh task 0" Enter wn=winX tmux list-window -t $sess 2>&1 | grep -q ": $wn \[" || tmux new-window -t $sess -n $wn tmux send-keys -t $sess:$wn "./dummytask.sh important mission" Enter wn=win1 tmux list-window -t $sess 2>&1 | grep -q ": $wn \[" || tmux new-window -t $sess -n $wn tmux send-keys -t $sess:$wn "./dummytask.sh another thing" Enter # here's the meat of this script, select window winX before attaching the session tmux select-window -t $sess:winX && tmux a -t $sess