Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash scripts with tmux to launch a 4-paned window

Tags:

bash

exec

tmux

Can anyone help explain what's going on with tmux, bash, and exec? I'm trying to set up a tmux session with a 4-pane window. Ideally, I want to run a command in 3 of the panes: e.g. a Ruby Thin server and a couple of Ruby daemons. This is what I have so far:

~/.bin/tmux-foo:

#!/bin/sh  tmux new-session -d -s foo 'exec pfoo "bundle exec thin start"' tmux rename-window 'Foo' tmux select-window -t foo:0 tmux split-window -h 'exec pfoo "bundle exec compass watch"' tmux split-window -v -t 0 'exec pfoo "rake ts:start"' tmux split-window -v -t 1 'exec pfoo' tmux -2 attach-session -t foo 

~/.bin/pfoo:

#!/bin/bash cd ~/projects/foo rvm use ree  # here I want to execute command1 2 3 or 4...  exec $SHELL 

It all works... but when I ctlr-c in the first pane that is running the thin server, it stops the thin server and returns to the shell. However, the command is not in the history; i.e. if I hit the up key I don't get the bundle exec thin start command... I get some other command from my bash history. I'm wondering if there's any way to arrange these scripts so that I get the commands in the bash history.

Also... I've tried many combinations of exec, exec $SHELL -s ..., and exec $SHELL -s ... -I and I'm not quite sure what is going on...

Can anyone help explain the general idea of what is going on with tmux and bash and exec here?

like image 263
Aaron Gibralter Avatar asked Mar 27 '11 04:03

Aaron Gibralter


2 Answers

As others have mentioned, your commands are being run by the shell script before launching your $SHELL; there is no general way the instance of $SHELL can know what its parent ran before starting it.

To get the “initial command” into the shell history, you need to feed the command keystrokes directly to the instance of $SHELL itself (after it has been started, of course). In other contexts I might suggest using a small Expect program to spawn an instance of $SHELL, feed it the keystrokes, then use interact to tie the tty to the expect-spawned $SHELL.

But in the context of tmux, we can just use send-keys:

#!/bin/sh  tmux new-session -d -s foo 'exec pfoo' tmux send-keys 'bundle exec thin start' 'C-m' tmux rename-window 'Foo' tmux select-window -t foo:0 tmux split-window -h 'exec pfoo' tmux send-keys 'bundle exec compass watch' 'C-m' tmux split-window -v -t 0 'exec pfoo' tmux send-keys 'rake ts:start' 'C-m' tmux split-window -v -t 1 'exec pfoo' tmux -2 attach-session -t foo 
like image 107
Chris Johnsen Avatar answered Oct 05 '22 10:10

Chris Johnsen


tmuxinator lets you specify this with a nice yaml file. For your case you could have:

# ~/.tmuxinator/foo.yml # you can make as many tabs as you wish...  project_name: foo project_root: ~/projects/foo rvm: ree tabs:   - main:       layout: tiled       panes:         - bundle exec thin start         - bundle exec compass watch         - #empty, will just run plain bash         - rake ts:start 

You can of course have extra windows etc.

like image 31
Hamish Downer Avatar answered Oct 05 '22 08:10

Hamish Downer