このコードを書いています。しかし、問題は、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が含まれている場合、この方法は機能しません。
そのため、上記のコードでは使用せずに存在するかどうかを2回-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