Lars2019: externes Skript starten

Hallo,

ich bestreite gerade meine ersten Schritte mit apache2, perl und cgi, was eigentlich schon recht gut klappt. Heute wollte ich aus einem cgi-Skript (mu.pl) heraus ein Python-Skript starten, was nur klappt, wenn ich perl mu.pl nutze, aber nicht wenn ich <ip>/cgi-bin/mu.pl nutze.

mu.pl

#!/usr/bin/perl -w

system "python3 Generator.py";
print <<ENDE;
Content-type: text/html

<html>
  <head>
    <title>Test</title>
  </head>
  <body>
    Test
  </body>
</html>

ENDE

Wo steckt mein Fehler?

Vielen Dank, Lars

  1. Wo steckt mein Fehler?

    Wo er steckt weiß ich nicht. Aber im error.log des Webservers steht er drin.

    1. Danke für den Hinweis.

      Nun bleibt noch die Frage, wieso

      system "pdflatex Datei.tex";

      mit der Fehlermeldung

      malformed header from script 'mu.pl': Bad header: This is is pdfTeX, Version 3.1415,

      beendet wird.

      1. Fehlermeldung

        malformed header from script 'mu.pl': Bad header: This is is pdfTeX, Version 3.1415,

        Das ist einfach.

        Erstes Problem:

        malformed header from script 'mu.pl'

        CGI-Programme müssen erste eine Zeile mit dem Content-Type ausgeben, dann eine Leerzeile, dann den Payload.

        Aus irgendeinem Grund unterbleibt das. Demnach hat Dein obiges Perl-Skript den falschen aufbau:

        #!/usr/bin/perl -w
        
        print "Content-type: application/pdf\n\n";
        system "python3 Generator.py";
        

        Zweites Problem:

        "This is is pdfTeX, Version 3.1415,"

        Du musst untersuchen, warum diese Zeile überhaupt erscheint. Scheinbar hat jemand die Kanäle für <stdout> und <stderr> „verhauen“.

        Wenn Du PDF liefern willst, dann solltest Du auch PDF liefern und keineswegs das Zeug unterhaltsame Zeug von der Konsole.

        Schau also, was die Generator.py macht.

        Was ich mich überhaupt frage:

        Mit der richtigen Endung und shebang ...

        #!/usr/bin/python3
        /**
        *file: generator.cgi
        */
        
        print ("Content-type: application/pdf\n\n");
        
        [Hier der Rest der generator.py]
        

        ... kannst du Dir das Herumgefummel mit Perl als wrapper sparen.

        Oder Du sagst Deinem Apache endlich, dass er .py auch als CGI-Skript "drannnehmen" soll.

        Dennoch muss Du das Skript noch reparieren.

        In PHP mach ich Vergleichbares so:

        
        chdir ( '/tmp' );
        $system = "pdflatex  -interaction=nonstopmode \-synctex=0 -output-directory=/tmp $tmpfile_tex";
        
        $dummy = exec( $system );
        header( 'content-type: application/pdf' );
        header( 'Content-Disposition: attachment; filename="' . $_POST['Filennumber'] . '.pdf"' );
        echo file_get_contents( $tmpfile_pdf );
        

        Ich unterdrücke also den Output von pdflatex und sende dann den inhalt der enstandenen Datei.

        [Y] funktioniert.

        1. 
          chdir ( '/tmp' );
          $system = "pdflatex  -interaction=nonstopmode \-synctex=0 -output-directory=/tmp $tmpfile_tex";
          
          $dummy = exec( $system );
          header( 'content-type: application/pdf' );
          header( 'Content-Disposition: attachment; filename="' . $_POST['Filennumber'] . '.pdf"' );
          echo file_get_contents( $tmpfile_pdf );
          

          Ich unterdrücke also den Output von pdflatex und sende dann den inhalt der enstandenen Datei.

          Bevor Du irritiert bist: Davor darf (auch von den nutzlosen Wrapper-Skripten wie Deinem Perl-Skript) NICHTS ausgegeben werden.

          Die beiden Header-Zeilen (Aber eben nichts davor!) kannst Du in python3 so senden:

          print ( "Content-Type: application/pdf\n" );
          print ( "Content-Disposition: attachment; filename=\"" + filenumber + ".pdf\"\n\n" );
          

          Achte darauf, dass in Python filenumber hierbei ein String sein muss..., also filenumber="3" - nicht filenumber=3

          Die Ausgabe der von pdflatex erzeugten Dateei kann dann so gehen:

          f = open("dateiname.pdf", "r")
          print(f.read()) 
          

          Dein Kernproblem ist übrigens, dass Du selbst sagst, Du seist ein Beginner, aber dann Probleme aus der hohen Reitschule präsentierst. Du fängst an Galopp zu reiten bevor Du weisst, wie der Sattel festgezogen wird.

        2. Dein Reitprogramm sieht so aus:

          Browser ⇆ Webserver ⇆ Perl als CGI ⇆ Python ⇆ pdflatex
          

          Wenn es dir um die "ersten Schritte mit apache2, perl und cgi" geht, dann solltest Du Dich auch auf

          Browser ⇆ Webserver ⇆ Perl als CGI
          

          beschränken. Wenn es Dir aber um das Ergebnis geht, dann solltest Du mindestens einen der Wrapper weglassen, also entweder:

          Browser ⇆ Webserver ⇆ Perl als CGI ⇆ pdflatex
          

          oder, moderner:

          Browser ⇆ Webserver ⇆ Python ⇆ pdflatex
          

          oder, einfacher zu lernen

          Browser ⇆ Webserver ⇆ PHP ⇆ pdflatex
          

          In jedem Fall hast Du mehrere Schnittstellen (⇆) bei denen Du den Datenfluss genau kontrollieren, Dir also auch ansehen musst. Wie schon der Martin andeutete kannst Du Dich dabei z,B. nicht auf eine Umgebung mit bestimmten Variablen/Einstellungen, wie z.B. Pfaden verlassen.

          Ganz generell sollte man nicht zu viele solche Wrapper haben. Ein Perl-Skript aufzurufen, welches interpretiert wird und dann faktisch nur ein Python Skript aufruft, welches interpretiert wird, welches dann wiederum pdflatex aufruft,** ergibt in summa ein ziemlich kompliziertes, und langsames Gesamtsystem**, bei dem man dann auch noch über

          1. den oder die Browser und
          2. den Apache Webserver und
          3. Perl und
          4. Python und
          5. pdflatex

          allerhand wissen muss. Genau genommen entspricht Dein Vorhaben also nicht nur einem „Galopp in der Reitschule“ sondern einem „schwierigen Geländeritt bei Mistwetter, unter Beschuss und Wettbewerbsbedingungen“.

          Damit sollte man als „Reitschüler“ eher nicht beginnen. Ich z.B. habe für das Begreifen der Zusammenhänge in ähnlichen Gesamtsystemen auch eine Weile gebraucht (war auch oft verweifelt) und bin dann halt keinere Schritte gegangen.

          1. Vielen vielen Dank für eure Hinweise ... ich sehe jetzt - das Kernproblem begreifend - die Hindernisse, die ich als indianischer Reitschüler ohne Sattel im Galopp bei Schietwedder unter Wettbewerbsbedingungen zu überwinden habe.

            Dann werde ich mich mal auf den Weg machen ... und, wenn ich darf, wieder melden ...

            1. und, wenn ich darf, wieder melden

              Das sollst Du. Hierorts besteht gerade ein gewisser Mangel an Gelegenheit für Entäußerungen dieser Natur und anders als Geografielehrer in und zu Zeiten der DDR weiß ich worüber ich parliere – denn ich habe das, was Du als Ziel vor Auge hast, schon lange am Laufen und kenne die Balken, die gewiss zur Seite zu räumen sind.

              Tipp: Lass anno 2020 Perl außen vor (ist grad nicht so der Hit bezüglich Modernität und Community-Support) und mache die gesamte Logik bis auf das Erzeugen des PDF in PHP (vor allem weil es speziell fürs Web gemacht ist) oder Python (man kann mit guten Argumenten behaupten, dass wäre die bessere allgemeine Skriptsprache).

  2. Hallo Lars,

    ich bestreite gerade meine ersten Schritte mit apache2, perl und cgi, was eigentlich schon recht gut klappt. Heute wollte ich aus einem cgi-Skript (mu.pl) heraus ein Python-Skript starten, was nur klappt, wenn ich perl mu.pl nutze, aber nicht wenn ich <ip>/cgi-bin/mu.pl nutze.

    zunächst mal ist "klappt nicht" oder "klappt nur, wenn" keine ausreichende Fehlerbeschreibung.

    Aber meine Glaskugel hat im trüben Dunst einen kleinen Hinweis. Wenn du das Perl-Script von der Konsole aufrufst, wird es unter deinem aktuellen Benutzernamen ausgeführt. Wenn du es über den Webserver aufrufst, wird es unter der Benutzerkennung des Apachen ausgeführt (das könnte z.B. www-data sein).

    Das Environment dieser beiden Benutzer, inbesondere $PATH, könnte grundverschieden sein. Vielleicht wäre es also eine gute Idee, den exakten Pfad zu python3 anzugeben.

    Live long and pros healthy,
     Martin

    --
    Ich stamme aus Ironien, einem Land am sarkastischen Ozean.
    1. Danke für den Hinweis.

      Der hat mir auch weiter geholfen.