Скрипт оболочки для проверки доступности файла в течение 1 часа. Если по истечении часа файл отсутствует, он выведет сообщение «Time Out»

Скрипт оболочки для проверки доступности файла в течение 1 часа. Если по истечении часа файл отсутствует, он выведет сообщение «Time Out»

я написал этот код. но проблема в том, что после каждых 300 с он печатает "Time over", когда $fname present выводится из цикла. Я хочу, чтобы "time over" через 1 час, если файл не прибыл, но после 300 с он начинает печатать "time over"

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делает его действительно тихим.

Этот вид проверки иногда реализуется (например, в других вопросах и ответах на этом сайте) следующим образом:

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команды, гарантируя, что время по часам не превышено в один час, и проверяет, 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

Связанный контент