쉘 스크립트는 1시간 동안 파일의 가용성을 확인하고, 1시간 후에 파일이 존재하지 않으면 "timeout"을 표시합니다.

쉘 스크립트는 1시간 동안 파일의 가용성을 확인하고, 1시간 후에 파일이 존재하지 않으면 "timeout"을 표시합니다.

이 코드를 작성했습니다. 그러나 문제는 300초마다 $fname이 루프에서 종료될 때 "Time over"가 인쇄된다는 것입니다. 파일이 도착하지 않으면 1시간 후에 "시간 초과"를 원하지만 300초 후에 "시간 초과" 인쇄가 시작됩니다.

echo "enter file name"

read fname

START=`date +%s`
while [ $(( $(date +%s) - 3600 )) -lt $START ]; do
  if [ -e $fname ]
  then
    echo "$fname present"
    break
    sleep 300
  else
    echo "Time Over"
  fi
done

답변1

내 생각엔 당신이 꽤 가깝다고 생각하지만 스크립트의 일부 측면은 지나치게 복잡해 보입니다.

다음 while루프를 시도해 볼 수 있습니다.

#!/bin/sh

timeout=3600
granularity=300
elapsed=0

echo "Please enter the filename"
read -r file

while [ "$elapsed" -lt "$timeout" ]
do
    if [ -f "$file" ]
    then
        break
    fi

    sleep "$granularity"
    elapsed=$((elapsed+granularity))
done

# Was the loop broken because the file appeared, or did it time out?
if [ -f "$file" ]
then
    echo "$file has appeared"
else
    echo "Time over"
fi

이 값을 초과할 $granularity때까지 매초마다 파일이 존재하는지 확인합니다 . $timeout파일이 이미 존재하는 경우 스크립트는 루프에서 빠져 나옵니다.

접근 방식의 문제는 "시간 초과" 출력이 else정기적으로 확인되는 분기에 있다는 것입니다.루프를 반복할 때마다파일을 찾을 수 없는 경우. 대신 확인해 보시는 걸 추천드려요루프 이후테스트 변수(스크립트의 출력 date)가 범위를 벗어나거나(루프 시간 초과를 나타냄) 파일이 존재하는 경우 "시간 초과" 메시지를 출력할지 여부를 결정합니다.

답변2

폴링의 단점(짧은 폴링 주기의 리소스 소비와 긴 폴링 주기의 변경 감지 대기 시간 간의 균형)을 방지하는 대체 접근 방식입니다. 지불된 대가는 귀하가 액세스할 수 없는 도구에 의존한다는 것입니다.이노티파이 도구그리고timeout(후자는 다음에서 유래한다.GNU Coreutils).

"가용성 확인"은 파일이 생성되기를 기다리고 있음을 의미한다고 가정합니다 fname(해당 이름은 변수에 있음).

timeout 3600 sh -c '
    if [ -e "$1" ]; then
        printf "%s is present already\n" "$1"
        exit
    fi
    while inotifywait -qq -e create dir; do
    if [ -e "$1" ]; then
        printf "%s present\n" "$1"
        exit
    fi
done' mysh "$fname"
[ "$?" -eq 124 ] && echo "Time over"

timeout지정된 기간(여기서는 3600초( s기본 시간 단위)) 동안 명령을 실행합니다. 시간 초과에 도달하면 timeoutstatus 로 종료되고 124, 그렇지 않으면 실행 중인 명령의 상태로 종료됩니다.

inotifywait디렉토리( dir디렉토리가 생성될 것으로 예상되는 디렉토리)에 대한 변경을 기다리는 것은 정말 조용합니다.$fnamecreate-qq

이 확인은 때때로 구현됩니다(예: 이 사이트의 다른 Q&A에서).

inotifywait -m ... --format "%f" | while read -r file; do ...

여기서 -m(감시 모드)는 inotifywait첫 번째 일치하는 이벤트 후에 종료되는 것을 방지하고 파이프의 오른쪽은 이벤트와 관련된 파일의 이름을 받습니다. 불행하게도 <newline>파일 이름에 s가 포함되어 있으면 이 방법이 작동하지 않습니다.

그렇기 때문에 위에 표시된 코드에서는 사용하지 않고 존재 여부를 두 번 -m확인합니다 . $fname이 접근 방식은 약간 취약합니다.$fname 가능한[ -e "$1" ]첫 번째 실행과 첫 번째 실행 사이 inotifywait(및 실행 사이) 에 생성됩니다 inotifywait. 각 실행이 inotifywait자체 감시를 설정 하므로 감시 디렉터리에 많은 수의 파일이 생성되는 경우에도 적합하지 않습니다 .

답변3

다음 스크립트는 FILENAME빈 입력을 확인하는 동안 읽고, 명령을 END_DATE사용하여 계산을 수행하여 date벽시계 시간이 1시간 이상 경과되지 않았는지 확인하고, FILENAME이라는 파일이 존재하는지 매초 확인합니다 INTERVAL. 현재 날짜인 경우:

  • 동일한 END_DATE: 마지막 파일 존재 확인이 발생하고 스크립트는 while 루프를 즉시 종료합니다(300초를 기다릴 필요 없음).
  • 초과하다 END_DATE: 파일이 존재하는지 확인하지 않고 while 루프가 중단됩니다.
#!/usr/bin/env bash

echo -n "Enter file name to monitor: "

read FILENAME

if [ -z "${FILENAME}" ]
then
    echo -e "\nError: Filename is empty!\nExiting..."
    exit 1
fi

END_DATE=$(date --date='next hour' '+%s')
INTERVAL=300

FOUND="false"
while :
do
    CURRENT_DATE="$(date '+%s')"
    if [ "${CURRENT_DATE}" -gt "${END_DATE}" ]
    then
        break
    elif [ "${CURRENT_DATE}" -eq "${END_DATE}" ]
    then
        INTERVAL='0.1'   # Allow for one last check
    fi

    if [ -e "${FILENAME}" ]
    then
        FOUND="true"
        break
    fi
    sleep "${INTERVAL}"
done

if [ "${FOUND}" == "true" ]
then
    echo "${FILENAME} is present"
else
    echo "Time is Over"
fi

관련 정보