How to create a tmux session with two windows with specific name and run specific scripts in each window?

I want to create a session with the name - generalAnd I want to have two windows in it -

  1. win1
  2. win2

And I need to run script1 in win1 and script2 in win2

Currently I have written the script like -

SESSION="general"
echo $SESSION
tmux attach-session -d -t $SESSION || tmux new-session -s $SESSION -n win1 -c /my/path/ ./script1.sh
tmux new-window -n win2 tel_csr

With this script, I am able to create a session with the name general. But only one window is coming up with the name win1 and running the script - script1.sh.

The second statement is not kicking in. What is wrong with the above script.

Note: script1.sh triggers a server program, so it doesn't return I guess.

1 Answer

Analysis

What is wrong with the above script?

Run sleep 5; echo done. Are you surprised echo works only after sleep exits? The shell runs the two commands in sequence, not in parallel.

Now run less /etc/fstab; echo done. You will see done only after you exit from less (with Q).

tmux new-session; tmux new-window is no different.

In your script tmux attach-session or tmux new-session attaches to a session. One or the other tmux command becomes a tmux client and it runs until you detach. The script waits for this tmux to exit before executing the next command. You cannot see the effect of tmux new-window before you detach because this command has not been executed yet.

If you detach then you will allow the script to continue. Do it without destroying the session, attach again and you will see the new window.


Solution

Attach after you set everything up.

Set everything up using commands that don't attach to the session (e.g. tmux new-session -d). If you eventually want to attach then tmux attach-session should be the last command in the script (unless you deliberately want to do something extra after you detach). This example (run it outside of tmux) will attach to a session where an additional window already exists:

tmux new-session -d
tmux new-window
tmux attach-session

In general you want to name and target the exact session, window etc. And you want some logic to handle a situation when the named session exists etc.


Alternative

An alternative approach is to invoke some "maintenance" commands from a subshell running asynchronously and attach early from the main shell, with the "maintenance" part still running in parallel. Example (run it outside of tmux):

(tmux new-session -d; sleep 5; tmux new-window) & sleep 2; tmux attach-session

sleep 5 simulates commands that take time. With the previous solution you would have to wait until all of them finish. Here you don't have to wait that long, you attach before tmux new-window runs. This way you can actually see a new window popping out in tmux.

This method has serious disadvantages though:

  • You can interact with tmux even before everything is set up. By changing the current pane (or window etc.) or destroying some pane (or window etc.) you can cause the "maintenance" commands to target the wrong pane (or window etc.) or to fail; unless they are carefully crafted to handle such situation.
  • Race conditions. In the above example sleep 2 delays attach-session so it hopefully runs after new-session. Even with sleep 2 (or even with sleep 2000) there is no guarantee new-session runs first, only high probability. There is tmux wait-for to handle such situations (but using it right can be tricky; see "Dealing with race conditions" in this another answer of mine).
5

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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

You Might Also Like