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 while
bucle:
#!/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 $granularity
segundos si el archivo está presente, hasta que $timeout
se 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 else
rama 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 fname
se 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"
timeout
ejecuta un comando durante la duración especificada, que aquí son 3600
segundos ( s
es la unidad de tiempo predeterminada). Si se alcanza el tiempo de espera, timeout
sale con un estado de 124
; de lo contrario, sale con el estado del comando que está ejecutando.
inotifywait
espera cambios en el dir
directorio (en el que $fname
se supone que se creará); create
es el evento que estamos esperando; -qq
lo 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 inotifywait
salir 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 -m
y verificamos la existencia de $fname
dos 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 inotifywait
también). Tampoco es realmente adecuado en caso de que se hayan creado muchos archivos en el directorio supervisado, porque cada ejecución inotifywait
configura sus propios controles.
Respuesta3
El siguiente script lee FILENAME
mientras busca entradas vacías, calcula END_DATE
usando el date
comando asegurándose de que no se exceda el tiempo de reloj de pared de una hora y verifica si FILENAME
existe un archivo con nombre cada INTERVAL
segundos. 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