
Bashスクリプトで実行されているアクティブなプロセスの数を確認しようとしています。アイデアは、xプロセスを実行し続け、1つのプロセスが完了すると、次のプロセスが開始されることです。
テスト目的で次のスクリプトを設定しました。
find $HOME/Downloads -name "dummy" &
find $HOME/Downloads -name "dummy" &
find $HOME/Downloads -name "dummy" &
while true
do
pids=()
while read pid; do
echo "PID: $pid"
pids+=("$pid")
done < <(jobs -p)
jobs -p
echo "Active processes: ${#pids[@]}"
if [ ${#pids[@]} -lt 2 ]; then
break
fi
echo "Process(es) still running... ${pids[@]}"
sleep 1
done
jobs -p
ただし、プロセスが完了した後もジョブIDが返され続けるため、機能しません。
次の例では、問題について詳しく説明します。
#!/bin/bash
find $HOME/Downloads -name "dummy" &
find $HOME/Downloads -name "dummy" &
find $HOME/Downloads -name "dummy" &
while true
do
jobs -p # continues to print all 3 jobs
sleep 1
done
while
ループでアクティブなタスクを取得するには?
挨拶、
答え1
(@icarusのコメントに従って)この特別なケースでは機能しますが、最後に開始されたプロセスのPIDが含まれているwait -n
ことに注意してください。$!
したがって、これをテストすることもできます。
#!/bin/bash
find $HOME/Downloads -name "dummy" &
p1=$!
find $HOME/Downloads -name "dummy" &
p2=$!
find $HOME/Downloads -name "dummy" &
p3=$!
while true
do
if ps $p1 > /dev/null ; then
echo -n "p1 runs "
else
echo -n "p1 ended"
fi
if ps $p2 > /dev/null ; then
echo -n "p2 runs "
else
echo -n "p2 ended"
fi
if ps $p1 > /dev/null ; then
echo -n "p3 runs "
else
echo -n "p3 ended"
fi
echo ''
sleep 1
done
しかし、parallel
それもより良い選択です。
答え2
このスクリプトの問題は、その中にあるものがスタンバイシステムコールの1つを呼び出さないことです。通常、カーネルは待機を呼び出す前にプロセスのエントリを予約します。なぜなら、ここに子プロセスの戻りコードが格納されているからです。親プロセスが子プロセスの前に終了すると、子プロセスは通常、PID 1 で親プロセスをリセットします。システムが起動した後、PID 1は通常ループに入り、待機のみを呼び出してこれらのプロセスの終了値を収集するようにプログラムされます。
wait
私たちが得たシェル組み込み関数を呼び出すようにテストスクリプトを書き直します。
pids=()
find $HOME/Downloads -name "dummy" &
pids+=( $! )
find $HOME/Downloads -name "dummy" &
pids+=( $! )
find $HOME/Downloads -name "dummy" &
pids+=( $! )
echo "Initial active processes: ${#pids[@]}"
for ((i=${#pids[@]}; i>1; i--)) ; do
do
wait -n # Wait for one process to exit
echo "A process exited with RC=$?"
# Note that -n is a bash extension, not in POSIX
# if we have bash 5.1 then we can use "wait -np EX" to find which
# job has finished, the value is put in $EX. Then we can remove the
# value from the pids array.
echo "Still outstanding $(jobs -p)"
sleep 1
done
答え3
Bashスクリプトで実行されているアクティブなプロセスの数を確認しようとしています。アイデアは、xプロセスを実行し続け、1つのプロセスが完了すると、次のプロセスが開始されることです。
GNU Parallelを使用すると、次のようになります。
parallel -j3 find $HOME/Downloads -name {} ::: "name1" "name2" "name3"
(他のパラメータだけでなく)他のプログラムを実行する必要がある場合:
parallel -j3 ::: "find $HOME/Downloads -name name1" "find $HOME/Downloads -name name2" "find $HOME/Downloads -name name3"
コマンドがより複雑な場合は、bash機能を使用してください。
find1() {
find $HOME/Downloads -name "name1"
}
find2() {
find $HOME/Downloads -name "name2"
}
find3() {
find $HOME/Downloads -name "name3"
}
export -f find1 find2 find3
parallel -j3 ::: find1 find2 find3
省略すると、-j3
CPUコアごとに1つのジョブが実行されます。