Outra forma deste problema ocorre com aplicativos de longa execução cujos logs são rotacionados periodicamente. Mesmo se você mover o log original (por exemplo, mv log.txt log.1
) e substituí-lo imediatamente por um arquivo com o mesmo nome antes que ocorra qualquer registro real, se o processo estiver mantendo o arquivo aberto, ele acabará gravando em log.1
(porque isso ainda pode ser o inode aberto) ou para nada.
Uma maneira comum de lidar com isso (o próprio criador de logs do sistema funciona dessa forma) é implementar um manipulador de sinal no processo que fechará e reabrirá seus logs. Então, sempre que você quiser mover ou limpar (excluindo) o log, envie esse sinal para o processo imediatamente depois.
Aqui está uma demonstração simples para o bash - perdoe minhas habilidades de casca rudimentares (mas se você for editar isto para melhores práticas, etc., por favor, certifique-se de entender a funcionalidade primeiro e testar sua revisão antes você edita):
#!/bin/bash
trap sighandler INT
function sighandler () {
touch log.txt
exec &> log.txt
}
echo $BASHPID
exec &> log.txt
count=0;
while [ $count -lt 60 ]; do
echo "$BASHPID Count is now $count"
sleep 2
((count++))
done
Comece por colocar em segundo plano:
> ./test.sh &
12356
Observe que ele informa seu PID para o terminal e começa a registrar em log.txt
.
Agora você tem 2 minutos para brincar. Aguarde alguns segundos e tente:
> mv log.txt log.1 && kill -s 2 12356
Apenas kill -2 12356
pode funcionar para você também. O sinal 2 é SIGINT (também é o que o Ctrl-C faz, então você pode tentar isso em primeiro plano e mover ou remover o arquivo de log de outro terminal), que o trap
deve capturar. Para verificar;
> cat log.1
12356 Count is now 0
12356 Count is now 1
12356 Count is now 2
12356 Count is now 3
12356 Count is now 4
12356 Count is now 5
12356 Count is now 6
12356 Count is now 7
12356 Count is now 8
12356 Count is now 9
12356 Count is now 10
12356 Count is now 11
12356 Count is now 12
12356 Count is now 13
12356 Count is now 14
Agora vamos ver se ainda está escrevendo para um log.txt
, embora tenhamos movido:
> cat log.txt
12356 Count is now 15
12356 Count is now 16
12356 Count is now 17
12356 Count is now 18
12356 Count is now 19
12356 Count is now 20
12356 Count is now 21
Observe que continuou indo exatamente de onde parou. Se você não quiser manter o registro, limpe o registro excluindo-o
> rm -f log.txt && kill -s 2 12356
Verifique:
> cat log.txt
12356 Count is now 29
12356 Count is now 30
12356 Count is now 31
12356 Count is now 32
12356 Count is now 33
12356 Count is now 34
12356 Count is now 35
12356 Count is now 36
Ainda vai.
Você não pode fazer isto em um shell script para um subprocesso executado, infelizmente, porque se ele estiver em primeiro plano, os manipuladores de sinal do bash ( trap
s) serão suspensos, e se você forçar o plano em segundo plano, você não pode reatribuir sua saída. Ou seja, isso é algo que você precisa implementar em seu aplicativo.
No entanto ...
Se você não pode modificar o aplicativo (por exemplo, porque você não o escreveu), eu tenho um utilitário CLI você pode usar como intermediário. Você também pode implementar uma versão simples disso em um script que serve como um canal para o log:
#!/bin/bash
trap sighandler INT
function sighandler () {
touch log.txt
exec 1> log.txt
}
echo "$0 $BASHPID"
exec 1> log.txt
count=0;
while read; do
echo $REPLY
done
Vamos chamar isso de pipetrap.sh
. Agora precisamos de um programa separado para testar, imitando o aplicativo que você deseja registrar:
#!/bin/bash
count=0
while [ $count -lt 60 ]; do
echo "$BASHPID Count is now $count"
sleep 2
((count++))
done
Isso será test.sh
:
> (./test.sh | ./pipetrap.sh) &
./pipetrap.sh 15859
Estes são dois processos separados com PIDs separados. Para limpar a saída de test.sh
, que está sendo canalizada através de pipetrap.sh
:
> rm -f log.txt && kill -s 2 15859
Verifique:
>cat log.txt
15858 Count is now 6
15858 Count is now 7
15858 Count is now 8
15858, test.sh
, ainda está em execução e sua saída está sendo registrada. Nesse caso, nenhuma modificação no aplicativo é necessária.