1

I am trying to write a bash script that performs the following actions:

  • open 8 tmux terminals
  • each of the terminals connects in ssh to a remote server
  • start a script X on 3 server, and when it's done
  • start another script Y in 3 different servers

The operations (especially the last two) must be executed in this precise order. I managed to create all tmux terminals, but I see that for some reasons tmux is so fast at executing commands that it does not wait the command to finish.

For example, writing just:

tmux send-keys -t 0 "ls" 

in the script not always produce the full list of files contained in the home folder.

Same happens with the two scripts on different servers, sometimes it executes Y before X.

This is my script:

######################################
# Setup tmux
######################################
tmux new-session -d -s sss
tmux new-window -t sss

for (( i = 0; i < 3; i++ )); do
  tmux split
  tmux select-layout even-vertical
done

for (( i = 0; i < 8; i=i+2 )); do
  tmux select-pane -t $i
  tmux split-window -h
done
######################################




######################################
# Ssh Connection
######################################
for (( i = 0; i < 8; i++ )); do
  tmux send-keys -t $i "$connection ${port[$i]}" C-m
done
######################################


for (( i = 0; i < 3; i++ )); do
  tmux send-keys -t $i "cd scripts" C-m
  tmux send-keys -t $i "./X.sh" C-m
done

for (( i = 3; i < 6; i++ )); do
  tmux send-keys -t $i "cd scripts" C-m
  tmux send-keys -t $i "./Y.sh ${servers_ips[${i}-3]}" C-m
done

Update

Also, how can I wait for a command to finish in the same tmux pane? Like doing something else only after a long command has been running

Thank you in advance.

1 Answer 1

3

If you really need to use tmux, and your commands are not interactive, then you can add a second command to the first command that signals somehow that the first command has finished. A simple way to do this using a built-in tmux command is wait-for with the option -L channel to lock, and -U channel to unlock. You can have many arbitrary channels. When you lock a channel, further attempts to lock will block until an unlock.

Here's an example:

tmux wait-for -L my1\; \
  send-keys 'sleep 5' Enter 'tmux wait-for -U my1' Enter\; \
  wait-for -L my1

This locks channel my1, sends the command sleep 5 to the shell, immediately followed by the tmux wait-for unlock shell command, then tries to get the lock again, so it blocks.

After 5 seconds, the sleep finishes, the shell executes the tmux unlock, and now the lock can be taken, and only then does the above tmux command return.

To get back to normal, a wait-for -U should now be done, perhaps by issuing another send-keys ... wait-for -U ... combined command as above.

3
  • Thank you! I'll try your suggestion as soon as I can. In the meanwhile, I am starting to think too that I don't really need tmux... In few words, what I need to do is send some commands to various remote servers to measure performance, wait that every machine has finished, and issue a new set of experiments. Any suggestion on the best way to do it?
    – John
    Commented Oct 13, 2018 at 19:31
  • You can probably keep it simple by issuing each command within its own ssh, rather than logging in with ssh then having to send commands over that connection. This is easier using password-less ssh, i.e. public key authentication.
    – meuh
    Commented Oct 13, 2018 at 20:08
  • You're right, I ended up doing that. I'll mark the question as solved. Thanks
    – John
    Commented Oct 19, 2018 at 13:03

You must log in to answer this question.

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