파일이 새로 고쳐질 때까지 기다리지만 시간 임계값을 초과하면 종료되는 while 루프가 있는 Bash 스크립트

파일이 새로 고쳐질 때까지 기다리지만 시간 임계값을 초과하면 종료되는 while 루프가 있는 Bash 스크립트

나는 bash를 꽤 잘 알고 있으므로 이 질문이 해결하기 쉽다면 사과드립니다. 더 자세한 내용이 필요하면 알려주십시오. 아래 스크립트는 Python 워크플로를 시작하고 워크플로가 끝날 때 results.json 파일이 업데이트될 때까지 기다리는 더 큰 스크립트의 일부입니다.

나는 사용해 보았습니다.

{
    sleep 1m
    kill $$
}&

그러나 results.json 파일이 1분 이내에 새로 고쳐지면 오류가 생성됩니다.

Kill: (90015) - 해당 프로세스가 없습니다.

스크립트는 다음과 같습니다.

#! /bin/bash
export DISPLAY=:0.0

export outputfile=results.json

if [[ ! -e $outputfile ]]; then
    touch $outputfile
fi

OldTimestamp=$(date -r $outputfile)

{
    sleep 1m
    kill $$
}&

NewTimestamp=$OldTimestamp; 
while [ "$NewTimestamp" = "$OldTimestamp" ]; do 
   sleep 0.1
   NewTimestamp="$(date -r $outputfile)" 
done

답변1

그냥 없애고 싶다면Kill: (90015) - 해당 프로세스가 없습니다.오류, 프로세스를 종료하기 전에 프로세스가 아직 실행 중인지 확인할 수 있습니다.

{
    sleep 1m
    ps -p $$ > /dev/null && kill $$
}&

하지만 실제로 나는 kill을 전혀 사용하지 않습니다. while 루프의 상호 작용 수를 추적하고 적절한 반복 횟수 후에 루프를 중단할 수 있습니다.

NewTimestamp=$OldTimestamp; 
iterations=0
while [ "$NewTimestamp" = "$OldTimestamp" ] && [ $iterations -lt 600 ]; do
   sleep 0.1
   NewTimestamp="$(date -r $outputfile)"
   let iterations++
done

파일이 업데이트되지 않은 경우 0이 아닌 종료 코드로 종료하려면 다음을 추가하면 됩니다.

if [ "$NewTimestamp" = "$OldTimestamp" ] ; then 
    echo "results.json was not updated" >&2
    exit 1
fi

아니면 그런 것.

답변2

이런 방식으로 수행해야 하는 경우 results.json을 성공적으로 생성할 때 다음 오류가 발생하는 이유는 다음과 같습니다. sleep 및 Kill을 중괄호 안에 넣으면 이를 그룹 명령이라고 합니다. 중괄호 뒤에 & 기호를 넣으면 서브쉘의 배경에 배치됩니다( $$그룹 명령이 구문 분석되고 실행될 때 현재 pid로 변경되므로 여전히 작동합니다). Python 프로그램이 성공적으로 완료되면 sleep 및 kill을 실행하는 하위 프로세스가 사라지도록 알려주는 것이 없습니다. 절전 모드가 만료되면 kill이 실행되고 원본 스크립트가 더 이상 실행되지 않으므로 "해당 프로세스가 없습니다"라고 불평합니다.

작동시키는 방법은 다음과 같습니다. 성공적인 결과를 얻으면 실행하십시오 kill %1. 그러면 수면이 제거되고 사망합니다.

OldTimestamp=$(date -r $outputfile)

{
    sleep 1m
    kill $$
}&

NewTimestamp=$OldTimestamp; 
while [ "$NewTimestamp" = "$OldTimestamp" ]; do 
   sleep 0.1
   NewTimestamp="$(date -r $outputfile)" 
done

echo "I have found my $outputfile and am done"
kill %1   # Kill off the subprocess which would have killed off this script

위에서 "필요하다면..."이라고 말한 이유는 사람들이 이 글을 쓰는 일반적인 방식이 아니기 때문입니다. 일반적으로 이 명령을 사용하여 timeoutresults.json을 생성해야 하는 Python 스크립트를 실행합니다. 이렇게 하면 해당 실행 상태를 확인하고 성공하지 못한 경우 스크립트를 종료할 수 있습니다.

또한 시간 초과 기간에 도달한 후 보고서 생성기를 종료할 수 있다는 이점도 있습니다. 위의 방법은 그렇지 않습니다. 보고서 생성기가 느린 경우 최상위 스크립트가 완료된 후에도 백그라운드에서 계속 실행되는 것을 볼 수 있습니다. (시스템이 어떻게 작동하는지에 대해 몇 가지 가정을 하고 있지만 일반적으로 이 방법은 최상위 스크립트만 중지하고 스크립트 자체에서 시작된 것은 중지하지 않습니다.)

Python 스크립트가 "makereport.py"인 경우 다음을 수행할 수 있습니다.

#!/bin/bash
export outputfile=results.json
OldTimestamp=$(date +"%s" -r $outputfile)  # Use %s so we have a simple integer

timeout 1m makereport.py
if [[ $? -ne 0 ]]; then
    echo "makereport.py failed"
    exit 1
fi

# At this point you can either assume report.json was created, or you
# can check it like you did before
CurTimestamp=$(date +"%s" $outputfile)
if [[ $CurTimestamp = $OldTimestamp ]]; then
    echo "makereport.py finished successfully, but a new report was not generated"
fi
echo "Verified we have a new report.json ready to go"

관련 정보