Daten über Pipe am Childprozess in Empfang nehmen

Dieses Thema im Forum "C/C++" wurde erstellt von pingu12, 12.08.2007.

  1. #1 pingu12, 12.08.2007
    pingu12

    pingu12 Jungspund

    Dabei seit:
    22.06.2005
    Beiträge:
    13
    Zustimmungen:
    0
    Hallo,

    Habe mir gerade eine kurze Einführung nach C++ durchgelesen und gemerkt, dass ich aus Zeitgründen auf das eigenständige Lösen dieses Problems erstmal verzichten muss.

    Ich möchte aus dem lighttpd (webserver) die accesslog-daten nicht in eine Datei schreiben, sondern in einem eigenen kleinen c++Prozess abfangen und verarbeiten. Letzteres sollte ich kurzfristig hinkriegen, das Abfangen allerdings macht mir noch Probleme.

    Hier ein Auszug aus der mod_accesslog des lighttpd der meines Erachtens für den Start des Childs (also meinem Prozess) verantwortlich ist:

    (Im Angang befindet sich der komplette Code)

    Code:
    #ifdef HAVE_FORK
    			/* create write pipe and spawn process */
    
    			int to_log_fds[2];
    			pid_t pid;
    
    			if (pipe(to_log_fds)) {
    				log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
    				return HANDLER_ERROR;
    			}
    
    			/* fork, execve */
    			switch (pid = fork()) {
    			case 0:
    				/* child */
    
    				close(STDIN_FILENO);
    				dup2(to_log_fds[0], STDIN_FILENO);
    				close(to_log_fds[0]);
    				/* not needed */
    				close(to_log_fds[1]);
    

    Ich wäre sehr dankbar wenn mir jemand kurz z.B. mit einem Beispielcode erklärt wie ich nun in meinem Child-Prozess an die gewünschten Daten komme.

    Gruß
    Pingu
     

    Anhänge:

  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. tr0nix

    tr0nix der-mit-dem-tux-tanzt

    Dabei seit:
    11.07.2003
    Beiträge:
    1.585
    Zustimmungen:
    0
    Ort:
    Schweiz, Opfikon/Glattbrugg
    Mach doch eine FIFO-Datei, lass den Webserver reinschreiben und dein Tool davon lesen? Könnte so funktionieren.

    Gruess
    Joel
     
  4. #3 der_Kay, 12.08.2007
    der_Kay

    der_Kay Doppel-As

    Dabei seit:
    28.02.2006
    Beiträge:
    140
    Zustimmungen:
    0
    Tut es auch. Gerade probiert. ;)

    mkfifo -m 666 access.log.pipe

    und accesslog.filename = "/<path>/access.log.pipe". Der Rest mit open() und read() aus <unistd.h> bzw. <fcntl.h>
     
  5. #4 pingu12, 12.08.2007
    pingu12

    pingu12 Jungspund

    Dabei seit:
    22.06.2005
    Beiträge:
    13
    Zustimmungen:
    0
    Tja, danke tr0nix und der_Kay, dass ihr euch meinem Problem angenommen habt ..

    .. ich bin mir jedoch noch nicht sicher ob ich jetzt weiter bin oder nicht da ich mit der fifo-Datei wenn man sie denn überhaupt als solche bezeichnen darf, wenig vertraut bin.

    Ist es denn sinnvoll das Problem über die fifo zu lösen statt der "normalen" pipe wie sie z.B. logprozesse wie cronolog benutzen ?
     
  6. #5 der_Kay, 12.08.2007
    der_Kay

    der_Kay Doppel-As

    Dabei seit:
    28.02.2006
    Beiträge:
    140
    Zustimmungen:
    0
    Eine FIFO ist eine "normale" pipe, eine sog. "named pipe". Das, was Du vorhast, ist genau das, wofür named pipes gemacht sind.

    Darum: Nur zu! :)
     
  7. #6 pingu12, 13.08.2007
    Zuletzt bearbeitet: 13.08.2007
    pingu12

    pingu12 Jungspund

    Dabei seit:
    22.06.2005
    Beiträge:
    13
    Zustimmungen:
    0
    Habe es mal versucht, erhalte jedoch am Ende der ausgelesenen Zeile ein \n gefolgt mit 3-4 Random-Zeichen. Woran mag das liegen?`

    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <cstdlib>
    #include <memory>
    #include <typeinfo>
    
    int main()
    {
      int fd_fifo;
      char buf[200];
    
      if((fd_fifo=open("/home/logauswertung/c/fifo99", O_RDWR)) == - 1)
        {
          fprintf(stderr, "Can't open file.\n");
          exit (0);
        }
    
      int index;
    
      if(read(fd_fifo, &buf, sizeof(buf)) == -1)
        fprintf(stderr, "Can't read from FIFO.\n");
      else
        printf("%s");
    
      return 0;
    }
    
     
  8. #7 pingu12, 13.08.2007
    Zuletzt bearbeitet: 13.08.2007
    pingu12

    pingu12 Jungspund

    Dabei seit:
    22.06.2005
    Beiträge:
    13
    Zustimmungen:
    0
    Da sich mir bei der Lösung mit der Fifo keine Vorteile in Performance, Sicherheit oder Schwierigkeit der Realisierung aufzeigen werde ich den Ansatz jetzt nicht weiter verfolgen. Eine Pipe zum Childprozess ist denke ich nicht schwieriger zu realisieren, hat aber den Vorteil, dass der Prozess vom lighttpd gestartet und im Problemfall auch neugestartet werden kann. Scheint mir nicht schwieriger zu sein und da ich ohnehin bei 0 anfange..

    Sollte ich mich in einem der Punkte irren bitte ich darum mich zu korrigieren, da ich für die paar Zeilen die 90% hier in 2 Minuten lauffähig machen den ganzen Tag bastel.
     
  9. tr0nix

    tr0nix der-mit-dem-tux-tanzt

    Dabei seit:
    11.07.2003
    Beiträge:
    1.585
    Zustimmungen:
    0
    Ort:
    Schweiz, Opfikon/Glattbrugg
    Ich glaube es liegt am printf. "\n" ist ja eigentlich newline aber wird nicht immer als Terminalsignal so Interpretiert. Wenn du es mit "normaler" Pipe irgendwie hinkriegst kannst du das natürlich auch gerne probieren, ich denke jedoch einen Prozess immer wieder zu spawnen wegen jeder einzelnen Zeile die reinkommt ist suboptimal.
     
  10. #9 der_Kay, 13.08.2007
    Zuletzt bearbeitet: 13.08.2007
    der_Kay

    der_Kay Doppel-As

    Dabei seit:
    28.02.2006
    Beiträge:
    140
    Zustimmungen:
    0
    Das flag "O_RDWR" ist für eine "FIFO" "verboten", siehe
    http://www.opengroup.org/onlinepubs/000095399/functions/open.html

    Wenn Du unbedingt lighthttpd patchen willst, will ich Dich nicht abhalten. Nochmal: Eine "FIFO" ist eine pipe. Ein Prozess schreibt hinein, ein anderer liest daraus (und öffnet sie dementsprechend O_RDONLY).

    "Sicherheit" erreichst Du über die Datei-Rechtemaske.

    Ich verstehe nicht, wo für Dich das Problem liegt.
     
  11. #10 pingu12, 13.08.2007
    Zuletzt bearbeitet: 13.08.2007
    pingu12

    pingu12 Jungspund

    Dabei seit:
    22.06.2005
    Beiträge:
    13
    Zustimmungen:
    0
    @tronix: Bei der Ausgabe ist doch gar kein \n enthalten. Das kommt nur in den Fehlermeldungen vor. Und der Prozess wird auch nur einmal von lighttpd gestartet.

    @der_Kay: Es ist nicht nötig den lighttpd zu patchen, mod_accesslog gibt die Möglichkeit einen Prozess zu spawnen statt die Logs in eine Datei zu schreiben.

    RD_ONLY konnte das Problem mit den Randomzeichen nicht lösen. Es ist nach wie vor so, dass ich meinen Prozess starte und sobald ich dann einen Logeintrag durch Seitenaufruf erzeuge kommt eine Logzeile und in der neuen Zeile dann jene Randomzeichen.
     
  12. #11 der_Kay, 13.08.2007
    Zuletzt bearbeitet: 13.08.2007
    der_Kay

    der_Kay Doppel-As

    Dabei seit:
    28.02.2006
    Beiträge:
    140
    Zustimmungen:
    0
    Du musst natürlich die mittels fread() gelesene Zeichenkette selbst terminieren! Die Nullbytes werden nicht von selbst generiert, denn fread() ist eine byte-orientierte Operation. Deshalb hast Du die Speichersuppe ab buf[nbytes_read] bis zum ersten folgenden '\0'im Output. ;)
    Code:
    int nbytes_read;
    // ...
    if(-1 != (nbytes_read=read(fd_fifo, &buf, sizeof(buf)-1))) {
        buf[nbytes_read]='\0';
       // ...
    } else { ...
    
    Du kannst auch ein memset(buf, 0, sizeof(buf)); vor fread() machen. Du wirst wahrscheinlich nicht drumherum kommen, einen Ringpuffer zu implementieren, der die gelesenen Teile nach einen Newline abschneidet und als verarbeitet zurückliefert.

    Um Deine ursprüngliche Frage von oben zu beantworten: Was es mit dem von Dir entdeckten (undokumentierten?) Feature bei fork() im Quellcode auf sich hat ist, dass wenn accesslog.filename mit '|' beginnt, mod_accesslog versucht, die folgenden Zeichen als als Shellkommando zu interpretieren, das "Kommando" zu starten versucht und die Logdaten in Filedescriptor 0 (STDIN) des Kindprozesses schreibt. Das ist aber sehr holprig, weil es mit lighthttpd mit der Prozessterminierung nicht so genau nimmt. Man kann z. B. durchaus

    accesslog.filename = "|tee > ./access-`date +%H%M%S`.txt"

    schreiben, aber z. B. accesslog.filename = "|gzip - > ./access-`date +%H%M%S`.gz" geht nicht, weil der GZip-Prozess beim Runterfahren flöten geht, bevor er die Daten auf die Platte schreiben kann.

    Du kannst Deinen Code (mit den kleinen Veränderungen) problemlos übernehmen, Du musst nur den Filedeskriptor austauschen. Aber: Implementieren musst das Gleiche, die Funktionsweise ist identisch, aber wenn Du eine named pipe ausliest, bekommt Dein Prozess immer das EOF mit, kann syncen und ordentlich runterfahren, während, wenn er als Kind von lighthttpd läuft, einfach an undefinierter Stelle weggeschossen wird. Zusammen mit den unverarbeiteten Logdaten.

    p.s.: Im Gegensatz zum '|'-Feature funktioniert das Beispiel mit GZip, wenn man die named pipe (accesslog.filename= "access.log.pipe") einsetzt, korrekt:

    gzip -9 - < access.log.pipe > access.gz

    access.gz enthält die komprimierten Logdaten, wenn lighthttp heruntergefahren wird.
     
  13. #12 Hello World, 14.08.2007
    Zuletzt bearbeitet: 14.08.2007
    Hello World

    Hello World Routinier

    Dabei seit:
    22.11.2006
    Beiträge:
    324
    Zustimmungen:
    0
    Was pingu12 hier zusammenschreibt, ist kein C++, sondern C. In C++ verwendet man nicht printf, fprintf, fread usw. usf., sondern die IOStream-Klassen. Damit kann man sich auch den ganzen Schwachsinn mit irgendwelchen Puffern usw. sparen. Man erzeugt einen ifstream, welcher von der FIFO liest. Dann liest man mit getline eine Zeile ein und fertig ist die Laube.
     
  14. tr0nix

    tr0nix der-mit-dem-tux-tanzt

    Dabei seit:
    11.07.2003
    Beiträge:
    1.585
    Zustimmungen:
    0
    Ort:
    Schweiz, Opfikon/Glattbrugg
    @hello world: äh ja, es spricht hier auch niemand von C++ und das Subforum heisst C/C++?
     
  15. Anzeige

    Vielleicht findest du HIER Antworten.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  16. #14 Hello World, 14.08.2007
    Zuletzt bearbeitet: 15.08.2007
    Hello World

    Hello World Routinier

    Dabei seit:
    22.11.2006
    Beiträge:
    324
    Zustimmungen:
    0
    Wer klugscheißen will, der sollte es wenigstens können.
    Sein eigentlicher Code ist aber weder ordentliches C noch C++. Schon bei den Includes ist er inkonsistent und bindet einerseits stdio.h und andererseits cstdlib ein. Ziemlich grausig, aber nicht weiter verwunderlich angesichts der Tatsache, dass C und C++ trotz der eklatanten Unterschiede ständig von irgendwelchen ahnungslosen Leuten in einen Topf geworfen werden...
     
  17. tr0nix

    tr0nix der-mit-dem-tux-tanzt

    Dabei seit:
    11.07.2003
    Beiträge:
    1.585
    Zustimmungen:
    0
    Ort:
    Schweiz, Opfikon/Glattbrugg
    Kann es sein, dass du leicht aggro bist? Wenn er von C++ redet aber in C coded ist das vielleicht einfach nur ein Typo. Jeder Anfänger includiert mal zuviel - und wenn der Anfänger C Grundknowhow hat und am Anfang eines C++ Buches steckt, mischt er auch gerne mal.

    Also: komm runter und erinnere dich an deine Anfänge.
     
Thema:

Daten über Pipe am Childprozess in Empfang nehmen

Die Seite wird geladen...

Daten über Pipe am Childprozess in Empfang nehmen - Ähnliche Themen

  1. Datensicherung von Ubuntu 12.04 Server über LAN auf Windows 8 Rechner

    Datensicherung von Ubuntu 12.04 Server über LAN auf Windows 8 Rechner: Samba4 ist auf ubuntu 12.04 Server als AD DC konfiguriert. Auf Samba 4 gibt es auch 8 Freigabeordner, die von mehreren Windowsbenutzern verwendet...
  2. Artikel: Daten über verschlüsseltes FTP senden

    Artikel: Daten über verschlüsseltes FTP senden: Das Protokoll FTP ist zum Übertragen von Dateien unschlagbar schnell, dafür aber völlig unverschlüsselt. FTP plus SSL/TLS schafft als FTPS sichere...
  3. Datensicherung über NFS bricht bei 4.2GB ab

    Datensicherung über NFS bricht bei 4.2GB ab: hi, ich weiss net genau, ob das hier reinpasst, aber ich dachte es is soviel platz also poste ichs mal hier. ich möchte eine datensicherung...
  4. PHP: Formular auf Checkbox prüfen und Formular-Daten an anderes Script übergeben

    PHP: Formular auf Checkbox prüfen und Formular-Daten an anderes Script übergeben: Hallo zusammen, ich stehe vor einem Verständnisproblem. Ich habe ein Script "A" indem ein Formular enthalten ist. In dem Formular soll der User...
  5. Wie war das nochmal mit dem Empfangen von Daten über bluetooth ?

    Wie war das nochmal mit dem Empfangen von Daten über bluetooth ?: Hi@all Ich habe besitze ein T280i von Sony Erricson und einen i.Tech Dynamic Limited Bluetooth Dongle. Soweit bin ich bisher gekommen:...