web-dev-qa-db-fra.com

Logrotate peut-il subir des conditions de course?

J'ai une application PHP qui peut générer beaucoup d'informations sur les journaux. Je voudrais utiliser logrotate pour m'assurer que ces journaux ne deviennent pas incontrôlables au fil du temps .

Cependant, je suis préoccupé par les conditions de course. Pourrait-il y avoir une perte de messages de journal si PHP est en train d'écrire dans un journal lorsque logrotate détermine qu'il doit faire tourner ce journal, comme dans la séquence d'événements ci-dessous Si non, pourquoi?

  1. PHP ouvre le fichier journal pour l'écriture.
  2. PHP écrit une ligne.
  3. logrotate décide que le fichier journal doit être tourné.
  4. PHP écrit une autre ligne.
  5. PHP ferme la ressource de fichier.

Est-ce que l'utilisation de PHP file_put_contents, par exemple, fait une différence? Qu'en est-il, plus généralement, de la sortie redirigée vers un fichier journal?

Spécificités de l'environnement:

J'utilise php5-fpm (Version: 5.5.9+dfsg-1ubuntu4.6) derrière un serveur nginx sur une autre machine.

Ma configuration logrotate proposée (je n'ai encore rien configuré) ressemblerait à ceci (en /etc/logrotate.d/my-app):

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

Quelques exemples de mon 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);

Il est possible que nous souhaitions à l'avenir utiliser quelque chose comme le code ci-dessous:

$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);
1
Alex

Lorsqu'une application ouvre un fichier, continuez à l'écrire même s'il est déplacé. Par conséquent, si vous voulez être sûr de ne pas perdre d'informations, vous devez envoyer un signal à l'application afin qu'elle libère des ressources.

Vous pouvez essayer cette configuration:

 /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
       }

Ce fichier general.log Subit une rotation chaque fois qu'il atteint une taille supérieure à 20M, Après avoir effectué 4 Rotations, le fichier est supprimé.

Le sharedscripts signifie que le script postrotate ne sera exécuté qu'une seule fois, pas une fois pour chaque journal qui est tourné.

Selon logrotate manuel:

          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.

Donc dans votre cas:

  1. faire pivoter le fichier
  2. supprimer general.log.5 s'il existe
  3. créer general.log avec l'attribut et la propriété appropriés
  4. exécute le script postrotate

Votre application continuera à écrire general.log.1 jusqu'à ce que le fichier soit fermé ou que postscript soit exécuté et que nginx effectue un redémarrage régulier.

Si votre application ferme toujours le fichier journal via fclose($fp) ou utilise file_put_contents, Vous devez omettre nginx grâce au redémarrage.

1
Lety