Michael Härtl
Michael Härtl

Reputation: 8607

How to start tmux with several windows in different directories?

I want to use a script to open a tmux session with 6 windows, each in a different directory. I started with a script I found and tried this first:

tmux new-session -s xyz   -n etc -d 'cd /etc'
tmux new-window  -t xyz:1 -n var    'cd /var/log'

But I soon found out that this will not work as I expected — the window will be closed after the shell command completes.

So my next idea was to start a new shell like this:

tmux new-session -s xyz   -n etc -d 'cd /etc; bash -i'
tmux new-window  -t xyz:1 -n var    'cd /var/log; bash -i'
tmux new-window  -t xyz:2 -n var2   'cd /var/log; bash -i'
tmux new-window  -t xyz:3 -n var3   'cd /var/log; bash -i'
tmux new-window  -t xyz:4 -n var4   'cd /var/log; bash -i'
tmux new-window  -t xyz:5 -n var5   'cd /var/log; bash -i'
tmux new-window  -t xyz:6 -n var6   'cd /var/log; bash -i'

tmux select-window -t xyz:1
tmux -2 attach-session -t xyz

This almost works. But if I start more than about 4 windows, I frequently see the following bash errors in one of the windows after startup:

bash: [: =: unary operator expected
bash: [: too many arguments
bash: [: =: unary operator expected
bash: [: =: unary operator expected
bash: [: =: unary operator expected
bash: [: =: unary operator expected
bash: [: too many arguments
bash: [: =: unary operator expected
bash: [: =: unary operator expected
bash: [: =: unary operator expected
bash: [: =: unary operator expected
bash: [: =: unary operator expected

I have no idea why this happens, but I still think that I’m not doing this right. Is there a better way to set up a tmux session over several directories?

Upvotes: 43

Views: 61593

Answers (7)

zzapper
zzapper

Reputation: 5041

This works for me . Each pane opens in a different directory

alias tmx='tmux new-session -c ~/Pictures \; split-window -v -c /intranet/homenote/ \; split-window -h -c ~/Videos/ \;'

Upvotes: 1

ThorSummoner
ThorSummoner

Reputation: 18199

For those who don't have ruby tmuxp is available in Python and supports both Teamocil and Tmuxinator style configuration files (in both yaml and json).

Not to mention there is a very sweet library behind it all https://github.com/tmux-python/libtmux

pip:

pip install --user tmuxp

Above: Add ~/.local/bin/ to your $PATH for python user install programs

apt (Debian / Ubuntu / Mint):

sudo apt install tmuxp

Brew:

brew install tmuxp

Configuration

# ~/.tmuxp/workbench.yaml
session_name: workbench
windows:
- name: workbench
  layout: main-vertical
  panes:
  - vim
  - pane
  - pane
tmuxp load workbench

You can load sessions directly: e.g. tmuxp load ./myworkspace.yaml

And finally, in your project-based config:

# tmuxp file aat project/.tmuxp.yaml
tmuxp load ./project

See documentation on tmuxp load for more information.

More configuration examples: https://tmuxp.git-pull.com/configuration/examples.html

Upvotes: 11

Schwesi
Schwesi

Reputation: 4904

To simply open tmux with multiple panes and run some commands, I created the following bash file:

#!/bin/bash
tmux split-window -v -p 30 -c ~/path/to/folder1
tmux split-window -h -p 66 -c ~/path/to/folder2
tmux split-window -h -p 50 'mongod'

Run the bash file to get the following:

-----------------------------------
|                                 |
|---------------------------------|
|  folder1  | folder2  |  mongod  |
-----------------------------------

Upvotes: 1

Goblinhack
Goblinhack

Reputation: 3096

I could not for the life of me get -c to work, so I worked around this by creating a script that is ran via send - this allows me to do whatever I want in each tmux session. In case it helps someone else, here it is:

#!/bin/bash
TMUX_SESSION=mystuff
TOP=~/mydir

tmux new-session -s "$TMUX_SESSION" -n $(pwd) -d

launch_my_window()
{
    WINDOW=$1
    NAME=$2
    SUBDIR=$3

    SCRIPT=$TMPDIR/tmux.sh.$WINDOW.$NAME
    tmux new-window -t "$TMUX_SESSION:$WINDOW" -n "$NAME"
    cat >$SCRIPT <<%%
cd $TOP/$SUBDIR
# do more stuff here
%%
    chmod +x $SCRIPT
    tmux send -t "$TMUX_SESSION:$WINDOW" $SCRIPT ENTER
    sleep 1
}

launch_my_window 1 "stuff"         subdir1
launch_my_window 2 "morestuff"     subdir2
launch_my_window 3 "yetmorestuff"  subdir3
#...

# Select window #1 and attach to the WINDOW
tmux select-window -t "$TMUX_SESSION:1"
tmux -2 attach-session -t "$TMUX_SESSION"

Upvotes: 3

Sam Stoelinga
Sam Stoelinga

Reputation: 5021

You can use Teamocil instead. Teamocil is a simple tool used to automatically create sessions, windows and panes in tmux with YAML files.

Upvotes: 9

Will
Will

Reputation: 4386

Tmuxinator is also really good for this. Basically you create setup files like so:

# ~/.tmuxinator/project_name.yml
# you can make as many tabs as you wish...

project_name: Tmuxinator
project_root: ~/code/rails_project
socket_name: foo # Not needed. Remove to use default socket
rvm: 1.9.2@rails_project
pre: sudo /etc/rc.d/mysqld start
tabs:
  - editor:
      layout: main-vertical
      panes:
        - vim
        - #empty, will just run plain bash
        - top
  - shell: git pull
  - database: rails db
  - server: rails s
  - logs: tail -f logs/development.log
  - console: rails c
  - capistrano:
  - server: ssh me@myhost

Then you can start a new session with:

mux project_name

I've been using it for a while and have had a good experience for the most part.

Upvotes: 35

Chris Johnsen
Chris Johnsen

Reputation: 225037

The shell errors are probably due to some problem in your startup files (or something they run).

As shellter commented, temporarily including the command set -vx early in your startup sequence is a good way to find out where the errors are occurring.
If you find the -vx output too verbose, you could try “printf debugging” (manually adding debug statements to your startup files until you can narrow down exactly which lines are causing the errors):

  • Put echo start of .bashrc and echo end of .bashrc at the start/end of your .bashrc to see if the error occurs during your .bashrc. If not, instrument your other startup files: .bash_profile/.bash_login/.profile. If the errors happen before that file, then the problem may be in /etc/profile.
  • Once you know which file is being processed when the errors occur, add more debug outputs around each “major block” or line to narrow down the responsible section/line.
  • The errors may not actually be in your startup file itself, but in a script that it runs.

Note: These debug additions need to be temporary since they will cause problems if you ever use a program that makes automated logins (e.g. rsync, SSH-based Git access, etc.) since these programs expect a “clean” connection without such debugging noise present.


There should be no need to use cd command like that in the shell-command argument given to either tmux new-session or tmux new-window.

A new window will “inherit” the current working directory when using new-session and new-window from the command line (i.e. when done through the tmux binary, instead of via a binding or at a tmux-: prompt). According to the CHANGES file, it looks like this has been the case since tmux 0.6 (at least for new-window).

This is tmux-mediated inheritance, not the parent–child inheritance that is the usual mechanism for passing along the cwd.

This script works for me with tmux 1.5:

#!/bin/bash
# var for session name (to avoid repeated occurences)
sn=xyz

# Start the session and window 0 in /etc
#   This will also be the default cwd for new windows created
#   via a binding unless overridden with default-path.
cd /etc
tmux new-session -s "$sn" -n etc -d

# Create a bunch of windows in /var/log
cd /var/log
for i in {1..6}; do
    tmux new-window -t "$sn:$i" -n "var$i"
done

# Set the default cwd for new windows (optional, otherwise defaults to session cwd)
#tmux set-option default-path /

# Select window #1 and attach to the session
tmux select-window -t "$sn:1"
tmux -2 attach-session -t "$sn"

This might also (as a side-effect) alleviate your shell startup errors since the way tmux starts a shell is different from a plain bash -i (it is more akin to bash -l, which uses your .bash_profile/.bash_login/.profile instead of (just) your .bashrc).

Upvotes: 29

Related Questions