Forum Programmation.shell Écriture différée de &> log

Posté par  .
Étiquettes : aucune
2
28
jan.
2011
J'ai un programme qui écrit sur la sortie standard et erreur (en C89, printf et fprintf (stderr)). Ce programme est lancé depuis bash. Je récupère la sortie avec ./programme &> log et je suis le fichier depuis une autre console avec tail -f log.

J'ai remarqué que le fichier log n'est pas à jour pendant le lancement du programme. Il me semble que la sortie de printf reste quelque part dans un buffer et est mis à jour quand le programme se termine. Cela m'empêche de suivre avec tail -f pendant l'exécution.

Est-ce que cela a quelque chose à voir avec le shell ? Puis-je forcer bash (ou un autre shell à votre convenance) à écrire immédiatement la sortie qu'il récupère ? J'ai essayé de taper sync sur la ligne de commande mais cela n'aide pas. Merci pour votre aide.
  • # simple

    Posté par  . Évalué à 5.

    le printf sur le stdout de ton programme n'est pas affiché car reste en cache (comportement normal pour éviter de multiple accès disque).

    A l'endroit de ton programme ou tu souhaite que l'ecriture soit active tu rajoute fflush(stdout) ou fflush(NULL) si tu veut aussi que tous les flux de sortie de ton programme soit synchro (stderr et stdout)
    • [^] # Re: simple

      Posté par  (site web personnel) . Évalué à 6.

      pour éviter de mettre des fflush partout on peut même mettre le buffer de sortie à 0

      setbuf(stdout, (char *)NULL);
    • [^] # Re: simple

      Posté par  . Évalué à 1.

      Ça marche comme prévu, merci beaucoup ! Je pensais que le programme C ne pouvait pas être au courant de ce que je faisais avec la sortie une fois qu'il la passe au shell. Mais je devais me tromper.
      • [^] # Re: simple

        Posté par  . Évalué à 2.

        Il me semble que le flux stderr est synchro. par défaut. Perso. je préfère faire comme ça car je peux avoir des stdout très verbeux (et le cache est là pour améliorer les performances dans ce cas).
      • [^] # Re: simple

        Posté par  (site web personnel) . Évalué à 0.

        Mais il n'est pas au courant :)
    • [^] # Re: simple

      Posté par  . Évalué à 8.

      Attention, le comportement observé n'a rien avoir avec les buffer/page caches, c'est une histoire de bufferisation : avec la libc, il y a trois types de bufferisation :
      - _IONBF : pas de bufferisation, on appelle tout de suite l'appel système write
      - _IOLBF : bufferisation par ligne, on appelle write lorsqu'on rencontre '\n', utilisée par défaut lorsque le descripteur de fichier est lié à un tty (sauf stderr qui est _IONBF)
      - _IOFBF : bufferisation complète, on bufferise jusqu'à ce que le buffer soit plein, utilisé par défaut pour les fichiers, les pipes, etc

      Même sans bufferisation, une écriture via printf/fwrite n'entraine pas forcément un accès au disque, le noyau utilise le page cache pour des questions de performance. Pour forcer l'écriture sur disque (commit), il faut passer un un fflush pour flusher le buffer au niveau de la libc, mais aussi un fsync pour forcer un commit des données en cache.
      Entre autres choses, la bufferisation au niveau de la libc permet de réduire le nombre d'appels systèmes, qui coutent cher.

      La grosse différence c'est que tant qu'il y a des données bufferisées au niveau de la libc (FILE *), les modifications ne sont pas visibles par les autres processus. Par contre dès que write(2) est appelé, elles deviennent visibles.
  • # c'est normal il me semble

    Posté par  . Évalué à 4.

    1°) sync en ligne de commande, c'est pour synchroniser le cache disque avec le disque en lui meme (avant de retirer une clef usb par exemple)

    2°) il me semble que les sorties asynchrones que tu as sont liés à la maniere de faire tes printf et fprintf.

    De memoire il faut un retour à la ligne pour que ca le valide et que ca l'affiche "vraiment".
    sinon ca attend la fin du programme ou le prochain retour à la ligne.
    • [^] # Re: c'est normal il me semble

      Posté par  . Évalué à 2.

      C'est utile, je prends note, mais en l'occurrence il y avait bien des retours à la ligne à la fin de mes sorties.
    • [^] # Re: c'est normal il me semble

      Posté par  . Évalué à 2.

      Je corrige un peu pour le point 1: sync n’a rien à voir avec son problème, si on demande un accès à un fichier qui est en cache, ce sera bien le cache qui sera lu. Imagine s’il y a plusieurs version du fichier à un instant t sur le système, ce serait un sacré bordel. C’est juste que le système va être paresseux dans l’écriture sur disque des changements, mais en aucun cas il lira une zone disque non mise à jour.
  • # Pas besoin de tail

    Posté par  (site web personnel) . Évalué à 8.

    ./programme 2>&1 | tee log

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.