rico: PHP läuft in CGI-Mosus - wie CGI-Skripte in PHP ausführen?

Hallo,

bisher habe ich folgendermaßen ein CGI-Skript aus meinen PHP/HTML-Dateien ausgeführt:
<?php virtual ("cgi-bin/dcounter/showload.cgi?http://www.meinedomain.de/download/datei.zip"); ?>

Nach einem Serverwechsel klappt aber eben dies nicht mehr, und es gibt folgenden Fehler aus:
Fatal error: Call to undefined function: virtual() in /home/www/server/html/test.html on line 61

virtual() ist dem Server also unbekannt. Ich vermute, dies liegt daran, dass PHP auf dem Server im CGI-Modus ausgeführt wird. (Laut http://php.net/manual/de/function.virtual.php wird die Funktion wird nur unterstützt, wenn PHP als Apache-Modul installiert wurde).

Gibt es eine andere Möglichkeit, CGI in PHP einzubinden, wenn PHP im CGI-Modus läuft?

Im voraus danke für jede Idee!

  1. Hi,

    Gibt es eine andere Möglichkeit, CGI in PHP einzubinden, wenn PHP im CGI-Modus läuft?

    Wenn du das CGI-Script per HTTP aufrufen kannst, und allow_url_fopen auf on steht, könntest du bspw. file_get_contents o.ä. verwenden, um einen ähnlichen(!) Effekt zu erzielen.
    Ob du damit genau das selbe Ergebnis erreichen wirst, und wie sich das hinsichtlich der Laufzeit auswirkt, kommt auf die genaueren Umstände an.

    MfG ChrisB

    --
    “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
    1. Hallo,
      danke für die Antwort!
      Nach gut drei Stunden Suche und Herumprobierei habe ich allerdings zwei Minuten nach dem Abschicken meines Beitrages bereits noch eine andere Möglichkeit gefunden, die funktioniert und zumindest dem Anschein nach das gleiche Ergebnis liefert (auch von der Geschwindigkeit her):

      <? echo @join (@file ("http://www.meinedomain.de/cgi-bin/dcounter/showload.cgi?http://www.meinedomain.de/download/datei.zip"),"") ?>

      Ich bin was das angeht noch ziemlicher Anfänger, spricht etwas gegen obige Lösung?

      Gruß,
      rico

      1. Moin!

        <? echo @join (@file ("http://www.meinedomain.de/cgi-bin/dcounter/showload.cgi?http://www.meinedomain.de/download/datei.zip"),"") ?>
        Ich bin was das angeht noch ziemlicher Anfänger, spricht etwas gegen obige Lösung?

        Du liest eine Datei zeilenweise ein um diese Zeilen dann wieder zusammenzufügen. Baue auf und reise nieder ... so hast Du Arbeit immer wieder. Nur macht die hier Dein Server.

        Je nach Konfiguration kann

        file_get_contents

        oder curl Dein Freund sein.

        MFFG (Mit freundlich- friedfertigem Grinsen)

        fastix

        1. Vielen Dank euch allen dreien für eure Hilfe!

          Du liest eine Datei zeilenweise ein um diese Zeilen dann wieder zusammenzufügen. Baue auf und reise nieder ... so hast Du Arbeit immer wieder. Nur macht die hier Dein Server.

          Je nach Konfiguration kann

          file_get_contents

          Damit habe ich es nun auch gemacht:

          <? echo file_get_contents("http://www.meinedomain.de/cgi-bin/dcounter/showload.cgi?http://www.meinedomain.de/download/datei.zip") ?>

          Und es läuft ebensogut :)
          Danke nochmal!

      2. Hi,

        <? echo @join (@file ("http://www.meinedomain.de/cgi-bin/dcounter/showload.cgi?http://www.meinedomain.de/download/datei.zip"),"") ?>

        Ich bin was das angeht noch ziemlicher Anfänger, spricht etwas gegen obige Lösung?

        Damit wird die Ausgabe erst in einzelne Zeilen aufgesplittet, nur um sie dann wieder zusammenzusetzen - da kannst du besser gleich file_get_contents nehmen.

        MfG ChrisB

        --
        “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
      3. Hi,

        <? echo @join (@file ("http://www.meinedomain.de/cgi-bin/dcounter/showload.cgi?http://www.meinedomain.de/download/datei.zip"),"") ?>
        Ich bin was das angeht noch ziemlicher Anfänger, spricht etwas gegen obige Lösung?

        äh, ja. Einiges. Sie ist an Nutzlosigkeit schwer zu toppen.
        Sie holt mit file() eine HTTP-Ressource ab (Glück gehabt, du darfst also HTTP-Ressourcen über die File-Funktionen ansprechen), du hast sie dann in einem Array, jedes Arrayelement eine Zeile. Das ist besonders bei Ressourcen, die nicht textbasiert sind, ziemlich sinnfrei. Eventuell auftretende Fehlermeldungen werden unterdrückt.
        Dann klebt join() die grundlos gesplitteten Zeilen im Array wieder zu *einem* String zusammen, auch dabei unterdrückst du eventuelle Fehlermeldungen.
        Den resultierenden String gibst du schließlich mit echo aus.
        Außerdem verlässt du dich noch darauf, dass die Short Tags ("<?" anstatt "<?php") erlaubt sind.
        Und zu guter Letzt missbrauchst du noch Domainnamen für deine Beispiele, die tatsächlich vergeben sind, anstatt die Namen zu verwenden, die extra dafür vorgesehen sind.

        Letztendlich tut der ganze Kladderadatsch also dasselbe wie

        <?php readfile("http://www.example.org/cgi-bin/dcounter/showload.cgi?http://www.example.org/download/datei.zip"),"") ?>

        Und ich bin überzeugt, es ist auch nicht im Sinne der Erfinders, dass das CGI-Programm seinerseits wieder per HTTP auf eine Ressource zugreifen soll, die auf demselben Server liegt.

        So long,
         Martin

        --
        Fettflecke werden wieder wie neu, wenn man sie regelmäßig mit etwas Butter einschmiert.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Hallo,

          Und zu guter Letzt missbrauchst du noch Domainnamen für deine Beispiele, die tatsächlich vergeben sind, anstatt die Namen zu verwenden, die extra dafür vorgesehen sind.

          Mein Fehler, das wusste ich nicht und da habe ich auch nicht drüber nachgedacht - Beispiele mit "meinedomain.de" (oder in der Art) hatte ich einige gesehen und das dann einfach auch übernommen. Werde mir das für die Zukunft merken!

          Letztendlich tut der ganze Kladderadatsch also dasselbe wie

          <?php readfile("http://www.example.org/cgi-bin/dcounter/showload.cgi?http://www.example.org/download/datei.zip"),"") ?>

          Das klappt ebenfalls, damit habe ich jetzt sogar zwei Möglichkeiten (file_get_contents + readfile)

          Und ich bin überzeugt, es ist auch nicht im Sinne der Erfinders, dass das CGI-Programm seinerseits wieder per HTTP auf eine Ressource zugreifen soll, die auf demselben Server liegt.

          Das ganze ist ein wenig Bastelei, da bin ich mir bewusst. Mit relativem Link anstelle vollem HTTP-Link läuft es allerdings wieder nicht.

          1. Hi,

            Mein Fehler, das wusste ich nicht und da habe ich auch nicht drüber nachgedacht - Beispiele mit "meinedomain.de" (oder in der Art) hatte ich einige gesehen und das dann einfach auch übernommen. Werde mir das für die Zukunft merken!

            sehr gut. :-)
            Die mit Abstand am häufigsten "missbrauchte" Domain ist aber vermutlich die der Stiftung Warentest.

            <?php readfile("http://www.example.org/cgi-bin/dcounter/showload.cgi?http://www.example.org/download/datei.zip"),"") ?>
            Das klappt ebenfalls, damit habe ich jetzt sogar zwei Möglichkeiten (file_get_contents + readfile)

            Ja, und zwischen den beiden besteht ein kleiner, aber wichtiger Unterschied:
            file_get_contents() liest den kompletten Dateiinhalt und speichert ihn in einem String, daher braucht's noch das echo, um den String auszugeben. Das heißt aber auch, dass es mit dem Arbeitsspeicher eng werden kann, wenn man große Dateien verarbeitet.
            readfile() reicht den Inhalt dagegen nur durch (deshalb braucht's das echo nicht) und muss ihn nicht zwischenspeichern - oder wenn, dann immer nur in kleinen Häppchen.

            Und ich bin überzeugt, es ist auch nicht im Sinne der Erfinders, dass das CGI-Programm seinerseits wieder per HTTP auf eine Ressource zugreifen soll, die auf demselben Server liegt.
            Das ganze ist ein wenig Bastelei, da bin ich mir bewusst. Mit relativem Link anstelle vollem HTTP-Link läuft es allerdings wieder nicht.

            Die Schwierigkeit bei relativen Verweisen ist immer, den richtigen Bezugspunkt zu wissen. In diesem Fall ist der Bezugspunkt höchstwahrscheinlich das Verzeichnis, in dem das CGI-Programm ausgeführt wird. Wenn du von dort ausgehend adressierst, sollte es gehen. Nebenbei: Wenn das CGI per HTTP auf die gewünschte Zieldatei zugreift, dann kann mein Browser das auch direkt selbst, und du führst den Sinn eines indirekten Zugriffs ad absurdum.

            So long,
             Martin

            --
            Die späteren Ehen sind oft glücklicher als die erste, weil das natürliche Ende bereits absehbar ist.
              (George Bernhard Shaw)
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            1. Hi,

              Mit relativem Link anstelle vollem HTTP-Link läuft es allerdings wieder nicht.

              Die Schwierigkeit bei relativen Verweisen ist immer, den richtigen Bezugspunkt zu wissen. In diesem Fall ist der Bezugspunkt höchstwahrscheinlich das Verzeichnis, in dem das CGI-Programm ausgeführt wird. Wenn du von dort ausgehend adressierst, sollte es gehen.

              Wenn nicht über HTTP gegangen wird, dann lesen readfile/file_get_contents den *Code* des CGI-Scriptes ein, und nicht dessen Ausgabe.

              MfG ChrisB

              --
              “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
              1. Moin!

                Wenn nicht über HTTP gegangen wird, dann lesen readfile/file_get_contents den *Code* des CGI-Scriptes ein, und nicht dessen Ausgabe.

                Äh... halt mal. Du hast uns vorhin ein zip-File präsentiert.

                Die Lösung für ausführbaren Kram steht hier.

                MFFG (Mit freundlich- friedfertigem Grinsen)

                fastix

                1. Hi,

                  Wenn nicht über HTTP gegangen wird, dann lesen readfile/file_get_contents den *Code* des CGI-Scriptes ein, und nicht dessen Ausgabe.

                  Äh... halt mal. Du hast uns vorhin ein zip-File präsentiert.

                  Ich habe gar nichts präsentiert, und der OP ein CGI-Script, dem der Pfad eines ZIP-Files als Parameter im Query-String übergeben wird.

                  MfG ChrisB

                  --
                  “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
                  1. Moin!

                    Ich habe gar nichts präsentiert, und der OP ein CGI-Script, dem der Pfad eines ZIP-Files als Parameter im Query-String übergeben wird.

                    stimmt.

                    MFFG (Mit freundlich- friedfertigem Grinsen)

                    fastix

                2. Danke für die weiteren Erklärungen @Martin und @ChrisB!

                  Äh... halt mal. Du hast uns vorhin ein zip-File präsentiert.
                  Die Lösung für ausführbaren Kram steht hier.

                  Kurz zur Erläuterung - der "Link" sieht folgendermaßen aus:
                  http://www.example.org/cgi-bin/dcounter/showload.cgi?http://www.example.org/download/datei.zip
                  Dabei liefert die showload.cgi den Stand eines Zählers (Anzahl der Downloads für die Datei "http://www.example.org/download/datei.zip"), den eine andere CGI in einer Textdatei abgelegt hat.

                  Aber wie gesagt, die Lösungen mit z.B. readfile() funktionieren bereits zu meiner Zufriedenheit.

                  1. Aber wie gesagt, die Lösungen mit z.B. readfile() funktionieren bereits zu meiner Zufriedenheit.

                    Naja. Von hinten durch die Brust ins Auge – aber wenn so ein Stümperkram gefällt … :)

                  2. Moin!

                    Aber wie gesagt, die Lösungen mit z.B. readfile() funktionieren bereits zu meiner Zufriedenheit.

                    ... ist aber weit von einem "perfekt" entfernt, weil Du auf extreme Weise Ressource verschwendest.
                    Du bemühst den eigenen Webserver eine große Datei an sich selbst auszuliefern, die er dann an den Client sendet.

                    Das Zip-File ausliefern und den Zähler dafür um eins erhöhen kann auch PHP mit wenigen Zählern.

                    <?php  
                    $file='../download/datei.zip';  
                    countAndSendFile($file);  
                    exit;  
                      
                    function countAndSendFile($file) {  
                      /*  
                          Festellen des Dateityps,  
                          mime_content_type ist veraltet...  
                      */  
                      if function_exists ('mime_content_type') {  
                         $mime_type=mime_content_type($file);  
                      } else {  
                        $fileInfo = new finfo(FILEINFO_MIME,'/usr/share/file/magic');  
                        $mime_type = $fileInfo->buffer(file_get_contents($file));  
                      }  
                      
                      /*  
                         Datei lesen und senden  
                      */  
                      header('Content-Type: '.$mime_type);  
                      readfile($file);  
                      
                      /*  
                         Counter schreiben.  
                      */  
                      
                      $counterFile=$file.'_counter.txt';  
                      $counter=file_get_contents($counterFile);  
                      $counter++;  
                      file_put_contents($counterFile, $counter);  
                      return true;  
                    ?>
                    

                    MFFG (Mit freundlich- friedfertigem Grinsen)

                    fastix

              2. Hallo,

                Die Schwierigkeit bei relativen Verweisen ist immer, den richtigen Bezugspunkt zu wissen. In diesem Fall ist der Bezugspunkt höchstwahrscheinlich das Verzeichnis, in dem das CGI-Programm ausgeführt wird. Wenn du von dort ausgehend adressierst, sollte es gehen.
                Wenn nicht über HTTP gegangen wird, dann lesen readfile/file_get_contents den *Code* des CGI-Scriptes ein, und nicht dessen Ausgabe.

                ja, natürlich. Ich sprach ja auch nicht davon, das CGI-Programm unter Umgehung von HTTP zu lesen, sondern habe empfohlen, dass das CGI-Programm unter Umgehung von HTTP die zip-Datei direkt lesen soll, die es dann als Antwort liefert.
                Aber ich gebe zu, bei so einem zweifach-dreifach-indirekten Zugriff kann man schon mal den Überblick verlieren.

                Ciao,
                 Martin

                --
                F: Was ist ekliger als ein angebissener Apfel mit einem Wurm drin?
                A: Ein angebissener Apfel mit einem halben Wurm.
                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
  2. Moin!

    Kommt drauf an, was Du willst. Es gibt da sehr viele Möglichkeiten.

    system()
    exec()
    Backticks
    passthru()
    ...

    MFFG (Mit freundlich- friedfertigem Grinsen)

    fastix

  3. virtual() ist dem Server also unbekannt. Ich vermute, dies liegt daran, dass PHP auf dem Server im CGI-Modus ausgeführt wird.

    virtual() startet im Prinzip eine HTTP-Anfrage, allerdings wird diese direkt in den Apache-Server eingeschleust, ohne Umweg über die Netzwerkschnittstelle. Auf diese Interna hast du keinen Zugriff, wenn PHP via CGI ausgeführt wird; hinter der CGI-Schnittstelle verbirgt sich (fast) nichts anderes als das Ausführen eines beliebigen externen Programms – und das ist dann auch deine Lösung:

    Gibt es eine andere Möglichkeit, CGI in PHP einzubinden, wenn PHP im CGI-Modus läuft?

    Rufe das Skript einfach so auf, wie es der Webserver auch macht: Als Programm. Die nötigen Funktionen findest du unter http://de.php.net/manual/en/book.exec.php, exec() und shell_exec() müssten deine Freunde sein.

    Beachte, dass die Ausgabe des Skriptes mit dem HTTP-Kopf beginnt (mindestens die Zeile Content-Type, eventuell mehr), die eigentlichen Daten erscheinen nach der ersten Leerzeile.