Shell-Skript zum Prüfen der Verfügbarkeit einer Datei für 1 Stunde. Wenn die Datei nach einer Stunde nicht vorhanden ist, wird „Time Out“ ausgegeben.

Shell-Skript zum Prüfen der Verfügbarkeit einer Datei für 1 Stunde. Wenn die Datei nach einer Stunde nicht vorhanden ist, wird „Time Out“ ausgegeben.

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 whileSchleife 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 $timeoutWert ü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 elseZweig 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 fnameErstellung 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"

timeoutführt einen Befehl für die angegebene Dauer aus, die hier 3600Sekunden beträgt ( sist die Standardzeiteinheit). Wenn das Timeout erreicht ist, timeoutwird mit dem Status beendet 124; andernfalls wird es mit dem Status des ausgeführten Befehls beendet.

inotifywaitwartet auf Änderungen am dirVerzeichnis (das, $fnamein dem es erstellt werden soll); createist das Ereignis, auf das wir achten; -qqmacht 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) inotifywaitdas 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 -mund prüfen $fnamezweimal, 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 inotifywaitihre eigenen Überwachungen einrichtet.

Antwort3

Das folgende Skript liest FILENAME, prüft auf leere Eingaben, berechnet END_DATEmit dem dateBefehl, stellt sicher, dass die Echtzeit von einer Stunde nicht überschritten wird, und prüft FILENAMEjede 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

verwandte Informationen