ich habe diesen Code geschrieben. aber das Problem ist, dass er alle 300 Sekunden „Time over“ ausgibt, wenn $fname present aus der Schleife herausgeholt wird. Ich möchte „time over“ nach 1 Stunde, wenn die Datei nicht angekommen ist, aber nach 300 Sekunden beginnt er, „time over“ auszugeben
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
Antwort1
Ich denke, Sie sind schon nah dran, aber einige Aspekte Ihres Skripts sehen zu kompliziert aus.
Sie könnten die folgende while
Schleife versuchen:
#!/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
Dadurch wird jede Sekunde geprüft $granularity
, ob die Datei vorhanden ist, bis der $timeout
Wert überschritten wird. Wenn die Datei vorhanden ist, bricht das Skript aus der Schleife ab.
Das Problem bei Ihrem Ansatz war, dass die Ausgabe "Zeit über" im else
Zweig Ihrer regelmäßigen Überprüfung liegt und daher auftrittjedes Mal, wenn die Schleife wiederholt wirdwenn die Datei nicht gefunden wurde. Stattdessen würde ich vorschlagen, zu überprüfennach der Schleifewenn Ihre Testvariable (die Ausgabe in Ihrem Skript date
) die Grenze überschritten hat (zeigt an, dass die Schleife abgelaufen ist) oder alternativ (vielleicht sogar besser), wenn die Datei vorhanden ist, um zu entscheiden, ob die Meldung „Zeit abgelaufen“ ausgegeben werden soll oder nicht.
Antwort2
Ein alternativer Ansatz, der die Nachteile des Pollings vermeidet (den Kompromiss zwischen Ressourcenverbrauch bei kurzen Polling-Zyklen und der Verzögerung bei der Änderungserkennung bei langen Polling-Zyklen). Der Preis dafür ist, dass er auf Tools angewiesen ist, die Ihnen möglicherweise nicht zur Verfügung stehen, nämlichinotify-toolsUndtimeout
(Letzteres ausGNU Coreutils).
Angenommen, die Bedeutung von „Überprüfen der Verfügbarkeit“ besteht darin, dass Sie auf die fname
Erstellung einer Datei (deren Name in der Variablen steht) warten:
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
führt einen Befehl für die angegebene Dauer aus, die hier 3600
Sekunden beträgt ( s
ist die Standardzeiteinheit). Wenn das Timeout erreicht ist, timeout
wird mit dem Status beendet 124
; andernfalls wird es mit dem Status des ausgeführten Befehls beendet.
inotifywait
wartet auf Änderungen am dir
Verzeichnis (das, $fname
in dem es erstellt werden soll); create
ist das Ereignis, auf das wir achten; -qq
macht es wirklich ruhig.
Diese Art der Prüfung wird manchmal (z. B. in anderen Fragen und Antworten auf dieser Site) wie folgt implementiert:
inotifywait -m ... --format "%f" | while read -r file; do ...
wobei -m
(Monitormodus) inotifywait
das Beenden nach dem ersten übereinstimmenden Ereignis verhindert und die rechte Seite der Pipe den Namen der Datei erhält, auf die sich das Ereignis bezog. Leider funktioniert dieser Ansatz nicht, wenn Dateinamen <newline>
s enthalten.
Aus diesem Grund verwenden wir im oben gezeigten Code nicht -m
und prüfen $fname
zweimal, ob vorhanden ist. Dieser Ansatz ist etwas fragil, weil$fname
könnte[ -e "$1" ]
zwischen dem ersten und dem ersten Durchlauf von inotifywait
(und auch zwischen den Ausführungen von ) erstellt werden inotifywait
. Es ist auch nicht wirklich geeignet, wenn viele Dateien im überwachten Verzeichnis erstellt wurden, da jede Ausführung von inotifywait
ihre eigenen Überwachungen einrichtet.
Antwort3
Das folgende Skript liest FILENAME
, prüft auf leere Eingaben, berechnet END_DATE
mit dem date
Befehl, stellt sicher, dass die Echtzeit von einer Stunde nicht überschritten wird, und prüft FILENAME
jede Sekunde, ob eine Datei mit dem Namen existiert INTERVAL
. Im Fall des aktuellen Datums:
- ist gleich
END_DATE
: Es wird eine letzte Überprüfung der Dateiexistenz durchgeführt, wobei das Skript die While-Schleife direkt danach verlässt (keine Wartezeit von 300 Sekunden). - übersteigt
END_DATE
: Die While-Schleife wird abgebrochen, ohne zu prüfen, ob die Datei vorhanden ist.
#!/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