It's licensed under these terms (it's not under any version of the GPL)
You can download it here. It'll require bashquote.
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.
$ ~/public_html/looper/looper --absolute-time --relative-time --to-stdout --dump-entire --stagger --max-concurrency 2 --maxtime 10 --verbosity 2 --ssh-command 's=$(($RANDOM%%20)); echo starting sleep $s; sleep $s; echo done with sleep $s' 'localhost dstromberg-desktop little-laptop'
using directory /tmp/looper-1250135514-2050
--> 'ssh localhost '"'"'s=$(($RANDOM%20)); echo starting sleep $s; sleep $s; echo done with sleep $s'"'"'' starting - writing to '0 - localhost' via thread
output from 0 - localhost (abs: 0.0m) (rel: 0.0m): starting sleep 12
--> 'ssh dstromberg-desktop '"'"'s=$(($RANDOM%20)); echo starting sleep $s; sleep $s; echo done with sleep $s'"'"'' starting - writing to '1 - dstromberg-desktop' via thread
output from 1 - dstromberg-desktop (abs: 0.0m) (rel: 0.0m): starting sleep 8
output from 1 - dstromberg-desktop (abs: 0.1m) (rel: 0.1m): done with sleep 8
--> 'ssh little-laptop '"'"'s=$(($RANDOM%20)); echo starting sleep $s; sleep $s; echo done with sleep $s'"'"'' starting - writing to '2 - little-laptop' via thread
Letting thread die, renaming file and closing file/pipes
<-- 'ssh dstromberg-desktop '"'"'s=$(($RANDOM%20)); echo starting sleep $s; sleep $s; echo done with sleep $s'"'"'' finished naturally - deleted outfile
Letting thread die, renaming file and closing file/pipes
<-- 'ssh localhost '"'"'s=$(($RANDOM%20)); echo starting sleep $s; sleep $s; echo done with sleep $s'"'"'' finished by timeout - written to '0 - localhost - 254'
output from 2 - little-laptop (abs: 0.2m) (rel: 0.0m): starting sleep 4
output from 2 - little-laptop (abs: 0.2m) (rel: 0.1m): done with sleep 4
waiting for threads to finish: 1 thread(s) remain(s), 1.4 seconds remains
waiting for threads to finish: 1 thread(s) remain(s), 1.3 seconds remains
waiting for threads to finish: 1 thread(s) remain(s), 1.2 seconds remains
waiting for threads to finish: 1 thread(s) remain(s), 1.1 seconds remains
waiting for threads to finish: 1 thread(s) remain(s), 1.0 seconds remains
waiting for threads to finish: 1 thread(s) remain(s), 0.9 seconds remains
waiting for threads to finish: 1 thread(s) remain(s), 0.8 seconds remains
waiting for threads to finish: 1 thread(s) remain(s), 0.7 seconds remains
waiting for threads to finish: 1 thread(s) remain(s), 0.6 seconds remains
Letting thread die, renaming file and closing file/pipes
<-- 'ssh little-laptop '"'"'s=$(($RANDOM%20)); echo starting sleep $s; sleep $s; echo done with sleep $s'"'"'' finished naturally - deleted outfile
waiting for threads to finish: 0 thread(s) remain(s), 0.5 seconds remains
true exit statuses: 2
false exit statuses: 1
/tmp/looper-1250135514-2050/0 - localhost - 254:
starting sleep 12
/tmp/looper-1250135514-2050 is not empty - please look it over
$ ~/public_html/looper/looper --to-stdout --stagger --max-concurrency 2 --maxtime 10 --ssh-command 's=$(($RANDOM%%20)); echo starting sleep $s; sleep $s; echo done with sleep $s' 'localhost dstromberg-desktop little-laptop'
using directory /tmp/looper-1250135774-2579
output from 0 - localhost: starting sleep 16
output from 1 - dstromberg-desktop: starting sleep 12
Letting thread die, renaming file and closing file/pipes
Letting thread die, renaming file and closing file/pipes
output from 2 - little-laptop: starting sleep 6
output from 2 - little-laptop: done with sleep 6
Letting thread die, renaming file and closing file/pipes
/tmp/looper-1250135774-2579/0 - localhost - 254:
starting sleep 16
(all lines shown)
/tmp/looper-1250135774-2579/1 - dstromberg-desktop - 254:
starting sleep 12
(all lines shown)
/tmp/looper-1250135774-2579 is not empty - please look it over
921
Back to Dan's tech tidbitsYou can e-mail the author with questions or comments:
![]()