Tmux create window failed: index in use: 0 - shell

I have a script like so that I'd like to create a tmux session with windows with various server connections:
tmux new-session -d -s server-connections
tmux new-window -t server-connections:0 -n 't-u14-nickpl' 'ssh T-U14-NickPL'
tmux new-window -t server-connections:1 -n 't-u12-dev1' 'ssh T-U12-Dev1'
tmux attach -t server-connections
When I run that file, I get create window failed: index in use: 0. At first I thought maybe the script was executing so quickly it attached to the window at index 0 faster than the command could be run, so I introduced a sleep just to be sure.
tmux new-session -d -s server-connections
tmux new-window -t server-connections:0 -n 't-u14-nickpl' 'ssh T-U14-NickPL'
tmux new-window -t server-connections:1 -n 't-u12-dev1' 'ssh T-U12-Dev1'
sleep 4
tmux attach -t server-connections
But still I get create window failed: index in use: 0 and then the sleep would happen.
What do I need to change to bind to that window at index 0?

chepner's answer is correct, but you can also avoid specifying window numbers by appending windows with the -a option:
tmux new-window -a -t server-connections -n 't-u14-nickpl' 'ssh T-U14-NickPL'
tmux new-window -a -t server-connections -n 't-u12-dev1' 'ssh T-U12-Dev1'

A new session always has an initial window, so window index 0 is already taken as soon as new-session completes. Instead of an explicit new-window command, just specify the information with the new-session command itself.
tmux new-session -d -s server-connections -n 't-u14-nickpl' 'ssh T-U14-NickPL'
tmux new-window -t server-connections:1 -n 't-u12-dev1' 'ssh T-U12-Dev1'
tmux attach -t server-connections

Related

Tmux open 4 panes and set each of those panes to a specific directory

Is there a way to create a script to have tmux open with 4 panes and each of those panes opens into a specific directory?
Both tmux new-window and tmux split-window come with a -c option that can specify a start-directory. So you can do a new-window followed by three consecutive split-windows to get your four pane window. You can also provide an additional tmux select-layout command to setup the wanted layout of those four panes.
example
tmux new-window -c ~
tmux split-window -h -c /tmp
tmux split-window -v -c /
tmux select-pane -t 1
tmux split-window -v -c /home
tmux select-pane -t 1

How do I create a tmux session with multiple windows already opened?

I've tried just about everything I can find online, but nothing is working. I have tried the following methods, and the usual result is a new tmux session with only one window.
Simply in .bashrc.
.bashrc
tmx () {
tmux new-session -A -s SessionName
tmux new-window -n Win1
tmux new-window -n Win2
tmux new-window -n Win3
tmux new-window -n Win4
tmux attach-session -d -t SessionName # with and without this line
tmux select-window -t Win1 # with and without this line
}
And again only in .bashrc.
.bashrc
tmx () {
tmux new-session -A -s SessionName ||
tmux \
neww -s Win1 \; \
neww -s Win2 \; \
neww -s Win3 \; \
neww -s Win4 \; \
selectw -t Win1
}
This following attempt would be my preferred method, as it makes the most sense to me.
Calling tmux without the first line makes all the other lines cause a "Session not found" error to occur. This makes no sense, since aren't we supposed to call tmux in order to reach this stuff anyway? My original plan was to make a session and have this file automatically set up my tmux.
.tmux.conf
new-session -A -s SessionName
new-window -t Win1
new-window -t Win2
new-window -t Win3
new-window -t Win4
attach-session -d -t SessionName # with and without this line
select-window -t Win1 # with and without this line
This method, whether using an alias or making a function, usually results in "failed to connect to server". But when fiddling with it enough for that not to happen, it produces the same result as the rest.
.bashrc
alias tmx='tmux source-file "~/.tmux/mysession"'
.tmux/mysession
new-session -A -s SessionName
new-window -t Win1
new-window -t Win2
new-window -t Win3
new-window -t Win4
attach-session -d -t SessionName # with and without this line
select-window -t Win1 # with and without this line
What am I doing wrong?
You need to create the session in detached mode (-d); otherwise, your script blocks until you detach from the new session. Likewise, your script will block after tmux attach-session until you detach, so you need to select the correct window first. Note that you can -d with new-window to avoid making each new window the current window, eliminating the need to call select-window at all.
Yes, -d gets used a lot.
tmx () {
# Use -d to allow the rest of the function to run
tmux new-session -d -s SessionName
tmux new-window -n Win1
# -d to prevent current window from changing
tmux new-window -d -n Win2
tmux new-window -d -n Win3
tmux new-window -d -n Win4
# -d to detach any other client (which there shouldn't be,
# since you just created the session).
tmux attach-session -d -t SessionName
}

Tmux not responding to commands in shell script

I have a simple bash script that creates a new tmux session and does some layout:
#!/usr/local/bin/bash
tmux new-session -s $1
tmux split-window -h -p 50 -t 1
tmux new-window
tmux split-window -h -p 50 -t 1
The contents are in an executable script. When i execute the script with the name of the session as the argument, I get a new tmux session but there is only one un-split window, instead of the two [split] windows that I am telling it to create. If I run the scripts one by one on the shell prompt then I do get the desired outcome. So why is this not working in the script?
The problem is that first command starts tmux and wait for it to finish before continue. What you need to do is write custom tmux.conf file and add pass it through -f filename.conf with first command.
the other possible way is use tmux -d
#!/bin/bash
tmux new-session -d -s $1
tmux split-window -h -p 50 -t $1
tmux new-window -t $1
tmux split-window -h -p 50 -t $1
tmux attach -t $1

Bash script for tmux managing

I'd like to start tmux from terminal, split it window and execute in the splits some commands. Furthermore, I'd like to did with bash script, that I start from terminal. Now, I've been able to start tmux only.
#!/bin/sh
tmux
# How to split tmux window there, and start commands in splits?
There is a script started tmux, splitted for to panes and started ls in the left pane and top in the right one.
#!/bin/sh
tmux new-session -d -s main ;
tmux split-window -h ;
tmux select-pane -L
tmux send-keys -t main 'ls' C-m
tmux select-pane -R
tmux send-keys -t main 'top' C-m
tmux attach-session -d -t main

Bash scripts with tmux to launch a 4-paned window

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?
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
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.
Place the following into the command prompt [all as one line], it will open 4 tmux panels automatically (I know this wasn't the question, but this looks somewhat easier than what I saw posted):
tmux new-session \; \split-window -v \; \split-window -h \; \select-pane -t 0 \; \split-window -h
Now you can take that command and use it with whatever scripting language you like [you need to double the escape characters {backslash characters} if using perl...and probably other languages].
This runs the subsequent command in the newer tmux panel, reverting to the first and splitting it at the end.
You are running the command and then entering the interactive shell; the command run from the script, not being in an interactive shell, doesn't get recorded in the history. You really want a way to stuff (that's a technical term :) once upon a time it was TIOCSTI for "terminal ioctl(): stuff input") input for the shell into the window.
With tmux, it looks like you use buffers for this. Something along the lines of (untested)
#! /bin/bash
cd ~/projects/foo
rvm use ree
if [[ $# != 0 ]]; then
tmux set-buffer "$(printf '%s\n' "$*")" \; paste-buffer -d
fi
exec ${SHELL:-/bin/sh}
You can create a bash script like this.
#!/bin/sh
tmux new-session -d -s mysession
tmux send-keys -t mysession "cd ~" Enter
tmux split-window -h -t mysession
tmux send-keys -t mysession "watch -n 1 df -H" Enter
tmux split-window -v -p 50 -t mysession
tmux send-keys -t mysession "htop" Enter
tmux select-pane -t mysession:0.0
tmux split-window -v -p 50 -t mysession
tmux send-keys -t mysession "cd ~" Enter
tmux select-pane -t mysession:0.0
# Attach to session
tmux attach -t mysession
You can change commands inside "" in each send-keys command as per your preference.

Resources