Skip to content

Shell Sessions / Tmux¤

Sessions are a required, when you document (or func test) longer command flows, with shared internal or external (e.g. filesystem) state.

  • We do not keep internal state within the docu building process but rely on tmux to keep it.
  • This makes state accessible out of band, i.e. you can attach to tmux sessions created by lp. This way you can, in long lasting, complex command flows (e.g. creating clusters in the cloud) fix failing commands manually until they run, add the fix to the failing last block and continue with the next.
  • Sessions are not automatically destroyed, except you instruct lp to do so.

Mechanics¤

  • We send the statements to evaluate over to tmux as a byte stream, using it's send-keys feature.
  • We capture the output of tmux via it's tmux capture-pane feature within a loop, until
    • the expected output is seen or
    • the timeout is reached

Example¤

LP Source:

 ```bash lp:bash session=docs addsrc
 ls -lta /etc/systemd
 ```

Result:

$ ls -lta /etc/systemd

$ ls -lta /etc/systemd                                
total 64            
drwxr-xr-x 138 root root 12288 Sep 30 14:07 ..                                  
drwxr-xr-x  20 root root  4096 Sep 30 14:07 system                              
-rw-r--r--   1 root root  1815 Sep 29 10:00 system.conf                         
drwxr-xr-x   5 root root  4096 Sep 29 09:58 .                                   
drwxr-xr-x   3 root root  4096 Sep  8 21:41 user                                
-rw-r--r--   1 root root   642 Jul 21 19:00 resolved.conf                       
-rw-r--r--   1 root root  1042 Apr 22  2020 journald.conf                       
-rw-r--r--   1 root root  1042 Apr 22  2020 logind.conf                         
drwxr-xr-x   2 root root  4096 Apr 22  2020 network                             
-rw-r--r--   1 root root   604 Apr 22  2020 timesyncd.conf                      
-rw-r--r--   1 root root  1185 Apr 22  2020 user.conf                           
-rw-r--r--   1 root root   584 Apr  1  2020 networkd.conf                       
-rw-r--r--   1 root root   529 Apr  1  2020 pstore.conf                         
-rw-r--r--   1 root root   790 Apr  1  2020 sleep.conf

Note that a --colors=always is not necessary here - the commands are run as if you would type them into a tmux window - in fact they are, using tmux send-keys.

Terminal Output¤

You should see output like this in the terminal, when building:

If the icons are missing then you need a proper font.

Tmux Base Index¤

Reminder tmux:

./img/tmux-diag.png

In order the mechanics to work we need to know the tmux window and pane base indexes of the window we are communicating with, i.e. the number of the first window created within a session.

Problem: Default is 0. But users using tmux configure it normally to 1 (easier window switching via shortcuts).

Since we do not want to fully control the life cycle of tmux sessions, i.e. allow the user to interact with it before, during and after our mkdocs sessions, it would be hard and prbly. not robust to always try find the base index currently in use - there are many things which can go wrong here.

So we decided to either

  • work out of the box, when base index is already at 1 (configured by the user) OR
  • configure the base index automatically, when there is NOT yet a ~/.tmux.conf on the system
  • fail when base index is configured to be 0

Warning

The second option involves a creation of ~/.tmux.conf (which you can naturally modify to your liking, except setting the base index to a different value than 1).

Tip

If you absolutely need to have 0 for you normal tmux work: Provide for mkdocs a tmux script, pointing to another config file in the make file or the environment ($PATH).

def configure_tmux_base_index_1(session_name):
    """
    Seems everybody really using it has 1 (on normal keyboards 0 is far away)
    and its a hard to detect or change, especially when the messed with it outside of
    our control. 

    On clean systems it will be just missing or: the user / runner does not care.

    => Lets create it - when it is NOT present, so that we can have automatic CI/CD.
    While for a normal user (who is using it) we fail if not configured correctly.
    """
    fn = env.get('HOME', '') + '/.tmux.conf'
    if exists(fn):
        return

    lp.app.warning('!!! Writing %s to set base index to 1 !!' % fn)
    r = [
        'set-option -g base-index 1',
        'set-window-option -g pane-base-index 1',
        '',
    ]
    write_file(fn, '\n'.join(r))
    lp.sprun('tmux source-file "%s"' % fn)
    wait(0.5)
    tmux_kill_session(session_name)
    wait(0.5)
    tmux_start(session_name)
    wait(0.5)