Tmux scripting

25 September 2011 (updated 25 September 2017)

I usually need to run more than 1 command for some project and got tired of searching through those putty windows for the session I want. So I thought of using a terminal multiplexer like Tmux.

I'm using celery with two queues and I need to run this:

  • manage.py celeryd -Q queueA
  • manage.py celeryd -Q queueB
  • manage.py celerycam -E

I need celerycam because it will get those stats in djcelery up to date.

It's also a good idea to tail the postgresql log - when you break your models or database in some cases Django isn't very helpful so this helps a lot:

  • tail -f /var/log/postgresql/postgresql-8.4-main.log

I use a wide screen so I want a layout like this:

+------------------------------------+-------------------+
|                                    |                   |
|              runserver             |                   |
|                                    |     celerycam     |
+------------------------------------+                   |
|                                    |                   |
|               celeryd              +-------------------+
|                                    |                   |
+------------------------------------+                   |
|                                    |   postgresql log  |
|               celeryd              |                   |
|                                    |                   |
+------------------------------------+-------------------+

I also want to start a new tmux session from the same command so I can close everything easily - those celeryd's don't reload automatically :(

You'd usually run something like:

tmux new-session "tmux splitw 'command1';  tmux splitw 'command3'; tmux splitw 'command3'; command4"

But that gets rather long and you need to quote and escape, calculate the panel sizes manually (I want equal height) and for the layout above you also need to select the right panels before splitting.

The commands vary across projects (some have more and some have less) - so how about we make a script:

import subprocess

left_commands = [
    "python manage.py runserver",
    "python manage.py celeryd -Q queueA -c 2 -E -n worker1",
    "python manage.py celeryd -Q queueB -c 2 -E -n worker2",
]
right_commands = [
    "python manage.py celerycam",
    "tail -f /var/log/postgresql/postgresql-8.4-main.log",
]
session = ''

if right_commands:
    session += 'tmux selectp -t 0; tmux splitw -hd -p 35 \"%s\"; ' % right_commands[-1]
for index, command in enumerate(right_commands[:-1]):
    session += 'tmux selectp -t 1; tmux splitw -d -p %i \"%s\"; ' % (
        100 / (len(right_commands) - index),
        command
    )

for index, command in enumerate(left_commands[1:]):
    session += 'tmux selectp -t 0; tmux splitw -d -p %i \"%s\"; ' % (
        100 / (len(left_commands) - index),
        command
    )
if left_commands:
    session += left_commands[0]

args = [
    'tmux',
    'new-session',
    session,
]
print 'Running ', args
subprocess.call(args)

This entry was tagged as celery django postgresql python sql tmux