私はスーパーコンピュータでタスクを管理するためのスクリプトを書こうとしています。詳細は重要ではありませんが、重要なのは、スクリプトがファイルがtail -f
表示されたらそのファイルを実行することです。これでこれは永久に実行されますが、ジョブが完了したことが検出された場合は完全に停止してスクリプトを終了したいと思います。
残念ながら私は立ち往生しています。私はいくつかの解決策を試しましたが、それらのどれもシャットダウンスクリプトを持っておらず、ジョブの終了を検出した後も実行され続けます。以下のバージョンが最も論理的なように見えますが、このバージョンも永遠に実行されます。
この問題をどのように解決するのですか?私はbashに精通していますが、まだ高度なレベルではありません。
#!/bin/bash
# get the path to the job script, print help if not passed
jobscr="$1"
[[ -z "$jobscr" ]] && echo "Usage: submit-and-follow [script to submit]" && exit -2
# submit job via SLURM (the job secluder), and get the
# job ID (4-5-digit number) from it's output, exit if failed
jobmsg=$(sbatch "$jobscr")
ret=$?
echo "$jobmsg"
if [ ! $ret -eq 0 ]; then exit $ret; fi
jobid=$(echo "$jobmsg" | cut -d " " -f 4)
# get the stdout and stderr file the job is using, we will log them in another
# file while we `tail -f` them (this is neccessary due to a file corruption
# bug in the supercomputer, just assume it makes sense)
outf="$(scontrol show job $jobid | awk -F= '/StdOut=/{print $2}')"
errf="$(scontrol show job $jobid | awk -F= '/StdErr=/{print $2}')"
logf="${outf}.bkp"
# wait for job to start
echo "### Waiting for job $jobid to start..."
until [ -f "$outf" ]; do sleep 5; done
# ~~~~ HERE COMES THE PART IN QUESTION ~~~~ #
# Once it started, start printing the content of stdout and stderr
# and copy them into the log file
echo "### Job $jobid started, stdout and stderr:"
tail -f -n 100000 $outf $errf | tee $logf &
tail_pid=$! # catch the pid of the child process
# watch for job end (the job id disappears from the queue; consider this
# detection working), and kill the tail process
while : ; do
sleep 5
if [[ -z "$(squeue | grep $jobid)" ]]; then
echo "### Job $jobid finished!"
kill -2 $tail_pid
break
fi
done
tail
また、基本プロセスで別のバージョンを試しましたが、while
ループが子プロセスで実行され、ジョブが終了すると、基本プロセスは終了しますが、機能しませんでした。それにもかかわらず、スクリプトは決して終了しません。
答え1
@Paul_Pedantのコメントのおかげで問題を見つけることができました。元のスクリプトでパイピングをしたときにtail
埋め込まれたPIDがなく、死んでいました。後者はそれを得ましたが、それを防ぐのに十分ではないようです。tee
$!
tee
tail
tee
$SIGPIPE
解決策は以下の答えにあります。https://stackoverflow.com/a/8048493/5099168
私のスクリプトに実装されている関連行は、次の形式を取ります。
tail -f -n 100000 $outf $errf > >(tee $logf) &
tail_pid=$!