特定の条件が満たされたら、スクリプトで「tail -f」を停止して終了するにはどうすればよいですか?

特定の条件が満たされたら、スクリプトで「tail -f」を停止して終了するにはどうすればよいですか?

私はスーパーコンピュータでタスクを管理するためのスクリプトを書こうとしています。詳細は重要ではありませんが、重要なのは、スクリプトがファイルが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$!teetailtee$SIGPIPE

解決策は以下の答えにあります。https://stackoverflow.com/a/8048493/5099168

私のスクリプトに実装されている関連行は、次の形式を取ります。

tail -f -n 100000 $outf $errf > >(tee $logf) & 
tail_pid=$!

おすすめ記事