2

I start GNU Parallel with --tmux which will start a tmux window per job.

I would like to join all windows as panes with the size nicely distributed between them (like tiled view: C-b M-5).

I tried doing:

seq 15 | parallel tmux -S /tmp/tmsF8j3K joinp -s {} -t 1

But it does not distribute the height evenly resulting in:

create pane failed: pane too small

Is there a way to tell a window to distribute height evenly when joinping or a way to join all windows as panes and then tile them? Maybe something using select-layout tiled?

Edit

I am using this as the test program:

seq 1000 | parallel --jobs 9 --tmux sleep

The goal is to have the 9 running jobs shown in a nice 3x3 window when attaching to tmux. When one job dies it should be replaced by the next job.

I have tried:

while [ -e "$SERVER" ] ; do
    top=$(tmux -S $SERVER new-window -P -n all)
    tmux -S $SERVER list-panes -a | grep -v "^$top" | cut -d':' -f1-2 |
        while read p ; do
          tmux -S $SERVER joinp -s $p -t $top
          tmux -S $SERVER select-layout tiled
        done
    tmux -S $SERVER kill-pane -t $top
    tmux -S $SERVER select-layout tiled
    sleep 1
done

But it still gives:

can't find pane X

And it does not keep all windows as panes in the first window when attaching.

Ole Tange
  • 35,514

2 Answers2

1

Your select-layout suggestion is along the right track, but needs to be invoked after each new pane is created. All panes are immediately reorganised, so (in my test -- a 95x58 terminal) there's enough room for the next split.

To avoid the can't join a pane to its own window message, it helps to create an additional window, then move all the existing windows into that, and terminate the extra pane at the end. parallel is not the right tool for this - you'd be better off querying the running windows, and moving each one, in a loop:

top=$(tmux -S $SERVER new-window -P -n all)
tmux -S $SERVER list-panes -a | grep -v "^$top" | grep -o  "%[0-9]\+\>" | 
  while read p ; do 
    tmux -S $SERVER joinp -s $p -t $top
    tmux -S $SERVER select-layout tiled
  done
tmux -S $SERVER kill-pane -t $top
tmux -S $SERVER select-layout tiled 

Alternatively, you could make each new pane 1 line high, with joinp -l 1. Depending on the size of your terminal, this might be enough to only need the one select-layout at the end.

However, parallel doesn't keep track of existing tmux windows/panes, and simply starts each job in a new window. The old one may disappear, depending on the remain-on-exit setting. So after a while, the original window (which showed each job in a pane) will contain no running jobs, and all the new jobs will be in their own windows again. You will have to rerun the script to move all the windows (and any old panes) into a single window again.

JigglyNaga
  • 7,886
  • I cannot make your solution work on: seq 1000 | parallel --tmux sleep – Ole Tange Aug 17 '16 at 22:02
  • @OleTange seq ... | parallel ... sleep will mean parallel jobs sleep 1, sleep 2, sleep 3 etc., so the first few will probably exit before you run all the joinp. And with 1000, you may still reach pane too small. – JigglyNaga Aug 18 '16 at 06:29
  • It will only run one per CPU in parallel. How can I make the panes show the currently running jobs? So a pane is replace with the next job when one pane finishes. – Ole Tange Aug 18 '16 at 07:10
1

Instead of running a separate command, possibly in a loop, to move the panes after they've been created, you could extend the job command so that it moves its own pane at startup:

seq 1000 |
 parallel --jobs 9 --tmux tmux joinp -t :0 \; \
 tmux select-layout -t :0 tiled \; \
 sleep

This will show the additional tmux commands (and then their output, arranging in: tiled) in each pane. To avoid that, you could write a wrapper script, eg.

#!/bin/sh

# move into the pane set
tmux joinp -t :0
tmux select-layout -t :0 tiled >/dev/null

# start the real task
sleep "$@"

And then run

seq 1000 | parallel --tmux --jobs 9 /path/to/wrapper.sh
JigglyNaga
  • 7,886