2017-07-10 3 views
1

J'essaie de rediriger à la fois stdout et stderr vers un seul fichier avec un programme C.Rediriger à la fois stdout et stderr vers un seul fichier et conserver l'ordre des messages

Voici mon code:

#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 

int redirectOutputs(); 

int main() 
{ 
    redirectOutputs(); 
    printf("OUT : test\n"); 
    perror("ERR : test"); 
    printf("OUT : test 2\n"); 


    int t = 23; 
    printf("OUT : again\n"); 
    perror("ERR : again"); 

} 

int redirectOutputs() 
{ 
    int log = open("err.log", O_RDWR|O_CREAT|O_APPEND, 0600); 
    if (log == -1) 
    { 
     perror("opening err.log"); 
     return -1; 
    } 
    close(STDIN_FILENO); 
    close(STDOUT_FILENO); 
    close(STDERR_FILENO); 
    dup2(log, STDOUT_FILENO); 
    dup2(log, STDERR_FILENO); 
    close(log); 
} 

Et le fichier de sortie:

ERR : test: Success 
ERR : again: Success 
OUT : test 
OUT : test 2 
OUT : again 

Ils sont tous deux redirigés bien, mais il semble que le tout stderr est écrit, puis le tout stdout. Je voudrais garder l'ordre des messages dans le fichier. je devrais avoir le fichier suivant:

OUT : test 
ERR : test: Success 
OUT : test 2 
OUT : again 
ERR : again: Success 

Savez-vous quel est le problème dans mon code?

+1

Votre sortie est-elle tamponnée? Essayez d'appeler 'fflush()' –

Répondre

4

Le problème est que la production par stdout est tamponnée tandis que stderr est non tamponnée.

Soit vous avez à faire stdout unbuffered comme stderr, ou faire stderr tamponnés comme stdout. Vous définissez la mise en mémoire tampon et le mode en utilisant setvbuf. Vous pouvez également appeler fflush sur stdout après chaque sortie.

+0

Il ya une idée intéressante, que je ne suis pas en mesure de tester pour le moment. Est-ce que '2> & 1' fera l'affaire comme OP veut? – iehrlich

+1

@iehrlich Oui, avoir la redirection du shell 'stderr' vers' stdout' devrait fonctionner correctement, et aussi supprimer une certaine charge sur le programmeur puisqu'aucune redirection programmatique n'est nécessaire. –

+0

Merci pour votre aide, c'était le problème;) – Arkaik

2

Votre problème est mise en mémoire tampon. La solution la plus simple consiste à appeler fflush() après chaque sortie. Vous pouvez bien sûr définir explicitement la mise en mémoire tampon pour ligne tamponnée avec setvbuf().


Cela dit, il serait probablement une meilleure idée d'avoir une interface d'enregistrement explicite qui attire tout le cas échéant stderr et stdout ainsi. Et une dernière remarque, certains de vos appels close() sont redondants, dup2() ferme automatiquement le nouveau fd avant la duplication.

+0

Merci pour votre aide, je vais probablement utiliser une macro de journal qui va vider après avoir écrit sur stdout – Arkaik