이 코드를 작성했습니다. 그러나 문제는 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
기본 시간 단위)) 동안 명령을 실행합니다. 시간 초과에 도달하면 timeout
status 로 종료되고 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
빈 입력을 확인하는 동안 읽고, 명령을 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