Rotação de log de stdout?

53

Eu tenho um programa Linux que pode gravar informações em stdout e stderr.

Eu tenho um script de shell que redireciona essa saída para um arquivo /var/log. (Via >>e 2>&1.)

Existe uma maneira de fazer esse arquivo de log girar? (tamanho máximo, depois mude para um arquivo diferente, mantenha apenas um número limitado de arquivos)

Eu já vi algumas respostas que falam sobre o logrotateprograma, o que parece bom, mas também parecem focadas em programas que estão gerando arquivos de log internamente e lidam com sinais HUP. Existe uma maneira de fazer isso funcionar com um script de redirecionamento de saída básico?

Miral
fonte
11
Por que você não pode simplesmente modificar o script que redireciona a saída para conter a lógica da rotação?
MaQleod
Eu poderia, se alguém pudesse me dizer como detectar o tamanho de um arquivo de log e girá-lo para baixo do stdout de um processo sem atrapalhar esse processo. Não preciso usar logrotatese houver uma opção melhor, que soou como um ponto de partida conveniente para discussão.
Miral
2
Você não precisa usar o logrotate, mas usar o logrotate economiza tempo ... Geralmente, não faz muito sentido reinventar a roda.
bubu
Exatamente o meu ponto. Existe uma maneira de fazer o logrotate funcionar com o stdout redirecionado de um processo em andamento?
Miral

Respostas:

44

Como alternativa, você pode canalizar a saída através de ferramentas projetadas com o objetivo principal de manter conjuntos de arquivos de log com limite de tamanho e rotação automática, como:

As ferramentas para processar multilogconjuntos de arquivos de log de formato incluem, entre outros:

Leitura adicional

JdeBP
fonte
11
Obrigado, multilogparece exatamente o que eu precisava.
Miral
O multilog parece ser a única solução plug-and-play no debian (daemontools possui um pacote oficial). Mas no meu caso particular, onde eu queria armazenar os logs em uma partição fat32, a rotação não funciona, pois o multilog deseja usar um link simbólico. Sem plug and play para mim :)
Arnout
Isso não pode ser verdade, pois multilognenhum lugar cria ou exige vínculos simbólicos. É totalmente neutro em relação a eles.
JdeBP # 23/18
URL de "Não use logrotate ou newsyslog neste século" tem pontos extras
duyue
15

a rotatelogsferramenta fornecida com o apache (no bindiretório) (consulte docs ) recebe a entrada do stdin e gira o log após um período específico de tempo

BertNase
fonte
14

Se você puder acessá-lo em um dos fluxos de logs padrão (syslog, daemon, cron, usuário, segurança, correio etc.), poderá usar o loggercomando e canalizar para ele.

echo "Hello." | logger -p daemon.info

Caso contrário, é melhor canalizar o conteúdo registrado para um programa ou script personalizado para lidar com isso ou verificar a logrotateconfiguração.

EDIT: A resposta do JdeBP parece ter o que você pode estar procurando.

Lara Dougan
fonte
2
+1 por simplicidade. BTW, você também pode configurar uma instalação personalizada (local0) em vez dos normais (daemon no seu exemplo)
Roger Keays
14

Eu tive um problema semelhante e inicialmente descartei o logrotate, mas acabou que o logrotate pode realmente fazer isso bem, a diretiva-chave é " copytruncate ". Por alguma razão, esse termo não apareceu em nenhum dos artigos que eu escrevi, por isso estou adicionando esta resposta para esclarecer exatamente como usá-lo neste caso.

O truque é que isso só funciona se o redirecionamento for feito com " >> " (anexar) em vez de " > " (criar).

Arquivo de configuração (truncate.cfg):

/tmp/temp.log {
    size 10M
    copytruncate
    rotate 4
    maxage 100
}

Programa de teste (nunca desiste de arquivo). Você pode vê-lo preenchendo o disco e, embora a exclusão do arquivo de log pareça funcionar, ele não liberará espaço no disco:

cat /dev/urandom >> /tmp/temp.log

Rodar log de execução:

logrotate truncate.cfg
Sam Hendley
fonte
É uma teoria legal, mas na verdade não funciona em nenhum sistema em que eu tentei. O arquivo não é realmente truncado e o programa continua anexado a ele como antes. (E sim, isso é mesmo com o redirecionamento feito via >>.) ((BTW, esta resposta foi já dada anteriormente).)
Miral
11
… Como discutido em logrotate não truncará o arquivo original (em nosso site Unix e Linux). Além disso, echo /dev/urandom >> /tmp/temp.loggravará 13 caracteres determinísticos /tmp/temp.loge sairá imediatamente. Você quis dizer cat /dev/urandom?
G-Man Diz 'Reinstate Monica'
2
Acabei de testar aqui, e parece funcionar. O conteúdo do arquivo é copiado para o novo arquivo de log. O arquivo original é mantido aberto pelo processo e é truncado (o tamanho agora mostra 0).
Philipp
11
Tenha cuidado com a possível perda de dados com copytruncate.
wanghq
11
+1 embora "Observe que há um intervalo de tempo muito pequeno entre copiar e truncá-lo, portanto, alguns dados de log podem ser perdidos".
Tagar 27/05
3

Existe uma maneira de fazer o logrotate funcionar com o stdout redirecionado de um processo em andamento?

Sim! Confira a diretiva "copytruncate" oferecida pelo logrotate. Especificando que instrui o logrotate para lidar com essa mesma situação: um programa simples que mantém seu arquivo de log aberto indefinidamente.

Uma ressalva pode ou não ser um problema na sua situação:

Observe que há um intervalo de tempo muito pequeno entre copiar o arquivo e truncá-lo, portanto, alguns dados de log podem ser perdidos.

Curiosamente, eu vi algumas fontes de log do "mundo real" que incentivam os usuários a aplicar esta diretiva. Há alguma discussão sobre essa opção aqui .

natevw
fonte
3

Use split, faz parte do coreutils. Pode pegar o stdin e dividi-lo em pedaços (com base no tamanho do pedaço ou no número de linhas, etc.).

Exemplo:

app | split --bytes 1G - /var/logs/put-prefix-here

Nota dash (-) instrui "split" para usar stdin em vez de arquivo.

Nazar
fonte
Você pode expandir sua resposta para descrever como fazer isso? Obrigado.
precisa saber é o seguinte
apenas atualizei minha resposta com o exemplo.
Nazar
O 1G é um tamanho arbitrário, após o qual inicia um novo arquivo?
fixer1234
11
Essa não é uma solução particularmente boa para o problema, pois significa que você pode acabar com meia mensagem em um arquivo e metade no seguinte. Também há o risco de perda de dados se a máquina travar enquanto splithouver dados no que poderia ser um buffer grande. Dado que existem várias ferramentas que resolvem esse problema adequadamente, não acho que esse tipo de solução faça seu próprio roll-on possa ser recomendado.
David Richerby
11
@ David Richerby- que tal adicionar -u para sem buffer?
Nick
3

Gosto multilogdo meu caso de uso, mas meu caso de uso é tão trivial / simples que não é apresentado de maneira muito simples nos documentos / exemplos que encontrei. Aqui está um exemplo simples de rotação múltipla:

mkdir /tmp/myapp
./myapp | multilog t s10000 n5 '!tai64nlocal' /tmp/myapp 2>&1

Algumas notas:

  • isso despeja os logs nesse diretório / tmp / myapp /
  • o s10000 representa 10.000 bytes *
  • o n5 representa 5 arquivos. * O log 'atual' conta como um dos arquivos, portanto, inclui 4 logs mais antigos + 'atual'
  • isso é baseado, adaptado dos exemplos fornecidos por François Beausoleil em: http://blog.teksol.info/pages/daemontools/best-practices
  • Não entendo muitas das opções - remeto-o para as várias documentações para estender isso ...
  • Os documentos alertam que: "Note that running processor may block any program feeding input to multilog."onde 'processador' é a '!tai64nlocal'parte do comando

* Para muitas aplicações, essas são escolhas ruins para uso a longo prazo. Eles permitem observar o comportamento de preencher e girar os logs mais rapidamente do que os grandes.

Finalmente, não se esqueça de usar o nohup, se necessário! Com nohup, você não precisa de 2>&1(s = 10e6 en = 30 aqui):

mkdir -p /tmp/myapp
nohup ./myapp | multilog t s10000000 n30 '!tai64nlocal' /tmp/myapp &

Esse comando deve começar.

sábio
fonte
1

Eu só queria adicionar ao comentário de Sam Hendley acima:

O truque é que isso só funciona se o redirecionamento for feito com >>(acrescentar) em vez de >(criar).

Corri para o mesmo problema em que o arquivo original continua crescendo se você usar >(criar), mas se você usar >>(acrescentar) o Logrotate copytruncate funciona perfeitamente e conforme o esperado. O arquivo original volta para zero bytes e o programa continua gravando.

Redirecione STDOUT e STDERR para um arquivo de log rotativo:

  1. some-program.sh >> /tmp/output.txt 2>&1 &
  2. Crie um arquivo de configuração de logrotate /etc/logrotate.dchamado de qualquer coisa, output_roll no meu caso.

    Exemplo de configuração para o meu caso:

    /tmp/output.txt {
        notifempty
        missingok
        size 1G
        copytruncate
        start 0
        rotate 15
        compress
    }
    
  3. Configure seu trabalho cron dentro do /etc/crontabarquivo

    *  *  *  *  * root /usr/sbin/logrotate /etc/logrotate.d/output_roll
    

    Isso verificará o arquivo a cada minuto. Você pode ajustar para atender às suas necessidades.

  4. Inicie:

    $> service crond restart
    
  5. É isso aí

Nota: Eu também tive um problema com o SELinux sendo definido como SELINUX=enforcingdefinido SELINUX=disabled.

user578558
fonte
1

Eu escrevi um logrotee neste fim de semana. Provavelmente, não leria se tivesse lido a ótima resposta e o @ JdeBP multilog.

Eu me concentrei em ser leve e poder bzip2 seus pedaços de saída como:

verbosecommand | logrotee \
  --compress "bzip2 {}" --compress-suffix .bz2 \
  /var/log/verbosecommand.log

Ainda há muito a ser feito e testado.

Victor Sergienko
fonte