Run command in new background tmux window and wait for process to finish

Viewed 6486

I'm trying to use tmux in a script, so that it runs a command that takes some time (let's say 'ping -c 5 8.8.8.8', for example) in a new hidden pane, while blocking the current script itself until the ping ends.

By "hidden pane", I mean running the command in a new pane that would be sent in background, and is still accessible by switching panes in order to monitor and/or interact with it (not necessarily ping).
(cf. EDIT)

Here is some pseudo bash code to show more clearly what I'm trying to do:

echo "Waiting for ping to finish..."
echo "Ctrl-b + p to switch pane and see running process"

tmux new-window -d 'ping -c 5 8.8.8.8' # run command in new "background" window
tmux wait-for                          # display "Done!" only when ping command has finished

echo "Done!"

I know the tmux commands here don't really have any sense like this, but this is just to illustrate.

I've looked at different solutions in order to either send a command in background, or wait until a process has finished in an other pane, but I still haven't found a way to do both correctly.

EDIT

Thanks to Nicholas Marriott for pointing out the -d option exists when creating a new window to avoid switching to it automatically. Now the only issue is to block the main script until the command ends.

I tried the following, hoping it would work, but it doesn't either (the script doesn't resume).

tmux new-window -d 'ping -c 5 8.8.8.8; tmux wait -S ping' &
tmux wait $!

Maybe there is a way by playing with processes (using fg,bg...), but I still haven't figured it out.

Similar questions:
[1] Make tmux block until programs complete
[2] Bash - executing blocking scripts in tmux
[3] How do you hide a tmux pane
[4] how to wait for first command to finish?

2 Answers

You can use wait-for but you need to give it a channel and signal that channel when your process is done, something like:

tmux neww -d 'ping blah; tmux wait -S ping'
tmux wait ping
echo done

If you think you might run the script several times in parallel, I suggest making a channel name using mktemp or similar (and removing the file when wait-for returns).

wait-for can't automatically wait for stuff like pane or windows exiting, silence in a pane, and so on, but I would like to see that implemented at some point.

The other answers are only working if you're already within a tmux session. But if you are outside of it you've to use something like this:

tmux new-session -d 'vi /etc/passwd' \; split-window -d 'vi /etc/group' \; attach

If you want to call this within a script you should check whether or not "$TMUX" is set. (Or just unset to force a nested tmux window).

#!/bin/sh
export com1="vi /etc/passwd"
export com2="vi /etc/group"
if [ -z $TMUX ]
then
    export doNewSession="new-session -d 'exit 0'"
else
    export doNewSession=""
fi
tmux $doNewSession \; split-window -d $com1 \; split-window -d $com2 \; attach;
[ -z $TMUX ] && exit 0
Related