このコードを書きました。しかし、問題は、$fname present がループから抜け出すと、300 秒ごとに「Time over」と表示されることです。ファイルが到着しない場合は 1 時間後に「time over」と表示したいのですが、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 コアユーティリティ)。
「可用性を確認する」という意味が、ファイル(名前が変数内にある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 ...
where -m
(モニター モード) は、inotifywait
最初に一致するイベントの後に終了しないようにし、パイプの右側にはイベントの対象となるファイルの名前が渡されます。残念ながら、ファイル名に<newline>
s が含まれている場合、この方法は機能しません。
そのため、上記のコードでは を使用せず、-m
の存在を$fname
2回確認しています。このアプローチは、$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