특정 조건이 충족되면 스크립트에서 "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=$!

관련 정보