Bash はジョブ待機とジョブ数の制限

Bash はジョブ待機とジョブ数の制限

重複の可能性:
4つのジョブを同時に実行しています。どうすればいいですか?

ループがコマンドを呼び出すと仮定します。

 grep -v '#' < files.m3u | sed 's/\\\\/\/\//g' | sed 's/\\/\//g' | while read line
 do
    filename=$(basename "$line")
    avconv -i "$line" "${filename%.*}.wav"
 done

avconv の後に & を配置すると、各ファイルに対して avconv が継続的に生成されます。今私は2つのことをしたいと思います:

  • 生成されるプロセス数を4つに制限したいと思います。
  • ループが完了した後、最後のループが準備されるまで待ちたいです。

ベストアンサー1

各新しいサブプロセスのPIDを覚えておくことができます($!起動後に確認)。まだ存在する子の数(パススルーなどkill -0)を定期的に確認し、数字が下がると新しい子を作成するなどの操作を実行します。最後に、ちょうどwait

同じ理由で私が書いたスクリプトは次のとおりです。

#! /bin/bash

## Tries to run commands in parallel. Commands are read from STDIN one
## per line, or from a given file specified by -f.
## Author: E. Choroba

file='-'
proc_num=$(grep -c ^processor'\b' /proc/cpuinfo)
prefix=$HOSTNAME-$USER-$$
sleep=10

children=()
names=()

if [[ $1 =~ ^--?h(elp)?$ ]] ; then
    cat <<-HELP
    Usage: ${0##*/} [-f file] [-n max-processes] [-p tmp-prefix] -s [sleep]
      Defaults:
        STDIN for file
        $proc_num for max-processes (number of processors)
        $prefix for tmp-prefix
        $sleep for sleep interval
    HELP
    exit
fi

function debug () {
    if ((DEBUG)) ; then
        echo "$@" >&2
    fi
}

function child_count () {
    debug Entering child_count "${children[@]}"
    child_count=0
    new_children=()
    for child in "${children[@]}" ; do
        debug Trying $child
        if kill -0 $child 2>/dev/null ; then
            debug ... exists
            let child_count++
            new_children+=($child)
        fi
    done

    children=("${new_children[@]}")
    echo $child_count
    debug Leaving child_count "${children[@]}"
}

while getopts 'f:n:p:s:' arg ; do
    case $arg in
        f ) file=$OPTARG ;;
        n ) proc_num=$((OPTARG)) ;;
        p ) prefix=$OPTARG;;
        s ) sleep=$OPTARG;;
        * ) echo "Warning: unknown option $arg" >&2 ;;
    esac
done

i=0
while read -r line ; do
    debug Reading $line
    name=$prefix.$i
    let i++
    names+=($name)

    while ((`child_count`>=proc_num)) ; do
        sleep $sleep
        debug Sleeping
    done

    eval $line 2>$name.e >$name.o &
    children+=($!)
    debug Running "${children[@]}"
done < <(cat $file)

debug Loop ended
wait
cat "${names[@]/%/.o}"
cat "${names[@]/%/.e}" >&2
rm "${names[@]/%/.o}" "${names[@]/%/.e}"

おすすめ記事