parexec

Short description

With parexec you can execute multiple commands in parallel and have their output clearly displayed in one shell, as well as terminating all with one keystroke.

Download

parexec 0.1 source (needs C++ compiler/pthreads and ncurses library)
Tested with gcc 3.3.2 under Linux. Should be easy to adapt on any POSIX system with pthreads.

Long description

Usage: parexec NUMTHREADS
where NUMTHREADS is the number of commands you want to execute in parallel

The commands are read from stdin. Empty lines are ignored. Lines containing a single `-' instruct parexec to wait until all previous commands have finished before starting to execute further commands.

When sending a SIGINT to parexec (usually done when you hit CTRL-C) it will wait for currently running processes, but if they are done parexec will exit ignoring all the following commands.
When sending a SIGQUIT to parexec (usually done when you hit CTRL-\) or by sending SIGTERM to parexec (e.g. with kill parexec_pid) it will terminate the running processes immediately and exit.

After the start of parexec your shell window will be split up horizontally into NUMTHREADS sections. Each section containing the output of one command (which will scroll away as your command writes too much) and a status bar. The status bar may show:

Examples

To efficiently encode an audio CD to mp3 with 128kpbs on a dual CPU system you may use:
> cdda2wav -B -Owav
> for f in *.wav; do echo "lame -q 0 -b 128 $f ${f%.wav}.mp3 && rm $f"; done | parexec 2
To efficiently compress all Postscript files in a given path on a 4 CPU machine do:
> find /path/to/ps -name '*.ps' -printf 'gzip --best --verbose "%p"\n' | parexec 4


Example 1: Two CPUs doing their best encoding mp3

Technical info

You must not read nor understand this to use parexec :-)

The program parexec is written in C++ and utilizes the pthreads and ncurses lib. For each NUMTHREADS a writer thread is started that execute their command via a modified system() call. All output of the command is send through a pipe to the reader thread. This reader thread waits for output of any command to arrive in the pipes (via poll() call). The serialized output is then written on the screen via ncurses. A signal handler is installed to catch the SIGINT, SIGQUIT and SIGTERM signals. Of course synchronisation (with mutexes and semaphores) is used for critical resources, such as the reading of commands or the output with ncurses.