1시간 동안 파일의 가용성을 확인하는 쉘 스크립트. 1시간 후에 파일이 없으면 "Time Out"이 표시됩니다.

1시간 동안 파일의 가용성을 확인하는 쉘 스크립트. 1시간 후에 파일이 없으면 "Time Out"이 표시됩니다.

나는 이 코드를 썼다. 하지만 문제는 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

폴링의 단점(짧은 폴링 주기에 대한 리소스 소비와 긴 폴링 주기에 대한 변경 감지 지연 간의 균형)을 방지하는 대체 접근 방식입니다. 지불해야 할 대가는 귀하가 사용할 수 없는 도구, 즉inotify 도구그리고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기본 시간 단위)) 동안 명령을 실행합니다. 시간 초과에 도달하면 timeout상태로 종료됩니다 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빈 입력을 확인하면서 읽고, 벽시계 시간인 1시간을 초과하지 않는지 확인하는 명령을 END_DATE사용하여 계산하고, 1초마다 이름의 파일이 존재하는지 확인합니다 . 현재 날짜의 경우:dateFILENAMEINTERVAL

  • 같음 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

관련 정보