Rediscovering Tmux and Screen

I have recently resurrected some older devices with flaky connectivity and while ssh-ing into them had to use some terminal tricks (aka multiplexers) to restore connections if disconnected (or to purposely disconnect/reconnect on long commands). I used tmux where possible, but occasionally only GNU screen was available, making a summary of features opportune.

screenshot of terminal ssh connection split windows with tmuxI don’t use either tmux or screen regularly, and, having had to refresh my memory on using both, I thought I commit my notes to this blog. I only need either for connecting to remote systems via ssh, in order to restore a session that may be interrupted by poor connectivity or multitasking (i.e., rather than wait for a task to finish, I might have to disconnect and come back to it later, without interrupting it).

In Windows I generally use MobaXterm for SSH connections. The screenshot is taken from this program, which allows tiling of several “instances” much like the multiplexers, but without the ability to restore sessions.

Both tmux and screen use a configurable “prefix” – a key combination giving the program notice that a command follows. For example, in both cases you use prefix + ? for a list of commands. I don’t normally change the default prefix.

Before delving into either, it’s a good idea to try to make sense of the terminology used by the programs.

Let's take Vim's terminology as a good example and then proceed to tmux and GNU Screen. Vim has the following entities when it comes to files and how they appear on the screen:

  • buffer -- holds the file
  • window -- displays one of buffers
  • tab -- displays one or more windows

tmux provides nice example of how one should never name things (it still gives me hard time remembering the naming):

  • window -- this is a "tab" in Vim and pretty much any other application
  • pane -- this is a "window" in Vim (very intuitive to name different things with very similar words, isn't it?..)

Naming is not strong part of GNU Screen as well, but there is a logic behind most of it:

  • window -- this is like a "buffer" in Vim (strange naming, but it gets better)
  • region -- this is like a "window" in Vim (makes sense, "region" suits well)
  • layout -- a "tab" in Vim (near perfect match, "tab" is just a layout container)

(via rt-tmx2scr)

TMUX

Tmux (short for “terminal multiplexer”) is the most popular such a tool. By default, the prefix is Ctrl+b and the config file is in ~/.tmux.conf.

To get more info about your current tmux setup, issue

  • tmux list-keys - lists out every bound key and the tmux command it runs
  • tmux list-commands - lists out every tmux command and its arguments
  • tmux info - lists out every session, window, pane, its pid, etc.

In a session one can create more than one window which can then spawn one pane. Windows show in the green bar at the bottom of the screen, but I find that I’m fine with one window per session and multiple panes when on a big monitor. Multiple windows without panes may be suitable on smaller monitors:

  • tmux new-window (prefix + c) create a new window
  • tmux select-window -t :0-9 (prefix + 0-9) move to the window based on index
  • tmux rename-window (prefix + ,) rename the current window (or A?)

In terms of window navigation, prefix + number or ‘ changes to window 0 to 9, n/p or <space>/<backspace> changes to next window on the list, “ shows window list, w shows window bar.

scrollback

I find that I can simply press PgUp and then PgDn to scroll back and once that’s done, I can even scroll with the mouse wheel.

To have tmux start or attach every time you login to a system with in interactive shell, add this to your remote system’s ~/.bash_profile file:

if [ -z "$TMUX" ]; then
    tmux attach -t default || tmux new -s default
fi

Otherwise, you start with a session (issuing tmux new –s yoursessionname) and “attach” to (tmux a or tmux attach and specify a named session with -t sessionname). List sessions with tmux ls or tmux list-sessions.

Important commands (following the prefix):

  • d - “detach” (or –d as a switch on the tmux command)
  • x – pane kill’em (followed by y to confirm) or to kill a detached session tmux kill-session –t sessionname.
  • & - Force kill-all processes in an unresponsive window
  • % - split current pane into two vertical panes (also tmux split-window-h)
  • " - horizontal split (also split-window).
  • arrow key – switch between panes (also tmux select-pane)
  • { or } – swaps pane with another in the specified direction (also tmux swap-pane)
  • z – toggle current pane into full screen (zoom or unzoom one pane) ; also tmux attach -t 0

Run the same commands to all panes at once with :setw synchronize-panes.

sharing

Sharing a session may seem quite complicated and counterintuitive at first sight.

Screen and tmux's behaviour for when multiple clients are attached to one session differs slightly. In Screen, each client can be connected to the session but view different windows within it, but in tmux, all clients connected to one session must view the same window.

This problem can be solved in tmux by spawning two separate sessions and synchronizing the second one to the windows of the first. This is accomplished by first starting a new session:

tmux new -s <base session>

Then pointing a second new session to the first:

tmux new-session -t <base session> -s <new session>

However, this usage of tmux results in the problem that detaching from these mirrored sessions will start to litter your system with defunct sessions which can only be cleaned up with some pretty extreme micromanagement.
I wrote a script to solve this problem, call it tmx and use it simply with tmx <base session name>.

See Brandur’s article for his script and more on sharing (ml-prctmx).

People have been using it to customize their workflow (especially in conjunction with vim and plugins such as powerline) and that usually involves changing tmux.conf.

SCREEN

Sometimes tmux is not available and you cannot install it, but still need a way to “restore” a session on disconnect. GNU screen responds to that demand. Its default prefix is Ctrl + a and the config file is ~/.screenrc.

I start screen using screen –S name which names the session I create. One could also use screen -dRR which attaches to a screen session. If the session is attached elsewhere, detaches that other display. If no session exists, creates one. If multiple sessions exist, uses the first one.)

scrollback

  • Ctrl+u – half page up
  • Ctrl+d – half page down
  • Ctrl+b – back
  • Ctrl +f- forward
  • h/j/k/l – cursor left/down/up/right

Here are the most important commands to remember, with the character to hit after prefix:

  • c - Creates a new screen session so that you can use more than one screen session at once.
  • n - Switches to the next screen session (if you use more than one).
  • p - Switches to the previous screen session (if you use more than one).
  • d - Detaches a screen session (without killing the processes in it - they continue). Use –d SCREENID to detach a session in another terminal.
  • w – display a list of all sessions currently opened.
  • A – rename the current session.
  • M – monitor for output – screen will fash an alert at the bottom when output is registered.
  • _ – you get notified when there is no more output (monitor for silence).
  • x – lock session, password required to restart. To require password at each reattach, add password crypt_password to .screenrc, where the crypt_… was created with mkpasswd.
  • k – equivalent to command exit which kills the current session and falls back to the next or to the terminal if no more sessions are running.
  • \ – “panic” button – exit all programs; D D detach & logout and Ctrl \ is forced exit
  • S – split screen horizontally into “regions”
  • l – split screen vertically
  • tab – switch input focus to next region; Ctrl+a toggle back to the last session; :resize
  • # – go to session number # (e.g., 1, 2, 7)
  • F – fit screen size to terminal size; equivalent to :fit.
  • “ – choose the session to move on.
  • Q – close all regions but current.
  • X – close the current region; equivalent to :remove.
  • H – activate logging (screenlog.0 in home directory); same as switch –L when starting session.
  • [ – start copy mode.
  • <space> – toggle selection to copy
  • ] – paste the copied text.
  • Ctrl+l – redraw windows

To list sessions, do screen –ls and to reconnect to one do screen –r [sessionname] or screen -x.

If using it regularly, consider adding this to your .bashrc:

# Auto-screen invocation. see: http://taint.org/wk/RemoteLoginAutoScreen
# if we're coming from a remote SSH connection, in an interactive session
# then automatically put us into a screen(1) session.   Only try once
# -- if $STARTED_SCREEN is set, don't try it again, to avoid looping
# if screen fails for some reason.
if [ "$PS1" != "" -a "${STARTED_SCREEN:-x}" = x -a "${SSH_TTY:-x}" != x ] 
then
  STARTED_SCREEN=1 ; export STARTED_SCREEN
  screen -RR -S main || echo "Screen failed! continuing with normal bash startup"
fi
# [end of auto-screen snippet]

Sharing among users

It is possible to use SCREEN to share a screen with other users, while simultaneously typing and seeing what each other is typing, or disabling writing permissions for one user.

  • Prefix + : then multiuser on to enable multiuser sessions.
  • Prefix + : again followed by aclchg newusername -w “#” (newusername is the the user to share with and -w is to disable write permission for that user) .
  • While logged in as newusername issue screen –x originalusername/ .

This might be useful in tech support or while working with remote team members.

Customizations in .screenrc

I collected the following from a few posts and post them here before having tested them:

  • defscrollback 30000 # Set scrollback buffer to 30000
  • hardstatus alwayslastline # Customize the status line
  • hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %m-%d %{W}%c %{g}]'
  • escape ^Bb # Instead of Control-a, make the escape/command character be Control-b as in tmux (optional)
  • autodetach on # Autodetach session on hangup instead of terminating screen completely (this might’ve been necessary back in 2007 – mc2007-screen)
  • startup_message off # Turn off the splash screen
  • shell -$SHELL # always use a login shell

I’m not terribly concerned with colors, but if you’re using tmux and terminal work extensively, the following could be useful.

# support color X terminals
termcap  xterm 'XT:AF=\E[3%dm:AB=\E[4%dm:AX'
terminfo xterm 'XT:AF=\E[3%p1%dm:AB=\E[4%p1%dm:AX'
termcapinfo xterm 'XT:AF=\E[3%p1%dm:AB=\E[4%p1%dm:AX:hs:ts=\E]2;:fs=\007:ds=\E]2;screen\007'
termcap  xtermc 'XT:AF=\E[3%dm:AB=\E[4%dm:AX'
terminfo xtermc 'XT:AF=\E[3%p1%dm:AB=\E[4%p1%dm:AX'
termcapinfo xtermc 'XT:AF=\E[3%p1%dm:AB=\E[4%p1%dm:AX:hs:ts=\E]2;:fs=\007:ds=\E]2;screen\007'

DOTCONF

As shown above, there’s a significant amount of configuring that can only be preserved if one saves configuration files and restores them to a new system. Such configuration files are called “dotfiles” and many people save them and share them on github:

  • anishathalye/dotbotIf – “bootstrap your dotfiles” – see also blog post
  • paulirish/dotfiles – macOS mostly: “If you're starting off consider forking mathias or alrra. paulmillr and gf3 also have great setups”
  • webpro/awesome-dotfiles - Inspired by the awesome list thing.
  • gpakosz/.tmux - Self-contained, pretty and versatile .tmux.conf configuration file.
  • thoughtbot/dotfiles - From time to time you should pull down any updates to these dotfiles, and run rcup.
  • cowboy/dotfiles - I finally decided that I wanted to be able to execute a single command to "bootstrap" a new system to pull down all of my dotfiles and configs, as well as install all the tools I commonly use. In addition, I wanted to be able to re-execute that command at any time to synchronize anything that might have changed. Finally, I wanted to make it easy to re-integrate changes back in, so that other machines could be updated.
  • lewagon/dotfiles - This repository is used by Le Wagon students during our 9-week coding bootcamp.
  • holman/dotfiles - I realized I could split a lot of things up into the main areas I used (Ruby, git, system libraries, and so on), (..) read my post on the subject.
  • alrra/dotfiles - These are the base dotfiles that I start with when I set up a new environment.

I subscribe to the opinion that most dotfiles may be too personal to share, but the above are far more elaborate than most people need and would likely be more useful to you than my own. I hope this helped.

Sources / More info: tmux cheatsheet, tmuxcheatsheet, se-usescr, powerline, mc2007-screen, autoscreen, screenfaq, scrtmx, yc-tmxtldr, rt-tmx2scr, su-tmxscrl, ml-prctmx, lp-taotmx, atk-dcxtmchts, gh-avtmxcht.

Comments

Popular posts from this blog