Pode logrotate sofrer condições de corrida?

1

Eu tenho um aplicativo PHP que pode gerar muitas informações de log. Gostaria de usar logrotate para garantir que esses logs não fiquem fora de controle ao longo do tempo.

No entanto, estou preocupado com as condições da corrida. Poderia haver uma perda de mensagens de log se o PHP estivesse no meio da gravação em um log quando logrotate determinar que precisa rotacionar esse log, como na sequência de eventos abaixo? Se não, por quê?

  1. O PHP abre o arquivo de log para gravação.
  2. PHP escreve uma linha.
  3. logrotate decide que o arquivo de log deve ser girado.
  4. PHP escreve outra linha.
  5. O PHP fecha o recurso de arquivo.

Usar o file_put_contents do PHP, por exemplo, faz alguma diferença? E quanto, mais geralmente, a saída que é canalizada para um arquivo de log?

Especificações de ambiente:

Estou usando php5-fpm ( Version: 5.5.9+dfsg-1ubuntu4.6 ) atrás de um servidor nginx em uma máquina diferente.

Minha configuração de logrotate proposta (ainda não configurei nada) seria algo assim (em /etc/logrotate.d/my-app ):

/var/my-app-data/logs/*.log {
    missingok
    notifempty
    weekly
    size 20M
    rotate 4
}

Alguns exemplos do meu código de registro em PHP:

$res = file_put_contents('/var/my-app-data/logs/general.log', date('[d/m/Y H:i:s]') . ' Something noteworthy has happened!' . "\n", FILE_APPEND);

É possível que possamos usar algo como o código abaixo no futuro:

$fp = fopen('/var/my-app-data/logs/general.log', 'a');
fwrite($fp, date('[d/m/Y H:i:s]') . ' Starting process...' . "\n");
// ...
fwrite($fp, date('[d/m/Y H:i:s]') . ' Something happened!' . "\n");
// ...
fwrite($fp, date('[d/m/Y H:i:s]') . ' Something happened!' . "\n");
// ...
fwrite($fp, date('[d/m/Y H:i:s]') . ' End of process.' . "\n");
fclose($fp);
    
por Alex 18.03.2015 / 16:16

1 resposta

1

Quando um aplicativo abre um arquivo, continue a escrevê-lo mesmo se ele for movido. Portanto, se você quiser ter certeza de não perder informações, você deve enviar um sinal para o aplicativo, para liberar recursos.

Você pode tentar esta configuração:

 /var/my-app-data/logs/general.log {
           missingok
           notifempty
           size 20M
           rotate 4
           create mode owner group
           sharedscripts
           postrotate
               nginx command to do graceful restart 
           endscript
       }

Este arquivo general.log é girado sempre que crescer em 20M em tamanho, depois de passar por 4 rotações, o arquivo é removido.

O sharedscripts significa que o script postrotate será executado apenas uma vez, não uma vez para cada log que é rotacionado.

De acordo com o logrotate manual:

          create mode owner group
          Immediately after rotation (before the postrotate script is run)
          the log file is created (with the same name as the log file just
          rotated).   mode  specifies  the  mode for the log file in octal
          (the same as chmod(2)), owner specifies the user name  who  will
          own  the  log  file,  and group specifies the group the log file
          will belong to.

Então, no seu caso:

  1. girar arquivo
  2. remove general.log.5 se existir
  3. crie general.log com atributo e propriedade próprios
  4. executa o script postrotate

Seu aplicativo continuará a escrever general.log.1 até que o arquivo seja fechado ou postscript seja executado e nginx execute uma reinicialização normal.

Se o seu aplicativo sempre fechar o arquivo de log via fclose($fp) ou usar file_put_contents , você deverá omitir nginx reinicialização normal.

    
por Lety 19.03.2015 / 14:03