It's licensed under these terms (it's not under any version of the GPL)
You can download it here, preferably via svn checkout <url>.
Usage looks like:
$ ./looper
Usage: ./looper
        --directory                             The directory to use for output files
        --resolution n                          The frequency with which to check for subprocess
                                                termination
        --exit-early                            Exit immediately upon detecting a subprocess that does
                                                not yield the expected value (depends on --or-statuses
                                                and --and-statuses)
        --or-statuses                           Or the exit statuses of the subprocesses when computing exit status
        --and-statuses                          And the exit statuses of the subprocesses when computing exit
                                                status (default)
        --max-concurrency n                     Start <= n subprocesses concurrently (default: infinite)
        --maxtime n                             Terminate processes that take longer than n seconds
        --derive                                Derive a filename for output from the command run
        --numbered                              Just use numbered filenames
        --command cmd                           Add cmd to the list of subprocesses
        --commands-file filename                Read commands, one per line, from filename
        --commands cmd1 cmd2 ... cmdn           Add commands to list of subprocesses from command line
        --labeled-command label:cmd             Add cmd to list of subprocesses.  Output in label
        --labeled-commands-file filename        Read label:cmd pairs from filename.  cmd output
                                                in filename "label"
        --labeled-commands                      label1:cmd1 label2:cmd2 ... labeln:cmdn.  cmdn output in labeln
        --parameterized-command                 cmd 'parameter1 parameter2 ... parametern'
                                                EG: 'ssh %s hostname' 'master node1 node2'
                                                output would be files master, node1 and node2
        --ssh-command                           cmd 'hostname1 hostname2 ... hostnamen'
                                                EG: 'hostname' 'master node1 node2'
                                                output would be files master, node1 and node2
        --scp-command                           "srcfilename" "destfilename" "hostname1 hostname2 ... hostnamen"
                                                EG: "/etc/hosts" "/etc/hosts" "node1 node2"
                                                output filenames are always derived
        --rsync1-command                        EG: filename "hostname1 hostname2 ... hostnamen"
        --rsync-command                         EG: srcfn dstfn "hostname1 hostname2 ... hostnamen"
                                                Note that --rsync2-command is an alias for --rsync-command
        --rsync3-command                        EG: rsyncopts srcfn dstfn "hostname1 hostname2 ... hostnamen"
        --number-padding n                      Pad output file numbering to n characters for ls sorting
        --no-unlink-desired                     Do not unlink output files with desired exit statuses (depends
                                                on --or-statuses and --and-statuses)
        --stagger                               Pause for 0.25 seconds after each command start
        --dump-lines number-of-lines            (defaults to 10)
        --dump-nothing
        --dump-entire
        --to-stdout
        --verbosity levelno
        -v
        --help
        --absolute-time                         output timestamps relative to program start (only in --to-stdout)
        --relative-time                         output timestamps relative to subprogram start (only in --to-stdout)
In --or-statuses mode, the exit status of this program will be the minimum of the
subprocesses' exit statuses.
Similarly, in --and-statuses mode (the default), the exit status of this program will
be the maximum of the subprocesses' exit statuses.
The exit status of a subprocess that timed out is always 254.
Output is saved, one file per command (host), in the specified directory.
Output files are deleted if the exit status is what was desired (true or
false depending on --and-statuses or --or-statuses) by default - see
--no-unlink-desired.
Don't try to --scp-command and --ssh-command in the same ./looper unless
the --ssh-command does not depend on the --scp-command; they may be
run in parallel, so use two ./looper's.
Comparing --to-stdout and --not-to-stdout:
        --to-stdout is a little slower than --not-to-stdout.
        --to-stdout is not fully binary-safe.  --not-to-stdout is.
        --to-stdout is more informative during a run.  --not-to-stdout is quieter.
        --not-to-stdout is the default.
	
$ ./looper --ssh-command /bin/true 'stromberg.dnsalias.org zareason2 dell-inspiron via-fierro' using directory /tmp/looper-1508727916-6544 b'/tmp/looper-1508727916-6544' is empty - removing
$ ./looper --ssh-command /bin/false 'stromberg.dnsalias.org zareason2 dell-inspiron via-fierro'
using directory /tmp/looper-1508727925-6632
b'/tmp/looper-1508727925-6632/0 - stromberg.dnsalias.org - 1':
        (all lines shown)
b'/tmp/looper-1508727925-6632/1 - zareason2 - 1':
        (all lines shown)
b'/tmp/looper-1508727925-6632/2 - dell-inspiron - 1':
        (all lines shown)
b'/tmp/looper-1508727925-6632/3 - via-fierro - 1':
        (all lines shown)
b'/tmp/looper-1508727925-6632' is not empty - please look it over
$ ./looper -v -v --maxtime 8 --ssh-command 'echo sleep 5; sleep 5' stromberg.dnsalias.org --ssh-command 'echo sleep 10; sleep 10' dell-inspiron
below cmd output started 2017 Sun Oct 22 08:16:55 PM PDT
using directory /tmp/looper-1508728615-9831
--> 'ssh stromberg.dnsalias.org 'echo sleep 5; sleep 5'' starting - writing to '0 - stromberg.dnsalias.org' via redirection
--> 'ssh dell-inspiron 'echo sleep 10; sleep 10'' starting - writing to '1 - dell-inspiron' via redirection
sleep 10
sleep 5
<-- 'ssh stromberg.dnsalias.org 'echo sleep 5; sleep 5'' finished naturally - deleted outfile
<-- 'ssh dell-inspiron 'echo sleep 10; sleep 10'' finished by timeout - written to '1 - dell-inspiron - 254'
true exit statuses: 1
false exit statuses: 1
b'/tmp/looper-1508728615-9831/1 - dell-inspiron - 254':
        (all lines shown)
You can e-mail the author with questions or comments: