script de shell para verificar la disponibilidad de un archivo durante 1 hora, después de una hora, si el archivo no está allí, emitirá un eco de "Tiempo de espera"

script de shell para verificar la disponibilidad de un archivo durante 1 hora, después de una hora, si el archivo no está allí, emitirá un eco de "Tiempo de espera"

Escribí este código. pero el problema es que cada 300 segundos imprime "Tiempo terminado", cuando el $fname presente se sale del bucle. Quiero que "se acabe el tiempo" después de 1 hora si el archivo no llegó, pero después de 300 segundos comienza a imprimirse "se acabó el tiempo"

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

Respuesta1

Creo que ya estás cerca, pero algunos aspectos de tu guión parecen demasiado complicados.

Podrías probar el siguiente whilebucle:

#!/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

Esto comprobará cada $granularitysegundos si el archivo está presente, hasta que $timeoutse exceda el valor. Si el archivo ha aparecido, el script saldrá del bucle.

El problema con su enfoque fue que la salida "Tiempo terminado" está en la elserama de su verificación periódica y, por lo tanto, ocurrirácada vez que se itera el buclesi no se encontró el archivo. En lugar de ello, sugeriría comprobardespués del buclesi su variable de prueba (en su secuencia de comandos la salida de date) ha excedido el límite (indica que el tiempo de espera del ciclo expiró), o alternativamente (tal vez incluso mejor) si el archivo está presente, para decidir si generar o no el mensaje "Tiempo terminado" .

Respuesta2

Un enfoque alternativo, que evita las desventajas del sondeo (la compensación entre el consumo de recursos para ciclos de sondeo cortos y el retraso en la detección de cambios para ciclos de sondeo largos). El precio a pagar es que depende de herramientas que quizás no estén disponibles para usted, a saberherramientas-inotifyytimeout(este último deGNU Coreutils).

Suponiendo que el significado de "verificar la disponibilidad" es que está esperando que fnamese cree un archivo (cuyo nombre está en la variable):

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"

timeoutejecuta un comando durante la duración especificada, que aquí son 3600segundos ( ses la unidad de tiempo predeterminada). Si se alcanza el tiempo de espera, timeoutsale con un estado de 124; de lo contrario, sale con el estado del comando que está ejecutando.

inotifywaitespera cambios en el dirdirectorio (en el que $fnamese supone que se creará); createes el evento que estamos esperando; -qqlo hace realmente tranquilo.

Este tipo de verificación a veces se implementa (por ejemplo, en otras preguntas y respuestas de este sitio) como:

inotifywait -m ... --format "%f" | while read -r file; do ...

donde -m(modo monitor) impide inotifywaitsalir después del primer evento coincidente y el lado derecho de la tubería recibe el nombre del archivo sobre el que se trató el evento. Lamentablemente, este enfoque no funciona si los nombres de archivos contienen <newline>s.

Es por eso que, en el código que se muestra arriba, no usamos -my verificamos la existencia de $fnamedos veces. Este enfoque es un poco frágil porque$fname podríase creará entre la primera [ -e "$1" ]y la primera ejecución de inotifywait(y entre ejecuciones de inotifywaittambién). Tampoco es realmente adecuado en caso de que se hayan creado muchos archivos en el directorio supervisado, porque cada ejecución inotifywaitconfigura sus propios controles.

Respuesta3

El siguiente script lee FILENAMEmientras busca entradas vacías, calcula END_DATEusando el datecomando asegurándose de que no se exceda el tiempo de reloj de pared de una hora y verifica si FILENAMEexiste un archivo con nombre cada INTERVALsegundos. En caso de fecha actual:

  • es igual END_DATE: se realiza una última comprobación de la existencia del archivo y el script sale del bucle while inmediatamente después (sin esperar 300 segundos).
  • excede END_DATE: el bucle while se rompe sin comprobar la existencia del archivo.
#!/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

información relacionada