eu escrevi esse código. mas o problema é que a cada 300 segundos ele imprime "Time over", quando $fname present sai do loop. Quero "fim de tempo" após 1 hora se o arquivo não chegar, mas depois de 300 ele começa a imprimir "fim de tempo"
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
Responder1
Acho que você já está perto, mas alguns aspectos do seu roteiro parecem complicados demais.
Você poderia tentar o seguinte while
loop:
#!/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
Isto irá verificar a cada $granularity
segundo se o arquivo está presente, até que o $timeout
valor seja excedido. Se o arquivo aparecer, o script sairá do loop.
O problema com sua abordagem foi que a saída "Time over" está no else
ramo da sua verificação periódica e, portanto, ocorrerátoda vez que o loop é iteradose o arquivo não foi encontrado. Em vez disso, sugiro verificardepois do ciclose a sua variável de teste (no seu script a saída de date
) excedeu o limite (indica que o loop expirou) ou, alternativamente (talvez ainda melhor) se o arquivo estiver presente, para decidir se deseja ou não gerar a mensagem "Tempo esgotado" .
Responder2
Uma abordagem alternativa, que evita as desvantagens da votação (o compromisso entre o consumo de recursos para ciclos curtos de votação e o atraso na detecção de alterações para ciclos longos de votação). O preço a pagar é que depende de ferramentas que podem não estar disponíveis para você, nomeadamenteferramentas inotifyetimeout
(este último deGNU Coreutils).
fname
Supondo que o significado de "verificar a disponibilidade" é que você está aguardando a criação de um arquivo (cujo nome está na variável):
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
executa um comando pela duração especificada, que aqui é 3600
segundos ( s
é a unidade de tempo padrão). Se o tempo limite for atingido, timeout
sai com o status 124
; caso contrário, ele sai com o status do comando que está executando.
inotifywait
aguarda alterações no dir
diretório (aquele em que $fname
deve ser criado); create
é o evento que estamos observando; -qq
faz com que seja realmente bastante.
Este tipo de verificação às vezes é implementado (por exemplo, em outras perguntas e respostas neste site) como:
inotifywait -m ... --format "%f" | while read -r file; do ...
onde -m
(modo monitor) impede inotifywait
a saída após o primeiro evento correspondente e o lado direito do canal recebe o nome do arquivo do qual o evento se tratava. Infelizmente, essa abordagem falha se os nomes dos arquivos contiverem <newline>
s.
É por isso que, no código mostrado acima, não usamos -m
e verificamos a existência de $fname
duas vezes. Esta abordagem é um pouco frágil porque$fname
poderser criado entre a primeira [ -e "$1" ]
e a primeira execução inotifywait
(e entre as execuções inotifywait
também). Também não é muito adequado caso muitos arquivos tenham sido criados no diretório monitorado, porque cada execução inotifywait
configura seus próprios relógios.
Responder3
O script a seguir lê FILENAME
enquanto verifica a entrada vazia, calcula END_DATE
usando o date
comando, certificando-se de que o tempo de uma hora do relógio não seja excedido e verifica se um arquivo nomeado FILENAME
existe a cada INTERVAL
segundo. No caso da data atual:
- é igual a
END_DATE
: uma última verificação de existência de arquivo ocorre com o script saindo do loop while logo após (sem espera de 300 segundos). - excede
END_DATE
: o loop while é interrompido sem verificar a existência do arquivo.
#!/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