Problem beim Umleiten einer C-Programmausgabe in bash

9

Ich habe ein Programm in C programmiert, das mit printf Nachrichten an das stdout sendet und ich habe Probleme, die Ausgabe in eine Datei umzuleiten (läuft von bash).

Ich habe es versucht:

%Vor%

In jedem Fall wird die Datei program.out erstellt, aber sie bleibt leer. Nach dem Ende der Ausführung ist die Dateigröße 0.

Wenn ich die Umleitung beim Ausführen des Programms weglasse:

%Vor%

Dann werden alle Nachrichten, die mit printf an stdout gesendet werden, im Terminal angezeigt.

Ich habe andere C-Programme, für die ich die Ausgabe auf diese Weise nicht umleiten kann. Hat es mit dem Programm selbst zu tun? mit dem Argument vorbei? Wo sollte nach dem Problem suchen?

Einige Details zum C-Programm:

  • Es liest nichts von stdin
  • Es verwendet BSD Internet Domain Sockets
  • Es verwendet POSIX-Threads
  • Er weist eine spezielle Handler-Funktion für das SIGINT-Signal unter Verwendung von sigaction
  • zu
  • Es sendet viele neue Zeilen an stdout (für diejenigen von euch, die denken, ich sollte flush)

Irgendein Code:

%Vor%     
mmutilva 01.02.2009, 00:27
quelle

5 Antworten

14

Spülen nach Zeilenumbrüchen funktioniert nur beim Drucken auf einem Terminal, aber nicht unbedingt beim Drucken in eine Datei. Eine schnelle Google-Suche ergab diese Seite mit weiteren Informationen: Ссылка

Siehe Abschnitt "Standard-Pufferungsmodi".

Sie müssen eventuell einige Aufrufe für fflush (stdout) hinzufügen.

Sie können die Puffergröße und das Verhalten auch mithilfe von setvbuf festlegen.

    
gclj5 01.02.2009, 00:34
quelle
6
___ qstntxt ___

Ich habe ein Programm in C programmiert, das mit printf Nachrichten an das stdout sendet und ich habe Probleme, die Ausgabe in eine Datei umzuleiten (läuft von bash).

Ich habe es versucht:

%Vor%

In jedem Fall wird die Datei program.out erstellt, aber sie bleibt leer. Nach dem Ende der Ausführung ist die Dateigröße 0.

Wenn ich die Umleitung beim Ausführen des Programms weglasse:

%Vor%

Dann werden alle Nachrichten, die mit printf an stdout gesendet werden, im Terminal angezeigt.

Ich habe andere C-Programme, für die ich die Ausgabe auf diese Weise nicht umleiten kann. Hat es mit dem Programm selbst zu tun? mit dem Argument vorbei? Wo sollte nach dem Problem suchen?

Einige Details zum C-Programm:

  • Es liest nichts von stdin
  • Es verwendet BSD Internet Domain Sockets
  • Es verwendet POSIX-Threads
  • Er weist eine spezielle Handler-Funktion für das SIGINT-Signal unter Verwendung von sigaction
  • zu
  • Es sendet viele neue Zeilen an stdout (für diejenigen von euch, die denken, ich sollte flush)

Irgendein Code:

%Vor%     
___ qstnhdr ___ Problem beim Umleiten einer C-Programmausgabe in bash ___ answer500259 ___

Vorschläge:

  1. Leiten Sie stderr ebenfalls in eine Datei um.
  2. Probieren Sie tail -f Ihre Ausgabedatei (en).
  3. Öffnen Sie eine Datei und fprintf Ihre Protokollierung (um herauszufinden, was los ist).
  4. Suchen Sie nach manuellem Schließen / Duplizieren / Verteilen von std * FILE-Handles oder 1-3 Dateideskriptoren.
  5. Reduzieren Sie die Komplexität; Schneiden Sie große Teile der Funktionalität aus, bis printfs funktioniert. Dann lies sie, bis sie wieder bricht. Fahren Sie fort, bis Sie den Täter-Code identifiziert haben.
___ tag123c ___ C ist eine universelle Computerprogrammiersprache, die für Betriebssysteme, Bibliotheken, Spiele und andere Hochleistungsanwendungen verwendet wird. Dieses Tag sollte bei allgemeinen Fragen zur C-Sprache verwendet werden, wie in der Norm ISO 9899: 2011 definiert. Fügen Sie ggf. ein versionsspezifisches Tag wie c99 oder c90 für Fragen zu älteren Sprachstandards hinzu. C unterscheidet sich von C ++ und es sollte nicht mit dem C ++ - Tag kombiniert werden, wenn ein rationaler Grund fehlt. ___ tag123linux ___ LINUX FRAGEN MÜSSEN PROGRAMMIEREN VERWANDT SEIN. Verwenden Sie dieses Tag nur, wenn sich Ihre Frage auf das Programmieren mit Linux-APIs oder das Linux-spezifische Verhalten bezieht, nicht nur, weil Sie Ihren Code unter Linux ausführen. Wenn Sie Linux-Unterstützung benötigen, können Sie https://unix.stackexchange.com oder https://askubuntu.com ausprobieren ___ tag123bash ___ Für Fragen zu Skripten, die für die Bash-Befehlsshell geschrieben wurden. Für Shell-Skripte mit Fehlern, überprüfen Sie diese bitte mit dem Shellcheck-Programm (oder im web-Shellcheck-Server unter https://shellcheck.net), bevor Sie hier posten. Fragen zur interaktiven Nutzung von Bash sind bei Super Usern eher Thema als bei Stack Overflow. ___ answer1097787 ___

Nur für das Protokoll, in Perl würden Sie verwenden:

%Vor%     
___ answer499910 ___

Wurde das Programm beendet, nachdem Sie den Inhalt der umgeleiteten Datei überprüft haben? Wenn es noch läuft, wird Ihre Ausgabe möglicherweise noch irgendwo in der Kette zwischengespeichert, so dass Sie es nicht in der Datei sehen.

Abgesehen davon und den anderen bisher gegebenen Antworten denke ich, dass es Zeit ist, ein repräsentatives Beispiel für den Problemcode zu zeigen. Es gibt zu viele esoterische Möglichkeiten.

BEARBEITEN

Wenn Sie nach dem Aussehen des Beispielcodes relativ wenig drucken, werden Sie im Ausgabepuffer gefangen. Spülen Sie nach jedem Schreiben, um sicherzustellen, dass es auf die Festplatte gegangen ist. Normalerweise können Sie unbeschriebene Daten im Umfang von bis zu einer Seitengröße haben.

Wenn kein Flush vorliegt, können Sie nur sicher sein, dass alles auf der Festplatte ist, wenn das Programm beendet wird. Selbst ein Thread-Terminierung wird es nicht tun, da Ausgabe-Puffer wie diese sind nicht per-Thread, sie sind pro-Prozess.

    
___ tag123printf ___ 'printf' ist eine gebräuchliche Funktion für formatierte Ausgaben. C und viele andere Sprachen haben eine ganze Familie verwandter Funktionen. Verwenden Sie dieses Tag nur, wenn sich die Frage direkt auf 'printf' oder verwandte Funktionen bezieht. ___ tag123redirect ___ Eine Antwort eines Webservers, die den Benutzeragenten auffordert, den Antworttext nicht anzuzeigen, sondern stattdessen eine andere Ressource anzufordern. ___ answer499895 ___

Spülen nach Zeilenumbrüchen funktioniert nur beim Drucken auf einem Terminal, aber nicht unbedingt beim Drucken in eine Datei. Eine schnelle Google-Suche ergab diese Seite mit weiteren Informationen: Ссылка

Siehe Abschnitt "Standard-Pufferungsmodi".

Sie müssen eventuell einige Aufrufe für fflush (stdout) hinzufügen.

Sie können die Puffergröße und das Verhalten auch mithilfe von setvbuf festlegen.

    
___ antwort500183 ___

Das Leeren der Puffer wird normalerweise von der Funktion exit() gehandhabt, die normalerweise implizit von einem return von main () aufgerufen wird. Sie beenden Ihr Programm, indem Sie SIGINT anheben, und anscheinend löscht der Standard-SIGINT-Handler die Puffer nicht.

Sehen Sie sich diesen Artikel an: Anwenden von Entwurfsmustern zur Vereinfachung der Signalverarbeitung . Der Artikel ist hauptsächlich C ++, aber es gibt ein nützliches C-Beispiel im zweiten Abschnitt, das zeigt, wie man mit SIGINT das Programm elegant beendet.

Warum unterscheidet sich das Verhalten eines Terminals von einer Datei? Werfen Sie einen Blick auf Stevens Fortgeschrittene Programmierung in der UNIX-Umgebung Abschnitt 5.4 über Pufferung. Er sagt das:

Die meisten Implementierungen verwenden standardmäßig die folgenden Pufferungsarten. Der Standardfehler ist immer ungepuffert. Alle anderen Datenströme werden zwischengespeichert, wenn sie sich auf ein Endgerät beziehen. Ansonsten sind sie vollständig gepuffert. Die vier Plattformen, die in diesem Buch behandelt werden, folgen diesen Konventionen für die Standard-I / O-Pufferung: Standardfehler sind ungepuffert, Datenströme, die für Endgeräte offen sind, werden zwischengespeichert und alle anderen Datenströme werden vollständig gepuffert.
    
___
user10892 01.02.2009 04:09
quelle
3

Wurde das Programm beendet, nachdem Sie den Inhalt der umgeleiteten Datei überprüft haben? Wenn es noch läuft, wird Ihre Ausgabe möglicherweise noch irgendwo in der Kette zwischengespeichert, so dass Sie es nicht in der Datei sehen.

Abgesehen davon und den anderen bisher gegebenen Antworten denke ich, dass es Zeit ist, ein repräsentatives Beispiel für den Problemcode zu zeigen. Es gibt zu viele esoterische Möglichkeiten.

BEARBEITEN

Wenn Sie nach dem Aussehen des Beispielcodes relativ wenig drucken, werden Sie im Ausgabepuffer gefangen. Spülen Sie nach jedem Schreiben, um sicherzustellen, dass es auf die Festplatte gegangen ist. Normalerweise können Sie unbeschriebene Daten im Umfang von bis zu einer Seitengröße haben.

Wenn kein Flush vorliegt, können Sie nur sicher sein, dass alles auf der Festplatte ist, wenn das Programm beendet wird. Selbst ein Thread-Terminierung wird es nicht tun, da Ausgabe-Puffer wie diese sind nicht per-Thread, sie sind pro-Prozess.

    
womble 01.02.2009 00:40
quelle
0

Vorschläge:

  1. Leiten Sie stderr ebenfalls in eine Datei um.
  2. Probieren Sie tail -f Ihre Ausgabedatei (en).
  3. Öffnen Sie eine Datei und fprintf Ihre Protokollierung (um herauszufinden, was los ist).
  4. Suchen Sie nach manuellem Schließen / Duplizieren / Verteilen von std * FILE-Handles oder 1-3 Dateideskriptoren.
  5. Reduzieren Sie die Komplexität; Schneiden Sie große Teile der Funktionalität aus, bis printfs funktioniert. Dann lies sie, bis sie wieder bricht. Fahren Sie fort, bis Sie den Täter-Code identifiziert haben.
HUAGHAGUAH 01.02.2009 05:13
quelle
0

Nur für das Protokoll, in Perl würden Sie verwenden:

%Vor%     
ssn 08.07.2009 12:35
quelle

Tags und Links