Assumindo que your-filter
lê seus dados de stdin:
while your-filter; do
sleep 60
done < file.log
Isso pressupõe que your-filter
apenas leia os dados e não tente lseek
, por exemplo.
Agora, para resolver o problema de rotação de log, se no Linux (onde, ao contrário da maioria dos outros sistemas, /dev/fd/n
são links simbólicos para os arquivos reais), com ksh
, bash
, zsh
, dash
, yash
(a maioria das shells POSIX, exceto as mais pedantemente POSIX, como posh
as -ef
não é POSIX):
while your-filter; do
if [ file.log -ef /dev/stdin ]; then
sleep 60
else
exec < file.log
fi
done < file.log
Após a rotação do log, isso chamaria your-filter
duas vezes, se você preferir que ele seja chamado uma vez com a concatenação do antigo e do novo:
while
if [ file.log -ef /dev/stdin ]; then
your-filter
else
exec 3<&0 < file.log
(cat <&3; cat) | your-filter &&
exec 3<&-
fi
do
sleep 60
done < file.log
Agora, após a rotação do log, pode haver um momento em que o arquivo file.log antigo foi renomeado, mas o novo file.log
ainda não foi criado. Nesse caso, o acima falhará se usar o exec < file.log
nesse muito momento. Então você poderia consertar isso com:
while
if [ file.log -ef /dev/stdin ] || ! command exec 3< file.log; then
your-filter
else
(cat; cat <&3) | your-filter &&
exec <&3 3<&-
fi
do
sleep 60
done < file.log
Então, ele continua lendo o arquivo antigo até que o novo seja exibido.
command
é necessário para evitar que exec
faça o shell sair quando ele falhar (como requer o POSIX). Não é necessário com zsh
ou bash
quando não estiver no modo sh
.
Agora, dormimos por 60 segundos no loop e your-filter
pode levar alguns segundos para ser executado. Se for importante que your-filter
seja executado a cada minuto, em média, com ksh
, bash
ou zsh
, você poderá alterá-lo para:
t=$SECONDS
while
if [ file.log -ef /dev/stdin ] || ! command exec 3< file.log; then
your-filter
else
(cat; cat <&3) | your-filter &&
exec <&3 3<&-
fi
do
t=$(($t + 60))
sleep "$((t - SECONDS))"
done < file.log
Com ksh93
e zsh
e desde que seu sleep
aceite argumentos de ponto flutuante, você pode executar typeset -F SECONDS
.