Le 27/06/2010 06:42, David Korn a écrit :

ksh93t aleady has this feature.  If you set the variable MAXJOBS=4,
then ksh will block until a job completes if you background more than
four jobs.

You can use the SIGCHLD trap to find out which job as completed
and get the exit status.

thanks David, I thought about it, you did it... :-)
exactly what I do, I try to anticipate the needs...

some weeks ago, I wrote this one for ksh88 and bash :

# tmout isn't implemented, yet !

function intr {
        typeset rc=$?
        exec 6>&2 2> /dev/null
        for pid in ${pids}; do
                kill "${pid}"
        done
        exec 2>&6 6>&-
        exit ${rc}
}

trap intr HUP INT TERM

function loop {
        typeset maxpid=$1
        typeset pid= newpids=
        typeset -i sleep=0
        while (( npid >= maxpid )); do
                newpids= sleep=1
                for pid in ${pids}; do
                        if kill -0 "${pid}" 2> /dev/null; then
                                newpids="${newpids} ${pid}"
                        else
                                sleep=0
                                (( npid -= 1 ))
                                wait "${pid}"
                                echo "${pid}: done"
                        fi
                done
                pids=${newpids}
                (( sleep != 0 )) && sleep 1
        done
}

function parallel {
        typeset ncpu=$1 tmout=$2
        #shift 2
        typeset -i npid=0
        typeset pids=
        while read -r; do
                case ${REPLY} in
                ''|'#'*)
                        continue
                        ;;
                ncpu=*|tmout=*)
                        echo ${REPLY}
                        eval ${REPLY}
                        continue
                        ;;
                rset)
                        echo rset
                        ncpu=${_ncpu}
                        tmout=${_tmout}
                        continue
                        ;;
                wait)
                        echo wait
                        loop 1
                        continue
                        ;;
                esac
                loop "${ncpu}"
                ${REPLY} &
                (( npid += 1 ))
                pids="${pids} $!"
                echo "$!: $REPLY"
        done
        loop 1
}

_ncpu=$1
if (( ${_ncpu:-0} < 1 )); then
        case $(uname) in
        AIX)
                _ncpu=$(LC_ALL=C lsdev -c processor | grep -c Avail)
                ;;
        Darwin)
                #noht#_ncpu=$(sysctl -n hw.physicalcpu)
                _ncpu=$(sysctl -n hw.availcpu) # was logicalcpu
                ;;
        FreeBSD)
                _ncpu=$(sysctl -n hw.ncpu)
                ;;
        HP-UX)
                _ncpu=$(ioscan -fkC processor | grep -c processor)
                ;;
        CYGWIN*)
                # _ncpu=${NUMBER_OF_PROCESSORS}
                _ncpu=$(grep -c processor /proc/cpuinfo)
                ;;
        Linux)
#noht#_ncpu=$(grep 'physical id' /proc/cpuinfo | sort -u | wc -l
)
                _ncpu=$(grep -c processor /proc/cpuinfo)
                ;;
        SunOS)
                _ncpu=$(LC_ALL=C psrinfo -v | grep -c on-line)
                ;;
        esac
fi

_coef=$2
if (( ${_coef:-0} > 1 )); then
        (( _ncpu *= _coef ))
fi

_tmout=$3

if (( $# <= 3 )); then
        shift $#
fi

_time0=${SECONDS}
parallel "${_ncpu:-1}" "${_tmout:-0}" "$@"
(( _time0 -= -${SECONDS} ))
echo elapsed: ${_time0}

I've also just retrieved this old one implementation :

#!/usr/bin/sh

# based on http://web.archive.org/web/20080513235232/http://itb.biologie.hu-berlin.de/~benda/software/bash.html

# the number of currently running jobs:
PARALLELNUM=0

# a list with the PIDs of the currently running jobs:
PARALLELQUEUE=

# the number of CPUs available on the machine:
case $(uname) in
AIX) PARALLELCPUS=$(LANG=C lsdev -c processor | grep -c Available) ;;
HP-UX) PARALLELCPUS=$(ioscan -fnkC processor | grep -c processor) ;;
Linux) PARALLELCPUS=$(grep -c vendor_id /proc/cpuinfo) ;;
SunOS) PARALLELCPUS=$(psrinfo | grep -c on-line) ;;
*) PARALLELCPUS=1 ;;
esac

# this function adds the most recently started child process to the queue
# and waits until you can start another job:
function addqueue
{
  # add recent child process to the list:
  PARALLELQUEUE="$PARALLELQUEUE $!"
  let PARALLELNUM+=1
  delqueue
}

function delqueue
{
  typeset OLDPARALLELQUEUE= PREVPARALLELQUEUE= P= PID=
  # wait until one process has finished:
  while [ $PARALLELNUM -ge $PARALLELCPUS ]; do
    OLDPARALLELQUEUE="$PARALLELQUEUE"
    for PID in $OLDPARALLELQUEUE; do
      # remove process from queue if it does not exist anymore:
      if ! kill -0 $PID 2> /dev/null; then
        wait $PID 2 /dev/null
        local PREVPARALLELQUEUE="$PARALLELQUEUE"
        PARALLELQUEUE=""
        for P in $PREVPARALLELQUEUE; do
          [ "$P" != "$PID" ] && PARALLELQUEUE="$PARALLELQUEUE $P"
        done
        let PARALLELNUM-=1
      fi
    done
    sleep 1
  done
}

# wait for all the remaining processes in the queue to terminate:
function waitqueue
{
  delqueue
  # just to be sure:
  PARALLELNUM=0
  PARALLELQUEUE=
}

# This is a stupid example demonstrating the use of the waitqueue function.
# It starts 4 processes:
while read -r REPLY; do
  eval $REPLY &
  addqueue
done

# you might want to wait for the remaining processes to terminate:
waitqueue

Regards,

Cyrille Lefevre
--
mailto:cyrille.lefevre-li...@laposte.net




_______________________________________________
ast-users mailing list
ast-users@research.att.com
https://mailman.research.att.com/mailman/listinfo/ast-users

Reply via email to