Leiten Sie stdout / stderr erneut in die Datei unter Unix C ++ um

Was ich machen will; was ich vorhabe zu tun

Leiten Sie stdout und stderr von c ++ aus zu einer oder mehreren Dateien um

Warum ich es brauche

Ich verwende eine externe, vorkompilierte Bibliothek von Drittanbietern, die eine lächerliche Menge an Ausgaben erzeugt, die ich in eine Protokolldatei umleiten möchte, um die Konsole sauber zu halten.

Bedingungen

Kompatibilität ist kein Problem, der Code kann nur auf Unix-Systemen ausgeführt werden. Die Umleitung sollte sich nicht nur auf das Drucken im C ++ - Stil (std :: cout << "Hallo Welt" << std :: endl), sondern auch auf das Drucken im C-Stil (printf ("Hallo Welt \ n") auswirken.

Was ich bisher ausprobiert habe

Ich habe einen halben Tag im Stackoverflow gestöbert und mehrere Antworten auf Personen mit ähnlichen Problemen gelesen. Mithilfe dieser Antworten konnte ich den folgenden Code zusammenstellen:

#include <stdio.h>
#include <iostream>
#include <fcntl.h>
#include "unistd.h"

const int stdoutfd(dup(fileno(stdout)));

int redirect_stdout(const char* fname){
  fflush(stdout);
  int newstdout = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP |     S_IROTH);
  dup2(newstdout, fileno(stdout));
  close(newstdout);
}

int restore_stdout(){
  fflush(stdout);
  dup2(stdoutfd, fileno(stdout));
  close(stdoutfd);
  return stdoutfd;
}

int main(){
  redirect_stdout("/dev/null");
  std::cout << "invisible 1" << std::endl;
  restore_stdout();
  std::cout << "visible 1" << std::endl;
  redirect_stdout("/dev/null");
  std::cout << "invisible 2" << std::endl;
  restore_stdout();
  std::cout << "visible 2" << std::endl;
  return 0;
}

Was ich erwarten würde zu sehen:

visible 1
visible 2

Was ich eigentlich sehe

visible 1

Das heißt, wenn Sie diesen Mechanismus zum ersten Mal verwenden, funktioniert er. Wenn Sie ihn jedoch erneut verwenden, funktioniert die Wiederherstellung der Ausgabe nicht. Kann mir jemand sagen, was ich ändern muss, damit der Mechanismus unendlich oft funktioniert?