#!/bin/bash # slightly modified implementation of sub-process limiter # by paxdiablo. See http://stackoverflow.com/a/1685440 # bgxupdate - update active processes in a group. # Works by transferring each process to new group # if it is still active. # in: bgxgrp - current group of processes. # out: bgxgrp - new group of processes. # out: bgxcount - number of processes in new group. bgxupdate() { bgxoldgrp=${bgxgrp} bgxgrp="" ((bgxcount = 0)) bgxjobs=" $(jobs -pr | tr '\n' ' ')" for bgxpid in ${bgxoldgrp} ; do echo "${bgxjobs}" | grep " ${bgxpid} " >/dev/null 2>&1 if [[ $? -eq 0 ]] ; then bgxgrp="${bgxgrp} ${bgxpid}" ((bgxcount = bgxcount + 1)) fi done } # bgxlimit - start a sub-process with a limit. # Loops, calling bgxupdate until there is a free # slot to run another sub-process. Then runs it # an updates the process group. # in: $1 - the limit on processes. # in: $2+ - the command to run for new process. # in: bgxgrp - the current group of processes. # out: bgxgrp - new group of processes bgxlimit() { bgxmax=$1 ; shift bgxupdate while [[ ${bgxcount} -ge ${bgxmax} ]] ; do sleep 0.1 bgxupdate done if [[ "$1" != "-" ]] ; then "$@" & bgxgrp="${bgxgrp} $!" fi # echo '[' ${bgxgrp} ']' } # bgxwait - wait for sub-processes to finish # Loops calling bgxupdate until there is something # in a process group bgxwait() { bgxupdate while [[ ${bgxcount} -ne 0 ]] ; do oldcount=${bgxcount} while [[ ${oldcount} -eq ${bgxcount} ]] ; do sleep 0.1 bgxupdate done # echo '[' ${bgxgrp} ']' done } bgxtest() { callback() { id=$1 ; shift echo start $id $(date | awk '{print $4}') "$BASHPID" sleep ${id}0 echo end $id $(date | awk '{print $4}') "$BASHPID" } # Test program, create group and run 6 sleeps with # limit of 3. bgxgrp="" for i in 1 2 3 4 5 6 ; do bgxlimit 3 callback ${i} done # Wait until all others are finished. bgxwait; }