7

Background and Problem:

I have created a tmux script to open a few windows. It works great but then I wanted to place a vertically split pane on one window and resize it to 5 characters tall. I cannot get my bash script to resize the pane properly. Depending on the commands I try, it will increase or decrease the size but it acts like it's bound to some range when executing from bash.

Some Commands/Variations I've tried:

  1. tmux split-window -v -l 5 -t 0 with and without the -t 0
  2. tmux split-window -v -p 5 -t 0 with and without the -t 0
  3. tmux split-window -v followed by tmux resize-pane -D 23 -t 1 with and without the -t parameter
  4. I also tried variations of: tmux send-keys C-b '"' C-m followed by tmux send-keys C-b ':resize-pane -D 20' but that typically dumps the quote and the resize-pane command into the actual terminal buffer instead of executing the command using tmux.

Best case scenario from any number of those is the pane resizes from half of the screen (56 lines / 2 = 28 lines) to 20 lines tall (my terminal is 56 lines high and thus half - 20 = 8). Or, if I set the resize-pane command to -U for up and then set some high number, it will make the pane much taller but still will only go so large, keeping pane 0 a certain height. I just can't seem to create a pane and resize it to 5 - 10 lines tall from a bash script. I can run all of the listed commands from within tmux using C-b and : (my default prefix key) and they work exactly as expected.

My tmux bash script:

# the name of your primary tmux session
SESSION=$USER

# if the session is already running, just attach to it.
tmux has-session -t $SESSION
if [ $? -eq 0 ]; then
    echo "Session $SESSION already exists. Attaching..."
    sleep 1
    tmux -2 attach -t $SESSION
    exit 0;
fi

# create a new session, named $SESSION, and detach from it
tmux -2 new-session -d -s $SESSION

# Now populate the session with the windows you use every day

# 0 - VIM
tmux new-window  -t $SESSION:0 -k -n VIM 
tmux send-keys   -t $SESSION:0 'cd /home/aDir/myDir/' C-m 
tmux send-keys   -t $SESSION:0 'vim .' C-m 

tmux split-window -v -l 5 -t 0 <--- HERE IS WHERE I WAS SWAPPING/TRYING COMMANDS

# 1 - MySQL
tmux new-window -t $SESSION:1 -k -n MySQL 'mysql -u root -p******** mydb'

# 2 - Shell
tmux new-window -t $SESSION:2 -k -n Shell 'sudo -s'

tmux select-window -t $SESSION:0
tmux -2 attach -t $SESSION

Additionally, I tried removing everything but the initial create new window and tried splitting and resizing with no other commands being sent (i.e. adding the additional windows and opening a directory in VIM).

As an aside, on execution of this script, I get a terminal message saying "failed to connect to server: Connection refused" message but all of my windows are working and operating as expected (MySQL and VIM open perfectly and my sudo commands waits for my password). Not sure what server is trying to be connected to (MySQL is local) and failing but seemingly not affecting any functionality I seek.

1 Answer 1

14

Per the documentation, when you create a detached session (new-session -d), it defaults to a size of 80×24. If you attach with a terminal window that is actually 24 lines high (or 25, since tmux uses one for a status line), then you should find that the below-Vim pane does in fact end up with just five lines.

The problem comes when you attach to the session with a terminal window that is much taller than 24 lines. When you do this, tmux resizes the panes to fill the full terminal window. The lower pane grows past its original five lines when this happens.

One way to work around this problem is to create the detached session with an initial size that matches that of the terminal window from which you will eventually attach to the session. One semi-portable way to do this is to parse the output of stty size (some shells also provide LINES and COLUMNS parameters (especially when in interactive mode), but these parameters are not always available and reliable in shell scripts).

set -- $(stty size) # $1 = rows $2 = columns
tmux -2 new-session -d -s "$SESSION" -x "$2" -y "$(($1 - 1))" # status line uses a row

The failed to connect to server: Connection refused message comes from your tmux has-session command. It is reporting that it there is no existing server. Since you are only interested in the exit code, you can probably just send the output to /dev/null to avoid seeing it at all. You can also put the command directly into the if statement:

if tmux has-session -t "$SESSION" 2>/dev/null; then
    ⋮
fi

Incidentally, you should almost always put your parameter expansions in double quotes (to avoid word splitting and glob expansion). You only have the one parameter and its value (copied from USER) is (usually) probably safe not to quote, but it is a good habit to always quote your expansions in almost all contexts.

3
  • You, sir, are a gentleman and a scholar! Your tips worked flawlessly! I would like to understand 2>/dev/null and the $(($1-1)). I get that we are sending it to /dev/null but what is the 2 for? And I get that we are subtracting one from the rows for the status line and returning the result but why the double parenthesis? Once again, thanks for your help, I am completely new to tmux and quite new to bash scripting. Also, I would upvote you but I don't have the requisite reputation yet.
    – Eric H
    Nov 9, 2011 at 14:53
  • 3
    @EricH: Digits before a redirection operator tell it which file descriptor to redirect; so 2> tells the shell to redirect file descriptor 2 (which is called “stderr” and is where tmux sends its “failed to connect” and “session not found” messages). The shells mostly do string processing, so you need a way to tell them to do math instead; the $((…)) syntax is for Arithmetic Expansion (i.e. inline math). Nov 9, 2011 at 21:01
  • Awesome! Thanks for the explanation and once again for the solutions.
    – Eric H
    Nov 14, 2011 at 14:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .