大量のシミュレーションデータを生成するためにジョブを継続的に実行するためのbashスクリプトを書いています。bashプログラミング、バックグラウンドプロセス、PIDとジョブが終了するのを待つ
本質的にスクリプトが実行されると、32個以下の同時バックグラウンドジョブを実行できるという制約の下で、バックグラウンドプロセスを継続的に起動してデータを生成する必要があります。これは、プロセスが使用可能なすべてのRAMを盛り上げて、サーバーを停止させないようにするために必要です。
私の考えは、バックグラウンドでbash関数を起動し、それらのジョブのPIDを保存することでした。その後、32個のジョブが起動した後、ジョブのすべてのPIDが実行を終了するまで、waitコマンドをwait
に使用します。
私はwait
が、waitコマンドが実行されたときにプロセスのpidが存在する限り(ここではシミュレーションを実行するのに6時間かかります)、waitコマンドがプロセスは終了する。
これはプロセスをポーリングするだけでなく、特定のPIDが存在するかどうかをチェックするよりも、PIDがリサイクルされ、同じPIDで終了した後に別のプロセスが開始された可能性があります。
しかし、wait
メソッドを使用すると、プロセスが実行された順序で終了しなければ、もはや存在しないPIDのためにwait
が呼び出されるという欠点があります(不運な場合はランダムチャンスです)。新しいプロセスが以前に記録したものと同じPIDを再使用しない限り、またあるジョブが他のジョブよりもかなり長い時間がかかった場合(偶然にも)、余裕がある間に1つのジョブが終了するのを待つその最後のPIDを終了するために、我々は待っているので、実行することはできません別の31のジョブ、システム...
これはおそらく
...ので、私はいくつかのコードを追加してみましょう可視化するビット困難になってきています10私はうまくいけば、コード内のコメントや上記のコードとコメントの組み合わせは、私がしようとしていますどのようなことを明確にする必要があり、この「アルゴリズム」
c=0 # count total number of jobs launched (will not really use this here)
PIDS=() # keep any array of PIDs
# maximum number of simultaneous jobs and counter
BATCH_SIZE=32
BATCH_COUNT=0
# just start looping
while true
# edit: forgot to add this initially
# just check to see if a job has been run using file existance
if [ ! -e "$FILE_NAME_1" ]
then
# obvious
if [ "$BATCH_COUNT" -lt "$BATCH_SIZE" ]
then
((BATCH_COUNT += 1))
# this is used elsewhere to keep track of whether a job has been executed (the file existence is a flag)
touch "$FILE_NAME_1"
# call background job, parallel_job_run is a bash function
parallel_job_run $has_some_arguments_but_not_relevent
# get PID
PID=$!
echo "[ JOB ] : Launched job as PID=$PID"
PIDS+=($PID)
# count total number of jobs
((c=c+1))
fi
else
# increment file name to use as that file already exists
# the "files" are for input/output
# the details are not particularly important
fi
true # prevent exit
# the following is a problem
do
if ((BATCH_COUNT < BATCH_SIZE))
then
continue
else
# collect launched jobs
# this does not collect jobs in the order that they finish
# it will first wait for the first PID in the array to exit
# however this job may be the last to finish, in which case
# wait will be called with other array values with PID's which
# have already exited, and hence it is undefined behaviour
# as to whether we wait for a PID which doesn't exist (no problem)
# or a new process may have started which re-uses our PID
# and therefore we are waiting for someone else's process
# to finish which is nothing to do with our own jobs!
# we could be waiting for the PID of someone else's tty login
# for example!
for pid in "${PIDS[@]}"
do
wait $pid || echo "failed job PID=$pid"
((BATCH_COUNT -= 1))
done
fi
done
の基盤としてwhileループを使用しています。
私の他の考え方は、最後のforループを、それぞれのPIDが存在するかどうかを絶えず調べる別のループに置き換えることでした。 (Polling。)これはCPUのホギングを防ぐためにsleep 1
と組み合わせることができます。しかし、この問題は以前と同じように、私たちのプロセスはPIDを解放して終了し、PIDを取得する別のプロセスが実行されることがあります。この方法の利点は、前のプロセスが終了したときに新しいプロセスが開始される前に約1秒以上待つことがないことです。
私はここにいる問題をどのように進めるべきか、誰にでも助言できますか?
私は今日この問題を絶えず更新しています。たとえば、見つかったら新しい情報を追加し、それを明確にするために書式/書式を設定します。