In Datei schreiben



  • Guten Abend zusammen,

    ich habe innerhalb eines größeren Programms eine Funktion die ein Logfile erstellen soll. Die Funktion arbeitet aber sporadisch nicht richtig. D.h. manchmal wird ein logfile erstellt und manchmal nicht. Mir ist noch kein Zusammenhang aufgefallen wann es funktioniert und wann nicht. Der Rest des Programms arbeitet einwandfrei.

    Hier die Funktion:

    void write_to_logfile(char *command, char *direction)
    {
      time_t rawtime;
      struct tm * timeinfo;
      time ( &rawtime );
      timeinfo = localtime ( &rawtime );
    
      logfile = fopen ("./logfile","a+");
    
      fseek (logfile, 0, SEEK_END);
      fprintf (logfile, "%.24s: %.2s [%-30.30s]\n",asctime (timeinfo), direction, command);
      fclose (logfile);
    }
    

    Ich arbeite auf Ubuntu mit QTCreator (QT4.5, g++ 4.3.3). Der Compiler liefert keine Fehler/Warnungen aus dieser Funktion.

    Ich bin leider nicht wirklich fit in C/C++ und mit meinem Latein am Ende.

    Vielen Dank schonmal für eure Hilfe!

    Vg
    Mathias



  • Arbeitest du mit threads? Vielleicht rufst du die Funktion 2x parallel auf und der zweite Aufruf kann die Datei nicht öffnen, da sie schon geöffnet ist.



  • ich habe von threads überhaupt keine ahnung, von daher lass ich lieber die Finger davon...

    aber das Problem geht in die Richtung, denn wenn ich die Datei komplett lösche wird sie IMMER neu erstellt und ein schönes log geschrieben. Probleme gibt es nur wenn die Datei bereits vorhanden ist und neue Zeilen angehängt werden müssen. Kann es sein, dass dieses fclose nicht immer korrekt ausgeführt wird? Gibt es dafür eine alternative?



  • Dir sind die open-Modi bekannt?
    Warum öffnest du "a+", also append UND READ, wenn du nur schreibst? [*]
    Außerdem ist ein fseek total unnötig, da mit "a" sowieso immer am Ende angehangen wird. [**]

    [*] http://www.cplusplus.com/reference/clibrary/cstdio/fopen/
    [**] http://www.cplusplus.com/reference/clibrary/cstdio/fseek/



  • Danke,

    zu dem "a+": stimmt, ein "a" müsste eigentlich reichen...

    zu dem fseek: ich hatte das Problem, dass die neuen Zeilen immer vorne angehängt wurden. ich werde das ohne fseek testen...

    Jetzt habe ich gerade versucht die Anwendung auf einem anderen Rechner laufen zu lassen: hier wird gar kein logfile erstellt. Es handelt sich um einen diskless Rechner mit Gentoo. Die Anwendung liegt allerdings im home-Verzeichnis, da sollte ich alle nötigen Berechtigungen haben...

    UPDATE: Also mit absoluten Pfaden (/home/xxx/Desktop/logfile statt ./logfile) scheint alles zu funktionieren. Ich werde aber nochmal alles genauer testen!



  • Gut, dann wäre interessant, wie du das Programm aufrufst.
    Schreib am besten irgendwo nach tmp, wo alle Schreibrecht haben, in ne Datei den Rückgabewert von get_current_dir_path() (->#include <unistd.h>)
    Denn was ich mir vorstellen kann, dass dein Arbeitsverzeichnis nicht immer das home-dir ist. Denn du öffnest die Datei als "./logfile", und dein relativer Pfad ist vom aktuellen Arbeitsverzeichnis abhängig.
    Klappt die Sache denn wenn du da einen absoluten Pfad einträgst?



  • lol, das war wohl gedankenübertragung, ich werde es nachher wie beschrieben testen. dank dir!



  • Außerdem solltest du auf Fehler von man: fopen(3) prüfen

    logfile = fopen ("./logfile","a");
    if(!logfile) {
      perror("logfile: fopen");
    }
    

    man: perror(3) wertet a man: errno aus.



  • Ach ja, evtl. willst du ja in ein spezifisches Verzeichnis in $HOME loggen.
    Das kannst du dir zusammenbasteln mit getenv("HOME"), ebenfalls aus unistd.h.



  • Zum Testen lieber mal einen absoluten Pfad angeben. Und dann gleich mal strace -e open ./deinprogramm .



  • Wozu getenv, wenn ~/ bereits aufs homedir zeigt? 😉



  • Keine Ahnung, wie der Smiley gemeint ist, aber bevor es hier zu Missverständnissen kommt: ~ wird erst von der Shell expandiert, dh. das kannst Du nicht einfach so als Pfadangabe in Deinen Sourcen verwenden.



  • ok, erstmal danke für die vielen antworten:

    Mit absoluten Pfaden läuft alles perfekt...

    Also ist es scheinbar so, dass ich mich nicht immer im Working Directory befinde und der Aufruf mit ./logfile das file irgendwo hinspeichert.

    Ich will das logfile aber immer in denselben Ordner speichern in dem die Anwendung selbst ist. Dies ist aber nicht immer das Home-Dir und offensichtlich nicht immer das Working-Dir. Gibt es eine Möglichkeit den Speicherort des eigentlichen Programms abzufragen?

    Vg
    Mat

    PS: Wenn ich "strace -e open ./meinprogramm" mache, kann ich ja alle system calls sehen. Ein kleiner Ausschnitt ist folgender:

    open("/usr/share/icons/DMZ-White/cursors/xterm", O_RDONLY) = 18
    open("./logfile", O_RDWR|O_CREAT|O_APPEND, 0666) = 18
    

    heisst das, dass mein logfile in dem Fall nach "/usr/share/..." gespeichert wird?



  • Also, dein file-executable kannst du dir auch herzaubern.

    1. mit getpid() die aktuelle Prozess-ID holen
    2. /proc/<pid>/exe ist ein symlink auf deine gestartete exe
    3. Mit readlink das link-target finden
      getpid() und readlink() gibt es ebenfalls über unistd.h

    Jetzt nur noch den Teil hinter dem letzten "/" wegschnippseln, und du hast deinen Pfad, in dem die exe liegt. Mit access() kannst du auch prüfen, ob du Schreibrechte hast.

    Ich würde aber eher schauen, dass ich in ein festes DIR mitlogge. verschiebst du mal dein binary, liegt auch das Logfile wo anders.



  • matze251284 schrieb:

    open("/usr/share/icons/DMZ-White/cursors/xterm", O_RDONLY) = 18
    open("./logfile", O_RDWR|O_CREAT|O_APPEND, 0666) = 18
    

    heisst das, dass mein logfile in dem Fall nach "/usr/share/..." gespeichert wird?

    Nein, das heißt, dass zuerst /usr/share/icons/DMZ-White/cursors/xterm Readonly geöffnet wird.

    Schau Dir mal man: getwd bzw. man: getcwd an (ich vergesse immer, welches welches ist) und lass Dir das ausgeben.

    no-c hat recht; nimm am besten irgendein Argument für das Logging-Dir an.



  • Vielen Dank für eure Antworten. Sorry für die verspätete Antwort, aber ich bin die letzten Tage nicht mehr dazu gekommen an dem Code weiterzuarbeiten. Ich werde eure Anregungen die nächsten Tage einarbeiten. Vielen Dank nochmal!


Anmelden zum Antworten