shell腳本檢查檔案的可用性1小時,一小時後如果檔案不存在,它將回顯“超時”

shell腳本檢查檔案的可用性1小時,一小時後如果檔案不存在,它將回顯“超時”

我寫了這段程式碼。但問題是每 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)超出了邊界(表示循環逾時),或者(可能更好)如果檔案存在,則決定是否輸出「Time over」訊息。

答案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

這種檢查有時會被實現(例如在本網站的其他問答中):

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

相關內容