Search code examples
bashtmux

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


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?


Solution

  • 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.