5

I'd like to create a simple tmux conf that does the follow.

  1. Splits the window/pane/whatever_stupid_terminology horizontally (hsplit)
  2. Opens in the top pane tail -f foo
  3. Opens in the bottom pane tail -f bar

How can I do this with tmux.

This is what I've got,

#!/bin/sh
tmux new-session -s asdf -n myWindow
tmux select-window -t myWindow
tmux split-window "tail -f /var/log/apache2/samperror.log" 
tmux attach-session -t asdf

I can't get anything thought to work. So I know it's all wrong. One of the most unintuitive conf files ever

  • Your question refers to a tmux configuration file but your example is a standalone shell script; what approach are you actually interested in? – jasonwryan Aug 11 '14 at 20:39
  • @jasonwryan thanks for that. I was desperate and I switched from a plain conf file -- which is what I'd prefer. – Evan Carroll Aug 11 '14 at 20:48
7

Here's a quick and dirty command-line that achieves what you want:

$ tmux new-session -s asdf -n myWindow -d 'tail -f foo'\; \
       split-window -d 'tail -f bar'\; attach-session

There are a few drawbacks to this solution:

  • it doesn't scale very well (a few more commands and the result is incomprehensible).

  • the two tail commands aren't run in an interactive shell, so if you exit them both, the window myWindow will be destroyed (together with the session if you haven't created any more sessions.


Here's a shell script that works along the lines that you tried. For me it's always easiest to think about how I would achieve my goal manually and then translate that into tmux commands. This might not be the simplest or cleanest way, but it usually works:

#!/bin/sh
# create a new session. Note the -d flag, we do not want to attach just yet!
tmux new-session -s asdf -n 'myWindow' -d

# send 'tail -f foo<enter>' to the first pane.
# I address the first pane using the -t flag. This is not necessary,
# I'm doing it so explicitly to show you how to do it.
# for the <enter> key, we can use either C-m (linefeed) or C-j (newline)
tmux send-keys -t asdf:myWindow.0 'tail -f foo' C-j

# split the window *vertically*
tmux split-window -v

# we now have two panes in myWindow: pane 0 is above pane 1
# again, specifying pane 1 with '-t 1' is optional
tmux send-keys -t 1 'tail -f bar' C-j

# uncomment the following command if you want to attach
# explicitly to the window we just created

#tmux select-window -t asdf:mywindow

# finally attach to the session
tmux attach -t asdf

If after some trying you still don't like the tmux command and configuration syntax, you might want to look into tmuxinator, a Ruby gem that lets you manage tmux sessions with a simplified and more transparent syntax.


In my answer to Multiple terminals at once without an X server you can find a few links to helpful tmux resources

1

Based on the answer here is more generic code:

tmuxMany(){
    #https://unix.stackexchange.com/a/149729/47116
    if [ $# -lt 2 ]; then
        echo usage: sessionName command1 command2 ...
        return 1
    fi
    local sessionName=$1
    local firstCommand=$2
    local secondAndRestCommands=( "${@:3}" )

    tmux new-session -s $sessionName -n 'myWindow' -d
    tmux send-keys -t $sessionName:myWindow.0 "$firstCommand" C-j
    local i
    for i in "${!secondAndRestCommands[@]}"
    do
        echo $i
        local command=${secondAndRestCommands[$i]}
        echo $command

        tmux split-window -v
        local tabNumber=$((i+1))
        tmux send-keys -t $tabNumber "$command" C-j
    done
    tmux select-layout even-vertical
    tmux attach -t $sessionName
}

Usage:

tmuxMany sessionName "tail -f file" "tail -f file2" htop

Will open tmux with 3 panes of equal height.

0

Assuming you do want to run this from your ~/.tmux.conf, not an external script, you would append this to your config file:

# session initialisation
new -s SessionName -n WindowName 'tail -f /var/log/apache2/samperror.log'
splitw -h -p 50 -t 0 'tail -f /var/log/apache2/other.log'
selectw -t 0

Then, when you start tmux with the command to attach to a session, tmux a, it will create SessionName with the window split horizontally (-h) in half (-p 50) running those two commands.

  • is there anyway to make the session automagically attach so I can just run tmux -f tmux.conf, and if the session already exists it attaches it -- otherwise it initializes and attaches? – Evan Carroll Aug 13 '14 at 1:11
  • @EvanCarroll That is what the a (a contraction of attach) is for. You can always write a function, like so: tmuxa() { [[ -z "$TMUX" ]] && { tmux attach -d || tmux -f $HOME/.tmux/conf new -s SessionName ;} } – jasonwryan Aug 13 '14 at 1:19
  • So there is no way to do it from within the .conf file? – Evan Carroll Aug 13 '14 at 1:32
  • 1
    @EvanCarroll that wouldn't really make much sense; it would, among other things, prevent you from opening a separate tmux session. – jasonwryan Aug 13 '14 at 1:39
0

This is how I launch an editor + REPL now:

mux $(basename $(pwd)) \
  "vim $(find src test resources test-resources -type f 2>/dev/null \
    | tr "\n" " ")" \
  "lein repl"

I hacked on Maxim's code to get a different layout:

#!/bin/bash

#https://unix.stackexchange.com/a/149729/47116
if [ $# -lt 2 ]; then
    echo usage: sessionName command1 command2 ...
    return 1
fi
sessionName=$1
firstCommand=$2
secondAndRestCommands=( "${@:3}" )

tmux new-session -s $sessionName -n 'myWindow' -d
WIN="$sessionName:myWindow"
tmux send-keys -t $WIN.1 "$firstCommand" C-j
for i in "${!secondAndRestCommands[@]}"
do
    command=${secondAndRestCommands[$i]}
    echo $i: $command

    tmux split-window -v
    tabNumber=$((i+2))
    tmux send-keys -t $tabNumber "$command" C-j
done
tmux select-pane -t $WIN.1

fixlayout() {
    tmux set-window-option -t $WIN main-pane-width $(($COLUMNS - 80))
    tmux select-layout -t $WIN main-vertical
}
fixlayout
sleep 1 && fixlayout &

tmux attach -t $sessionName

Incidentally this guy's tmux.conf seems pretty useful.

0

Try something like this:

$ chmod +x tmux.conf
$ cat tmux.conf
#!/usr/bin/tmux source-file
new-session -s asdf -n myWindow "tail -f /var/log/maillog"
split-window "tail -f /var/log/messages"

When you run ./tmux.conf, tmux executes each command in turn, creating the layout you requested.

The surprising part is that tmux -f tmux.conf only runs the commands in tmux.conf for the first session that's created. If you already have sessions running, the -f tmux.conf is silently ignored. You can work around that with tmux source-file tmux.conf. You can use that in a shebang line, to make it a script.

I've found this technique really helpful. In the root of each of my project directories, I have an executable tmux.conf. When I start working on that project again, I run ./tmux.conf to create the work environment that I prefer for that project.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.