나는 이 코드를 썼다. 하지만 문제는 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
디렉토리 ) 에 대한 변경을 기다립니다 . 우리가 지켜보고 있는 사건입니다. 정말 꽤 됩니다.$fname
create
-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초마다 이름의 파일이 존재하는지 확인합니다 . 현재 날짜의 경우:date
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