Como vincular um arquivo de log a / dev / null e restaurar o espaço usado automaticamente

3

Eu tenho um arquivo de log que cresce muito. A informação que posso obter é insignificante.

Eu quero vinculá-lo a /dev/null . No entanto, mesmo que seja "excluído" (veja abaixo a saída do lsof), ele consome todo o meu espaço em disco rígido.

Eu posso truncá-lo usando:

: > "/proc/$pid/fd/$fd"
# for instance:
: > "/proc/2456/fd/2"

Infelizmente, existem processos no sistema que são pausados quando o disco rígido está cheio e devem ser reiniciados manualmente (e eu quero evitar que os processos sejam pausados).

Existe uma maneira de truncar automaticamente o arquivo quando ele fica muito grande (por exemplo, quando ele consome mais de 1G?)

lsof output:

program  2456 user    2w   REG    8,5 441433300992     0 21365598 /home/user/file (deleted)
    
por gc5 07.09.2015 / 18:32

4 respostas

4

O conteúdo de um arquivo é excluído apenas quando não há mais referência a ele. Uma referência a um arquivo pode ser uma entrada de diretório ou um identificador de arquivo aberto. Quando você remove um arquivo (por exemplo, com o comando rm ) que um processo ainda está aberto (aqui, o processo que está fazendo o log), o conteúdo do arquivo permanece até que o processo feche o arquivo.

A maneira mais simples de se livrar de logs antigos é

  1. Mover o arquivo para outro nome, por exemplo %código%
  2. Instrua o processo para reabrir seu arquivo de log. Se o processo não tiver como fazer isso, reinicie-o.
  3. Exclua o arquivo de log antigo agora fechado ( mv foo.log foo.log.old ).

O programa logrotate automatiza esse mecanismo e pode ser configurado para quantos dias de registros antigos devem ser mantidos . Ele também pode compactar logs antigos.

Para a etapa 2, se você não puder reiniciar o programa e não tiver como reabri-lo, tente forçá-lo a reabrir o arquivo de log com um depurador. No entanto, esteja ciente de que isso pode travar o programa se ele mantiver informações sobre o arquivo de log que agora se tornou inconsistente. Prova de conceito (cuidado com o fato de que muitas coisas podem dar errado com isso; em caso de dúvida, não faça isso):

gdb -n $pid -batch -x /dev/stdin <<EOF
call close(2)
call open("/path/to/foo.log", 1)
EOF

Um método bruto alternativo para liberar algum espaço em disco se você não se importa com nenhum dos logs é truncar o arquivo. O processo de registro continuará escrevendo na mesma posição no arquivo, mas o arquivo se tornará um arquivo esparso . Se você ler o arquivo desde o início, você obterá bytes nulos, mas esses bytes nulos ocuparão apenas alguns kB no disco.

dd if=/dev/null of=/path/to/foo.log
    
por 08.09.2015 / 01:38
2

Quando você exclui um arquivo, você não o "exclui". Você desvincula isso. O resultado final é que o programa que tinha o arquivo de log aberto ainda pode acessar o arquivo de log até que ele seja fechado (o que é raro com arquivos de log).

Agora, para corrigir corretamente seu problema, você vai querer analisar a rotação de logs e a filtragem de registros.

A rotação do registro permitirá arquivar, compactar e excluir com base em um conjunto de regras. Por exemplo, todas as entradas mais antigas e um dia são compactadas e todas as entradas com mais de 7 dias são excluídas.

A filtragem de logs está simplesmente reduzindo a quantidade de "coisas" que entram no log. Alguns programas implementam a filtragem no lado do programa, outros no lado do registrador. Se você estiver usando o syslogd, por exemplo, você pode dizer para filtrar mensagens não críticas em cada coisa (novamente, por exemplo).

Para corrigir seu problema rapidamente, reinicie o serviço, descubra se ele responde a um sinal SIGUSR1 e SIGHUP são muito comuns e envie-o ou reinicie a máquina.

    
por 07.09.2015 / 18:53
1

Reinicie o program para liberar o arquivo excluído. Investigue logrotate ou algo parecido para gerenciar adequadamente os dados do registro ou ajuste o programa para emitir menos mensagens de registro.

    
por 07.09.2015 / 18:40
1

Se o arquivo de log estiver sendo criado pela saída para stderr ou stdout , e se você puder controlar a maneira como o programa que cria o arquivo de log (vamos chamá-lo bar ) for iniciado, inicie-o com bar &>/dev/null , que redirecionará todas as saídas padrão ou mensagens de erro para / dev / null.

Como alternativa, (e sei que isso é uma prática muito ruim, mas pelo menos funcionará) configure um cron job de hora em hora para eliminar o programa que está criando o log, excluir o arquivo de log e iniciar o backup do programa, programa não é essencial para a operação do sistema. Novamente, desde que o nome do programa seja bar , a maneira de fazer isso seria echo "* 0 0 0 0 \"/bin/killall [offending program]; /bin/rm [offending log]; [command to run program];\" 1>[crontab location]" .

Observe que os colchetes são usados para denotar marcadores de posição e não devem estar no comando inserido.

Mais uma vez, observe que a segunda solução é uma péssima prática e, no geral, apenas uma correção de bandagem ... portanto, use-a por sua conta e risco.

    
por 07.09.2015 / 19:57