Dailyfile : un petit outil en ligne de commande

Publié par cpb
Mai 01 2017

Dailyfile

J’ai récemment été confronté à un souci de taille de fichiers de traces pour le débogage d’une application. Pour résoudre mon problème j’ai écrit un petit programme en ligne de commande permettant de répartir la sortie d’un pipeline du shell dans des fichiers quotidiens.

J’ai appelé cet outil dailyfile et je vous le présente ici, en espérant qu’il puisse servir à d’autres.

Présentation

Problématique

J’ai développé il y a quelques temps pour un client un programme sous Linux qui s’occupe d’initialiser et de superviser des communications entre des applications distantes et des serveurs. La mise au point est un peu compliquée car les communications reposant sur des modems 2G des difficultés inattendues apparaissent dans la gestion des déconnexions intempestives.

J’ai prévu, comme d’habitude, dans mon programme de nombreux messages de débogage que l’on peut activer ou non en fonction d’un niveau paramétrable à la compilation.

Un script démarre l’application, qui écrira tous ses messages de débogage sur la sortie stderr. Comme je n’ai pas accès directement à ce serveur, les données sont redirigées dans un fichier que mon client me transmet par mail quand un problème survient. Le script est un peu plus complexe, mais on peut imaginer quelque chose comme :

$ ./my-application >logfile.txt 2>&1

La première redirection envoie la sortie standard stdout du programme dans le fichier de trace, la seconde redirection 2>&1 redirige la sortie stderr de la même manière. Le script réel est plus compliqué car on gère un redémarrage automatique en cas de crash et un fichier de trace dont le nom contient la date de démarrage.

Les erreurs se produisant somme toute assez rarement, le programme tourne parfois pendant plusieurs jours entre deux redémarrages, et le fichier de trace pèse facilement plusieurs centaines de mégaoctets. Son transfert et l’analyse de son contenu deviennent alors plus compliqués.

On ne peut pas facilement répartir le contenu dans différents fichiers sans arrêter l’application, ce qui est problématique dans notre cas. L’utilisation de logrotate est un peu complexe, d’autant que nous n’avons pas les droits d’administration sur le serveur.

Solution

Mon idée a été de remplacer la redirection “>” vers un fichier par une redirection “|” dans un pipeline. De l’autre côté du pipeline un programme lira les données, et les copiera dans un fichier, en changeant tous les jours.

La programmation proprement dite est simple, et le code source est disponible dans mon dépôt Github.

Installation

La compilation du programme ne présente en principe pas de difficulté :

$ git  clone  https://github.com/cpb-/Dailyfile
Clonage dans 'Dailyfile'...
remote: Counting objects: 33, done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 33 (delta 12), reused 31 (delta 10), pack-reused 0
Dépaquetage des objets: 100% (33/33), fait.
Vérification de la connectivité... fait.
$ cd  dailyfile/
$ make clean  &&  make
rm -f dailyfile dailyfile.o *~
gcc -Wall -W -DPROGRAM_VERSION="0.3" -c  dailyfile.c
gcc -o dailyfile dailyfile.o 
$ sudo  make  install
cp dailyfile /usr/local/bin/
$

Utilisation

L’utilisation de base est plutôt simple :

$  commande-qui-dure-longtemps  |  dailyfile

Toutes les données écrites par la première commande dans le pipeline seront enregistrées dans des fichiers nommés day-YYYY-MM-DD.logYYYY, MM, et DD représentent respectivement l’année, le mois et le jour de création du fichier.

En voici un exemple d’exécution réelle :

$ while true; do date; sleep 5; done | dailyfile

Cette commande affiche la date toutes les cinq secondes. On retrouve plusieurs jours plus tard les résultats dans les fichiers :

$ ls -l
total 2148
-rw-r--r-- 1 cpb cpb 583906 avril 29 01:59 day-2017-04-28.log
-rw-r--r-- 1 cpb cpb 727838 avril 30 01:59 day-2017-04-29.log
-rw-r--r-- 1 cpb cpb 750812 mai    1 01:59 day-2017-04-30.log
-rw-r--r-- 1 cpb cpb 113240 mai    1 06:08 day-2017-05-01.log

On peut remarquer que l’heure de la dernière modification des fichiers écoulés est à 1 heure 59. C’est normal, le basculement est effectué en se basant sur l’heure G.M.T, décalée de deux heures l’été par rapport à l’heure locale affichée par ls.

Options

Il existe quelques options pour modifier le comportement du programme.

  • -b size ou --buffer-size=size : modifier la taille du buffer interne de copie des données. Par défaut 16384 octets.
  • -c seconds ou --cycle=seconds : fixer la durée de commutation en secondes. Par défaut 86400 secondes (une journée).
  • -d dir ou --directory=dir : indiquer le répertoire où stocker les fichiers. Par défaut, ils sont enregistrés dans le répertoire courant.
  • -h ou --help : afficher un rappel des commandes.
  • -l ou --localtime : utiliser l’heure locale lors de la création des noms de fichiers. Faux par défaut, on utilise l’heure G.M.T.
  • -p string ou --prefix=string : préciser le préfixe à écrire avant la date dans le nom du fichier. Par défaut, c’est “day-“.
  • -s string ou --suffix=string : indiquer le préfixe à écrire après la date dans le nom du fichier. Par défaut, c’est “.log“.
  • -v ou --version : afficher la version de l’outil dailyfile.

Lorsque la période de commutation (option -c) est inférieure à une journée, le nom des fichiers inclut des champs heure, minute, et seconde de création.

Exemple

Voici un exemple d’exécution où je modifie le préfixe du fichier pour le remplacer par “date-“, son suffixe devient “.txt“, et sa période est changée pour avoir un basculement de fichier à chaque changement d’heure :

$ while true; do date; sleep 5; done | dailyfile -c 3600 -p 'date-' -s '.txt' -l

Après quelques heures on observe des fichiers dont le nom inclut l’heure de création. On peut observer des petites fluctuations dans le champ “seconde”, dûes aux périodes de réveil du shell.

$ ls -l
-rw-r--r--  1 cpb cpb  2255 avril 27 12:59 date-2017-04-27-12-55-24.txt
-rw-r--r--  1 cpb cpb 29520 avril 27 13:59 date-2017-04-27-13-00-00.txt
-rw-r--r--  1 cpb cpb 29520 avril 27 14:59 date-2017-04-27-14-00-02.txt
-rw-r--r--  1 cpb cpb 29479 avril 27 15:59 date-2017-04-27-15-00-04.txt
-rw-r--r--  1 cpb cpb 29520 avril 27 16:59 date-2017-04-27-16-00-02.txt
-rw-r--r--  1 cpb cpb 29479 avril 27 17:59 date-2017-04-27-17-00-04.txt
-rw-r--r--  1 cpb cpb 29479 avril 27 18:59 date-2017-04-27-18-00-02.txt
-rw-r--r--  1 cpb cpb 29520 avril 27 19:59 date-2017-04-27-19-00-00.txt
-rw-r--r--  1 cpb cpb 29479 avril 27 20:59 date-2017-04-27-20-00-03.txt
-rw-r--r--  1 cpb cpb 29479 avril 27 21:59 date-2017-04-27-21-00-02.txt
-rw-r--r--  1 cpb cpb 29520 avril 27 22:59 date-2017-04-27-22-00-00.txt
-rw-r--r--  1 cpb cpb 29479 avril 27 23:59 date-2017-04-27-23-00-04.txt
-rw-r--r--  1 cpb cpb 31636 avril 28 00:59 date-2017-04-28-00-00-02.txt
-rw-r--r--  1 cpb cpb 31680 avril 28 01:59 date-2017-04-28-01-00-01.txt
-rw-r--r--  1 cpb cpb 31636 avril 28 02:59 date-2017-04-28-02-00-04.txt
-rw-r--r--  1 cpb cpb 31636 avril 28 03:59 date-2017-04-28-03-00-03.txt
-rw-r--r--  1 cpb cpb 31636 avril 28 04:59 date-2017-04-28-04-00-01.txt
-rw-r--r--  1 cpb cpb 31680 avril 28 05:59 date-2017-04-28-05-00-00.txt
-rw-r--r--  1 cpb cpb 31636 avril 28 06:59 date-2017-04-28-06-00-04.txt
  [...]

 

Les suggestions, remarques et pull requests sur Github sont les bienvenues !

Précédent :

URL de trackback pour cette page