Teil von SELFHTML aktuell Teil von Artikel Teil von CGI/Perl

Michael Schröpl
Die Inbetriebnahme eines CGI-Skripts

nach unten Michael Schröpl
nach unten Einleitung
nach unten Warum CGI?
nach unten Name und Installationsort einer Datei
nach unten Datei-Inhalt
nach unten Erkennen der CGI-Anwendung durch den Webserver
nach unten Ausführbarkeit einer Datei
nach unten Wie findet der Webserver den Interpreter?
nach unten Diagnoseinformationen
nach unten Hilfreiche CGI-Skripte
nach unten Checkliste
nach unten Literatur

Michael Schröpl

E-Mail: E-Mail michael.schroepl@gmx.de
Homepage-URL: deutschsprachige Seite http://www.schroepl.net/

Bei Fragen zu diesem Beitrag bitte den Autor des Beitrags kontaktieren!

nach obennach unten

Einleitung

Interaktive Anwendungen erfüllen Websites mit Leben. Das Common Gateway Interface (CGI) ist eine verbreitete, plattformunabhängige und standardisierte Methode zum Einsatz solcher Programme. Zugriffszähler, Gästebücher, Diskussionsboards, aber auch viele kommerzielle Dienste - immer da, wo mehr als nur eine statische Präsentation von Informationen erforderlich ist, kommen CGI oder verwandte Techniken zum Einsatz.

Kleine interaktive Anwendungen können schon mit geringem Aufwand selbst erstellt werden; an zahlreichen Stellen im WWW gibt es kostenlose CGI-Anwendungen zum Download. Jetzt müßte man sie nur noch auf dem eigenen Server bzw. in der eigenen Homepage zum Laufen bringen. Daß das Problem hierbei oft an einem von vielen Details liegen kann, soll dieser Artikel aufzeigen - und ein paar Tipps für häufig auftretende Probleme anbieten.

Für das Verständnis bestimmter Eigenheiten ist in einigen Fällen Hintergrundwissen über die Art und Weise, wie ein Webserver arbeitet, erforderlich oder wenigstens hilfreich. In dieser Hinsicht wendet sich der Artikel auch an den Betreiber eines Webservers, welcher ggf. selbst die Aufgabe hat, seinen Anwendern die erforderlichen Voraussetzungen zum Betrieb von CGI-Anwendungen zu schaffen. Nicht in jedem Falle kann man davon ausgehen, daß ein Problem automatisch auf einen Anwenderfehler zurückzuführen ist - es gibt schließlich eine ganze Reihe von Einstellungen vorzunehmen, bis der Webserver gemäß der Zielvorgabe perfekt läuft. (Deshalb heißt der Artikel auch nicht "Die Installation eines CGI-Skripts", weil es damit allein manchmal eben nicht getan ist.)

Der Artikel mag ob seiner Länge abschreckend wirken - "ja, wenn das sooo schwierig ist ...". Das ist natürlich keineswegs meine Absicht. In jedem einzelnen Fall, in dem es nicht schon auf Anhieb klappt, wird wahrscheinlich ein anderes der vielen möglichen Probleme auftreten, aber kaum jemals alle auf einmal. Mit unerschütterlich methodischem Vorgehen lassen sich fast alle Probleme lösen - scheitern wird man nur dann, wenn der Webmaster eine notwendige Voraussetzung nicht zu schaffen bereit ist.

Die Problematik von CGI-Anwendungen ist weder auf eine Betriebssystemplattform noch auf einen Webserver oder eine Programmiersprache beschränkt, sondern universell; bei eigenen Beispielen innerhalb dieses Artikels habe ich die mir geläufigsten (und vermutlich verbreitetsten) Ausprägungen, nämlich UNIX, Apache und Perl, verwendet.

nach obennach unten

Warum CGI?

Reine HTML-Dokumente sind - zunächst einmal - eine statische Angelegenheit. Will man auf einer Webseite 'Intelligenz' erzeugen, dann sind hierfür häufig zwei Eigenschaften erforderlich:

Beim Transport einer Webseite von einem Webserver zu einem Betrachter sind zwei Rechner wesentlich beteiligt: Der Webserver-Rechner (Server) und der Browser-Rechner (Client). Jeder der beiden kann die gewünschten Aufgaben in gewisser Weise übernehmen.

Soll der Client die Intelligenz produzieren, dann ist der Autor der Webseite allerdings in verschiedener Hinsicht eingeschränkt:

Soll der Server die Intelligenz produzieren, dann kann der Autor der Webseite die erforderlichen Eigenschaften in vielen Fällen aus eigener Kraft sicherstellen:

Was beim Browser ankommt, ist ggf. wieder reines (harmloses) HTML; die Eigenschaften des Clients spielen dann lediglich für die Darstellung des zu erzeugenden Inhalts der Seite eine Rolle, nicht für das einsetzbare Werkzeug zu dessen Erzeugung - das ist der Vorteil an der Sache.
Speicherbedarf und Rechenleistung sind in diesem Falle allerdings auf die Summe der Anforderungen aller Besucher auszulegen, und der Server muß die Ausführung der Anwendung erlauben - das sind die wichtigsten Nachteile.

Selbstverständlich kann man beide Intelligenzmodelle auch kombinieren: Eine interaktive Anwendung kann einerseits ein dauerhaftes Gedächtnis auf einem Server benötigen, aber andererseits in der zum Anwender übertragenen HTML-Seite gleichzeitig JavaScript-Funktionen mitliefern, mit denen der Anwender lokal durch seinem Browser z. B. eine Syntaxanalyse für seine Formular-Eingaben erhält und somit möglichst nur geprüfte Eingaben zurück an den Webserver überträgt. Die Entlastung des Netzes durch Reduzierung der Kommunikationsvorgänge, die dadurch mögliche schnellere Reaktion und die ggf. schönere Präsentation (Übertragung von Graphik macht die Sache wieder langsamer) sind nicht zu verachtende Stärken der dezentralen Intelligenz.

Da die Bedienung eines Browsers schon bald zu den elementaren Kenntnissen der meisten Anwender gehören wird und ein kleiner, aber CGI-fähiger und fertig konfigurierter Webserver sich problemlos auf einer CD-ROM mit ausliefern und installieren läßt, kann man heute ernsthaft darüber nachdenken, beliebige Software mit einer CGI-basierten Web-Oberfläche statt einer plattformabhängigen und aufwendiger zu programmierenden graphischen Oberfläche zu versehen - zumal man die Netzwerkfähigkeit umsonst dazu bekommt, falls ein TCP/IP-Netz verfügbar ist. Es muß nicht immer das Internet sein, in dem eine CGI-Anwendung ihre Stärken entfaltet.

nach obennach unten

Name und Installationsort einer Datei

Nun also los mit der Inbetriebnahme der CGI-Anwendung, deren Dateien zunächst einmal auf den Webserver-Rechner gebracht werden müssen.

Das Standardproblem beim Transport einer Datei auf einen Server, nämlich daß Windows Groß- und Kleinschreibung in Dateinamen nicht unterscheidet, UNIX aber sehr wohl, trifft natürlich auch auf CGI-Skripts zu.

Die Konfiguration des Webservers kann relativ beliebige Abbildungen von realen Verzeichnissen auf URLs enthalten. Nicht immer kann man aus dem Installationsort eines CGI-Programms sofort auf die beim Aufruf des CGI-Programms anzugebende (also ggf. in einem HTML-Formular einzutragende) URL schließen.

Falls aus irgendeinem Grund die URL der Anforderung vom Webserver nicht auf den Pfadnamen der zu aktivierenden Datei abgebildet wird, dann wird der Anwender in seinem Browser eine Fehlermeldung der Art "not found" erhalten.

nach obennach unten

Datei-Inhalt

Zeilentrenner

Unglücklicherweise gibt es in verschiedenen Betriebssystemen unterschiedliche Auffassungen davon, wie ein Zeilenwechsel in einer (Text-)Datei darzustellen sei. UNIX verwendet ein Line Feed-Zeichen, DOS/Windows verwendet die Kombination aus Carriage Return und Line Feed.
Schon beim Transport einer normalen kleinen Homepage wird der Anwender also lernen müssen, daß er bei der Übertragung seiner Daten auf den Inhalt der Dateien Rücksicht nehmen muß:

Bei CGI-Anwendungen liegt genau dasselbe Problem vor:

Sichtbare Folgen

Hat der Anwender sein Programm in einem falschen Modus übertragen, dann wird es bei der Ausführung höchstwahrscheinlich abstürzen.
Mit ebenfalls hoher Wahrscheinlichkeit (bei Perl sogar mit Sicherheit, weil ja gleich die erste Zeile 'kaputt' ist) wird es das CGI-Programm nicht mehr schaffen, auch nur einen korrekten http-Header an den Anwender, der das Ergebnis in einem Browser bewundern möchte, zurückzusenden. Damit sind leider auch die (wahrscheinlich durchaus hilfreichen) Meldungen etwa des Perl-Interpreters über diesen Fehler im Browser nicht mehr sichtbar (falls die überhaupt nach stdout gegangen sind und nicht ohnehin nach stderr, was im Browser niemals ankommen wird).

Je nachdem, wie der Webserver funktioniert bzw. eingestellt ist, wird er in diesem Falle irgendwas tun. Leider gibt es viele Möglichkeiten:

An dieser Stelle ist ein Fehler also schwer zu identifizieren, zumal dieselben Symptome auch bei anderen Fehlersituationen auftreten können. Da hilft nur: Richtig machen oder im Falle eines mysteriösen Effekts immer auch die Übertragung des Dateiinhalts kontrollieren.

Test von Perl-Skripts auf dem Zielrechner

Konkret im Fall von Perl kann man sich weiterhelfen, wenn man auf dem Serverrechner selbst Kommandos ausführen darf - beispielsweise über eine Terminal-Sitzung (telnet etc.).

Zunächst einmal kann man einfach den Perl-Interpreter 'von Hand' aufrufen, also etwa mit

perl <dateiname>

(ggf. mit dem vollständigen Pfad des Perl-Interpreters) das Skript ausführen. Dieses hat dann zwar erst mal keine CGI-Parameterwerte, aber die hätte es auch nicht, wenn ein Anwender die entsprechene URL in seinem Browser eingetippt hätte - ein ordentliches CGI-Skript muß damit fertig werden.
Einen fehlerhaften Dateiinhalt (oder auch einen Syntaxfehler) findet man so jedenfalls sicher, weil man nun die Meldung des Perl-Interpreters lesen kann.

Wenn das Perl-Skript seine CGI-Parameterliste über den Perl-Standardmodul CGI interpretiert, dann erhält man in diesem Falle eine weitere wertvolle Testhilfe. cgi erkennt nämlich, daß kein CGI-Aufruf vorliegt, und fordert den Anwender auf, die fehlenden CGI-Parameterwerte im Dialog einzugeben. Das ist vielleicht nicht ganz so komfortabel und somit etwas anfällig für Bedienerfehler, aber auf diese Weise kann man das Verhalten eines CGI-Skripts ganz ohne Webserver in einer ziemlich realistischen Umgebung testen. Das ist doch auch was wert.

Unter UNIX kann man diese Eingabe zudem auch in den Perl-Aufruf hinein 'pipen':

echo "variable=wert" | perl skript.pl

also auch beides in einem Skript speichern und damit die Bedienung wieder etwas erleichtern.

Alternativ kann man die CGI-Umgebung auch dadurch simulieren, daß man in den richtigen Environmentvariablen von Hand plausible CGI-Parameterwerte setzt. Das geht in einem UNIX-shell-Skript ebenso wie in einer Windows-Batchdatei. Beispiel für Windows:

set QUERY_STRING="parameter1=wert1&parameter2=wert2"
perl skript.pl
pause

Das Kommando pause bewirkt, daß das Fenster nicht sofort zuklappt, wenn man eine solche Datei per Doppelklick aus dem Windows-Dateimanager startet.

Die 'Arbeit', solche Werte syntaktisch korrekt anzugeben, macht man genau einmal und ändert dann nur noch die Namen und Werte. Selbst wenn man das Skript nicht im Detail kennt, hat man doch oft ein HTML-Eingabeformular und kann sich durch versuchsweises Starten der CGI-Anwendung über einen Webserver den Query-String leicht beschaffen - die URL einer Seite wird ja auch im Fehlerfall vom Browser angezeigt.
Als Kandidaten für solche Environment-Variablen braucht man neben QUERY_STRING auch noch REQUEST_METHOD=GET - und ggf. REMOTE_USER=<name> (falls man ein System mit Seite Zugriffskontrolle vor sich hat ...).

Falls das Perl-Skript nicht den CGI-Modul verwendet und ohne brauchbare CGI-Parameterwerte in einer Orgie von Fehlermeldungen ertrinkt (es könnte ja ein im WWW gefundenes und weniger toll geschriebenes Skript sein), kann man es immerhin noch mit

perl -c <dateiname>

vom Perl-Interpreter auf dem Server-Rechner syntaktisch testen lassen - außer bestimmten Initialisierungsroutinen wird das Skript dabei nicht ausgeführt, aber komplett geprüft.
Zwar ist der Perl-Interpreter etwas eigenwillig, wenn es um die genaue Position eines Fehlers geht, aber dafür sind seine Meldungen in den meisten Fällen ziemlich aussagekräftig.

nach obennach unten

Erkennen der CGI-Anwendung durch den Webserver

Befindet sich der Inhalt der CGI-Anwendung unversehrt auf dem Zielrechner, dann muß der Webserver erkennen, daß er es mit einer CGI-Anwendung und nicht mit einem HTML-Dokument, einem Bild oder was auch immer zu tun hat. Irgendwie muß er in der Lage sein, einer bei ihm angeforderten URL, welche der Anwender ja auch direkt in die URL-Zeile des Browsers getippt haben kann, anzusehen, daß er hier mehr tun muß als nur den Inhalt einer Datei zurückzuliefern.

Hierfür bieten sich verschiedene Methoden an, die darin resultieren, den Installationsort bzw. das Namensmuster der auszuführenden Datei entsprechend den Vorgaben des Webservers zu wählen.

CGI-Verzeichnisse

Ein Verzeichnis oder gar ein kompletter Teilbaum des Webservers kann in dessen Konfiguration so gekennzeichnet sein, daß jeder Zugriff auf eine Adresse innerhalb dieses Teilbaums als Aktivierung einer CGI-Anwendung verstanden wird. Dies ist vermutlich der verbreitetste Mechanismus zur Erkennung von CGI-Anwendungen; viele Webserver kennen ein Verzeichnis mit dem Namen cgi oder cgi-bin, wobei der Teil bin vom traditionellen UNIX-Verzeichnisnamen bin für ausführbare Programme bzw. Systemkommandos in Maschinencode (binary) herrühren dürfte.
In diesem Falle muß der Anwender nichts weiter tun, als seine CGI-Anwendung in einem solchen Verzeichnis (dessen Name ihm der Webmaster vorher mitteilen wird) abzulegen. Insbesondere ist in diesem Fall der Dateiname (inklusive Endung) der CGI-Anwendung frei wählbar.

So einfach diese Möglichkeit ist und so elegant sich auf diese Weise die (oftmals als gefährlich angesehene) Berechtigung zur Ausführung von CGI-Anwendungen unter Kontrolle halten läßt (ggf. installiert der Webmaster die Anwendung sogar selbst, damit er keinem Anwender Schreibrecht auf sein einziges, kostbares CGI-Verzeichnis geben muß), so hat sie auch ihre Nachteile.
Eine komplexe CGI-Anwendung, etwa ein Diskussionsforum, besteht in den meisten Fällen aus ganz verschiedenen Komponenten: Skripts, Anleitungen, Eingabeformularen in HTML, Dateien zum Speichern der Anwendungsdaten usw. Kippt man nun das ganze Zeug einfach in das CGI-Verzeichnis und versucht, auf ein HTML-Dokument zuzugreifen, dann erhält man wahrscheinlich eine Fehlermeldung des Webservers, welcher vergeblich versucht hat, das HTML-Dokument als CGI-Anwendung 'auszuführen'. So geht es also nicht.
In diesem Falle wäre man gezwungen, seine Dateien an verschiedenen Stellen seines Verzeichnisbaums (die CGI-Programme im CGI-Verzeichnis, die übrigen Dateien z. B. in einem Produktverzeichnis) zu installieren. Auch das erschwert den Überblick ebenso wie beispielsweise die Datensicherung einer solcherart verstreuten Anwendung.
Auf diese Weise sammeln sich in einem CGI-Verzeichnis zudem im Laufe der Zeit allerlei Anwendungen verschiedenster Herkunft an, denen man aufgrund kurzer, oft kryptischer Dateinamen auf den ersten Blick weder ihren Zweck noch ihre Zusammengehörigkeit in einfacher Weise ansehen kann. Kurz gesagt: "Schön ist anders."

Hier tut sich bei der verteilten Installation einer CGI-Anwendung eine zusätzliche Fehlerquelle auf, die allerdings gleich beim ersten Aufruf des CGI-Programms entdeckt wird. Mit hoher Wahrscheinlichkeit sind entsprechende Formularseiten wenigstens geringfügig anzupassen - und womöglich sogar die Programme selbst, falls man keinen workaround verwenden kann.
Das ist beispielsweise eine Situation, in der es hübsch ist, wenn der Webserver die Traversierung von symbolic links erlaubt - damit kann man z. B. dem CGI-Programm den Installationsort von Datenverzeichnissen an der erwünschten Stelle vorgaukeln, ohne dafür irgendwelche fremden Programme ändern zu müssen. Die Anpassung der überschaubaren und lesbaren HTML-Formulare ist ja normalerweise nicht das Problem.

Dateitypen und Handler

Für die unterschiedliche Behandlung verschiedener Dateitypen müssen sich Server (Webserver) und Client (Browser) auf eine Konvention einigen, Dokument mit entsprechenden Typbezeichnungen zu versehen. Die MIME-Konvention ist ein solches Verfahren, durch welches etwa einem HTML-Dokument der Typ text/html, einer ASCII-Datei (bei welcher der Browser keine tags interpretieren soll) jedoch der Typ text/plain zugewiesen wird - auf diese Weise bleibt dieser Dateityp unabhängig von (ggf. plattformspezifisch eingeschränkten) Namenskonventionen (ein UNIX-Webserver kann ein Dokument hallo.html mit dem passenden MIME-Typ an einen Browser auf einem Windows-3.1-System senden, welches eine Datei mit einer 4 Zeichen langen Endung nicht hätte darstellen können).

Wenn der Webserver also ohnehin eine Konvention beherrschen muß, die eine Abbildung bestimmter Dateien auf entsprechende MIME-Typen aufgrund eines Namensmusters liefert, dann liegt es nahe, dieselbe Technik auch für die Erkennung von CGI-Anwendungen und anderen besonders zu behandelnden Dateitypen (z. B. HTML-Dokumente mit Server Side Includes) einzusetzen.
Allgemeiner dargestellt kann mancher Webserver (insbesondere Apache) in seiner Konfiguration einzelnen Dateitypen (Namensendungen) entsprechende Handler zuordnen. Solche Handler könnte man sich für Apache sogar selbst schreiben (die Schnittstelle dazu ist dokumentiert ...), es gibt aber natürlich vordefinierte Handler, und einer davon ist der Handler cgi-script, welcher das tut, was man von ihm erwartet.

Mit einer Anweisung der Art

add-handler cgi-script cgi

kann man (d. h. der Webmaster in seiner Konfiguration, ggf. auch der Anwender in seiner Seite .htaccess-Datei) also für den Geltungsbereich dieser Anweisung (dies kann der gesamte URL-Baum, aber auch ein einzelnes Verzeichnis sein) den Webserver anweisen, Dateien mit der entsprechenden Endung .cgi als CGI-Anwendungen anzusehen - auch wenn sie nicht in einem speziellen CGI-Verzeichnis installiert sind. Dies erlaubt es dem Anwender, seine Dateien nach inhaltlichen statt nach technischen Gesichtspunkten anzuordnen und läßt ihm größtmögliche Freiheit bei der Anordnung seiner Dateien und Verzeichnisse.
Wie man dem obigen Beispiel ansehen kann, muß eine etwa als Perl-Skript geschriebene CGI-Anwendung keineswegs immer *.pl heißen - es kommt darauf an, was der Webserver erwartet, und ggf. muß der Anwender seine Programme (und die darauf verweisenden Dokumente) geringfügig anpassen, falls er keinen Einfluß auf die Konfiguration des Webservers ausüben kann.

nach obennach unten

Ausführbarkeit einer Datei

Unter UNIX kann man einer Datei neben Lese- und Schreibrecht auch das Recht der Ausführbarkeit erteilen bzw. vorenthalten. Will ein Webserver auf einem UNIX-Rechner eine CGI-Anwendung ausführen, dann muß diese Anwendung ihm dies also erlauben.
Wird die CGI-Anwendung allerdings mit Hilfe eines FTP-Programms auf den Server transportiert, dann ist dieses Recht normalerweise erst mal nicht gesetzt. Schließlich kann es Viren auf allen Systemen geben, und der FTP-Server, welcher die übertragende Datei auf dem Zielrechner entgegennimmt, ist deshalb oftmals 'defensiv' eingestellt.
Der FTP-Server kann dem FTP-Client das Recht erteilen, die übertragene Datei durch eine entsprechende Aktion auch ausführbar zu machen (in diesem Falle stehen dem Anwender im FTP-Programm entsprechende Kommandos oder gar Dialoge zur Verfügung) - aber er muß nicht. Auf diese Weise kann der Betreiber eines FTP-Servers beispielsweise verhindern, daß ein Einbrecher auf seinem Rechner ein unliebsames Programm ausführt, obwohl er es immerhin dorthin transportieren durfte.

In bestimmten Fällen muß eine CGI-Anwendung nicht nur ausführbar, sondern gleichzeitig auch noch lesbar sein, um tatsächlich aktiviert werden zu können - und zwar genau dann, wenn sie durch ein Interpreterprogramm gelesen werden soll. Ein übersetztes und gebundenes C-Programm kann der (privilegiert ablaufende) Programmlader auch ohne Leserecht ausführen.

Hinzu kommt auch noch, daß der Anwender zwar im Normalfall seine eigene Benutzerkennung auf dem Webserver-Rechner besitzt, aber der Webserver selbst keineswegs mit der Berechtigung genau dieser Benutzerkennung ausgeführt werden muß.
Manchmal läßt ein Betreiber seinen Webserver sogar ganz bewußt unter einer eigenen Kennung mit besonders wenigen Rechten (z. B. nobody) laufen - falls tatsächlich mal jemand ein Programm über den Webserver ausführt, welches diesem Böses will, kann man damit den Schaden vielleicht in Grenzen halten. Man darf also nicht davon ausgehen, daß eine CGI-Anwendung unbdingt unter derjenigen Berechtigung ausgeführt wird, unter der sie installiert wurde.

In der UNIX-Welt werden Berechtigungen zum Lesen (Read), Schreiben (Write) und Ausführen (eXecute) in drei Sorten eingeteilt:

Um sicher zu gehen, daß der Webserver auf einem UNIX-Rechner eine CGI-Anwendung in einer Skript-Sprache ausführen kann, wird man ihr also insgesamt sechs Rechte erteilen, nämlich Lese- und Ausführungsrecht für jede dieser drei Sorten.
Praktischerweise erteilt man sich selbst (dem Besitzer) auch noch das Recht, den Inhalt der Datei ändern zu dürfen, und erhält somit die sieben gesetzten Bits, die mit den Kommandos

chmod u+rwx <dateiname>       # user:   +read, +write, +execute
chmod g+rx  <dateiname>       # group:  +read,         +execute
chmod o+rx  <dateiname>       # others: +read,         +execute

oder in kryptischer, aber bequemer Form

chmod 755 <dateiname>

aktiviert werden, wie bereits in bereichsübergreifende Seite SELFHTML erwähnt.

Wenn man genau weiß, welche Rechte für die Ausführung einer CGI-Anwendung erforderlich sind, dann wird man allerdings daran interessiert sein, alle übrigen Rechte auszuschalten - andernfalls könnten andere Anwender auf demselben Server-Rechner ggf. mehr mit solchen Dateien anfangen, als beabsichtigt war. Wenn es etwa um Geheimhaltung geht, lohnt es sich möglicherweise, den Webmaster zu fragen - oder selbst solange einzelne Rechte wegzunehmen, bis die Anwendung nach dem nächsten Schritt nicht mehr funktioniert.

nach obennach unten

Wie findet der Webserver den Interpreter?

Soll das CGI-Skript von einem Interpreterprogramm ausgewertet werden, dann muß der Webserver bei der Aktivierung des CGI-Programms diesen Interpreter auch finden können.

Wie er dies allerdings tut, ist leider keineswegs standardisiert. In den meisten Fällen wird der Webmaster das dem Anwender erklären müssen. Um den Leser wenigstens für das Thema zu sensibilisieren, seien hier drei Beispiele genannt.

WebSite 1.1 unter Windows32

Als typisches Windows-Programm kümmert sich der WebSite-Server nicht darum, wie eine CGI-Anwendung ausgeführt wird - so etwas ist Sache des Betriebssystems. WebSite führt das Skript einfach aus und hofft, daß irgendetwas Sinnvolles passieren wird.
In Windows kann man Dateitypen (also Namensendungen) einen Interpreter zuordnen - genau das muß man als WebSite-Betreiber für alle potentiellen CGI-Endungen tun. Wenn man seine Perl-Skripts mit dem Lieblings-Editor verknüpft hat, um in seiner Entwicklungsumgebung das Skript durch einen Doppelklick auf die Datei im Datei-Manager oder Windows-Explorer bearbeiten zu können, dann wird der Webserver mit dieser Einstellung nicht glücklich werden.

Apache 1.3 unter UNIX

Als typisches UNIX-Programm kennt Apache einen Mechanismus, um Programme auszuführen: Es ruft eine shell auf, die das erledigen kann. die Systemroutine system() auf, also den normalen UNIX-Programmlader.
Dieser liest zunächst die ersten zwei Byte aus der auszuführenden Datei. Wenn dort die 'magische' Zeichenfolge #! steht, dann liest er alles, was dahinter bis zum ersten Zeilenende folgt, und interpretiert es als Kommando zum Start eines Interpreterprogramms; dabei muß ein vollständiger Pfadname angegeben werden. An dieses Kommando wird zudem der Pfadname der ursprünglich auszuführenden Datei als Parameter angefügt.
Kurz gesagt: Man schreibt also das Kommando zum Start des Interpreters in die 1. Zeile des Skripts.

Dafür muß man leider wissen, wo dieser Interpreter auf dem Webserver-Rechner installiert ist.
Obwohl es unter UNIX üblich ist, daß Kommandos über eine Liste von Verzeichnisangaben in der Environment-Variable PATH gefunden werden, verwendet der Webserver diese Konvention nicht (weil er dafür entweder selbst diese Verzeichnisliste auf der Suche nach dem Interpreter ggf. komplett durchprobieren oder aber eine Shell starten müßte, was das System wiederum Ressourcen kosten würde - system() allein ist zu unflexibel dafür).
Obwohl ein fertiges Perl-Skript aus dem WWW üblicherweise bereits einen solchen Interpreteraufruf enthält, muß der Anwender diesen vor dem Transport des Skripts auf den Server-Rechner also selbst anpassen.
Da der Perl-Interpreter an nahezu beliebiger Position innerhalb des Verzeichnisbaums installiert sein kann, ist die naheliegende Konsequenz, den Webmaster zu fragen, wie der exakte Aufruf des Interpreters auf seinem Rechner lautet. (Theoretisch kann der Perl-Interpreter statt perl ja genausogut perl5 heißen oder wie auch immer ...)

Hat der Anwender einen Dialogzugang zu seinem Webserver-Rechner, kann dort also selbst Kommandos ausführen, dann kann er den Interpreter selbst finden, falls er den Namen der Datei errät und der Interpreter selbst über die oben erwähnte Environment-Variable PATH erreichbar ist. Hierfür steht das shell-Kommando which zur Verfügung, welches genau die gewünschte Operation durchführt.

Beispiel:

which perl

könnte zur Ausgabe

/usr/local/bin/perl

oder einem beliebigen anderen Pfadnamen führen. Dieser ist dann in Zeile 1 des Perl-CGI-Skripts einzutragen.

Natürlich muß auch der Interpreter selbst für den Anwender (bzw. später für die Benutzerkennung, unter welcher der Webserver abläuft) nach oben ausführbar sein - andernfalls findet übrigens auch das which-Kommando ihn nicht, selbst wenn sein Verzeichnis in PATH eingetragen ist ...

Anmerkung: Auch der Netscape Enterprise Server 2.0 für UNIX verhält sich exakt so wie hier für den Apache-Webserver beschrieben - und wahrscheinlich werden die meisten anderen Webserver unter UNIX dasselbe tun.

Apache 1.3 unter Windows32

Sinngemäß gilt hier dasselbe wie für Apache unter UNIX:

Die Windows-Version des Apache-Webservers kann also die Environment-Variable PATH auswerten, falls diese (über AUTOEXEC.BAT oder die Registry) entsprechend gesetzt wurde.
Anschließend genügt die Angabe

#!perl

in Zeile 1 des Perl-Skripts, damit Apache den Perl-Interpreter wie gewünscht aufrufen kann.

nach obennach unten

Diagnoseinformationen

An diversen Stellen waren wir bisher darauf angewiesen, bestimmte Fehler zu erraten. Das ist bedauerlich, denn der Webserver hatte im Moment des Scheiterns der Ausführung des CGI-Skripts wesentlich genauere Kenntnis über die Fehlersituation als wir. Und selbstverständlich hat er diese Informationen nicht einfach weggeworfen, sondern in einer seiner Protokolldateien abgelegt.
Wenn wir also Zugriff auf diese Protokolldateien hätten, wären wir der Lösung des Problems meist wesentlich näher.

Protokollinformationen lassen sich in verschiedene Gruppen einteilen:

Diese mächtigen Diagnosefunktionen sind ein wesentlicher Grund dafür, wieso man seine CGI-Anwendung möglichst auf einem eigenen Rechner testinstallieren sollte, bevor man den Schritt auf den Zielrechner wagt - hier hat man normalerweise ungleich bessere Chancen, die Anwendung zum Laufen zu bekommen. Ihre Verfügbarkeit ist allerdings auch der Unterschied zwischen einem guten und einem weniger guten Service durch den Webmaster.

nach obennach unten

Hilfreiche CGI-Skripte

Umgebungsvariablen

Sobald der Anwender in der Lage ist, ein einfaches CGI-Skript auszuführen (also die Probleme des nach oben Installationsorts, des nach oben Datei-Inhalts, der nach oben CGI-Erkennung , der nach oben Ausführbarkeit und der nach oben Interpreter-Verknüpfung im Griff hat), kann er sich eine kleine CGI-Anwendung installieren, die als Perl-Skript ungefähr folgendermaßen aussehen könnte (1. Zeile ggf. nach oben entsprechend anpassen):

#! /usr/local/bin/perl
print "Content-Type: text/plain\n\n";
foreach my $p (sort keys %ENV) { print "$p=$ENV{$p}\n"; }

Was tut das Ding? Es erzeugt als Ausgabe ein http-Paket mit einem Text-Dokument (text/plain - ich brauche kein HTML, wenn ich nur triviale Ausgaben erzeugen will), in welchem die Inhalte sämtlicher diesem (und jedem anderen) CGI-Programm zugänglichen Environment-Variablen (vordefinierte Perl-Variable %ENV) dargestellt werden.
Die Ausgabe im Browser wird also ungefähr folgendermaßen aussehen:

DOCUMENT_ROOT=/export/one/d/produkt/apache/htdocs
GATEWAY_INTERFACE=CGI/1.1
HTTP_ACCEPT=image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
HTTP_CONNECTION=Keep-Alive
HTTP_HOST=www:8080
HTTP_PRAGMA=no-cache
HTTP_USER_AGENT=Mozilla/3.01 [de] (WinNT; I)
PATH=/bin:/usr/bin:/usr/ucb:/etc:/usr/local/bin:.
QUERY_STRING=
REMOTE_ADDR=153.46.90.209
REMOTE_PORT=1269
REQUEST_METHOD=GET
REQUEST_URI=/cgi-bin/env.pl
SCRIPT_FILENAME=/export/one/d/benutzer/cgi-bin/env.pl
SCRIPT_NAME=/cgi-bin/env.pl
SERVER_ADMIN=michael.schroepl@gmx.de
SERVER_NAME=www
SERVER_PORT=8080
SERVER_PROTOCOL=HTTP/1.0
SERVER_SIGNATURE=Apache/1.3.6 Server at www Port 8080
SERVER_SOFTWARE=Apache/1.3.6 (Unix)
TZ=WET

Damit erfährt man über den Webserver-Rechner immerhin so einiges, etwa

Je besser man sich auf seinem Zielsystem auskennt, um so bewußter kann man die dort verfügbaren Möglichkeiten ausnutzen.
(Das gilt natürlich ganz besonders für den Webmaster selbst, der genau wissen sollte, was seine 'Kunden' von seinem Rechner alles sehen können!)

Wie man sieht, kann das CGI-Skript eventuell nicht nur auf die in der Definition der CGI-Schnittstelle festgelegten Variablen zugreifen, sondern auch solche aus der Prozeßumgebung des Webservers - wenn der Webserver entsprechend konfiguriert wurde. (Im obigen Beispiel durch den Apache-Modul mod_env; was wirklich sichtbar ist, muß man letztlich ausprobieren.)

Gleichzeitig erhält man aber auch einen Eindruck darüber, was das CGI-Skript über den Anwender erfährt, etwa

Je besser man die Möglichkeiten seines CGI-Skripts kennt, desto flexibler kann dieses auf allfällige Situationen reagieren. Einige weitere wichtige CGI-Variablen wie QUERY_STRING, HTTP_REFERER oder REMOTE_USER sind in diesem Beispiel aus verschiedenen Gründen leer oder nicht definiert - es erspart also nicht die Lektüre der CGI-Spezifikation.

Systemkommandos

Wenn der Anwender auf dem Webserver-Rechner selbst Kommandos ausführen kann, dann kann er eine Reihe von Tests durchführen, die ihm weitere Informationen über den Webserver-Rechner und damit über mögliche Fehlerquellen liefern.
Wir schreiben uns also wieder ein kleines Skript (wie vorhin: 1. Zeile ggf. entsprechend anpassen):

#! /usr/local/bin/perl
print "Content-Type: text/plain\n\n";
my $command = "uname -a";
print "Kommando: '",   $command,  "'\n";
print "Ergebnis: ",   `$command`,  "\n";
print "Returncode: '", $?,        "'\n";

Achtung, genau hinsehen: Das sind viele verschiedene Hochkommata-Arten!

Was tut das Ding? Es führt das Systemkommando uname -a auf dem Webserver-Rechner aus (dieses wurde der Variablen $command zugewiesen), sammelt dessen Ausgaben auf (das erledigen diese seltsamen rückwärtigen Hochkommata, auch backticks genannt) und liefert beides sowie den Returncode des Kommandos als ASCII-Dokument an den Browser zurück.
Das Ergebnis sieht dann ungefähr so aus:

Kommando: 'uname -a'
Ergebnis: SunOS WWW 5.5 Generic_103093-03 sun4u sparc SUNW,Ultra-1
Returncode: '0'

Aha: Die Kiste heißt also WWW, ist eine SUN-Maschine Ultra-1 mit sparc-CPU drin und verwendet das Betriebssystem SunOS in der Version 5.5 Sub-Release Generic_103093-03. (Siehe man page zu uname.) Na also - wer fragt, bekommt auch Antworten ...

Falls die Ausführung des Kommandos nicht funktioniert hat (z. B. weil es das Kommando gar nicht gibt), dann wird der Returncode einen Wert ungleich 0 aufweisen.

Natürlich kann man beliebige Kommandos eigener Wahl verwenden (und dabei sogar die vorhandene PATH-Definition ausnutzen), sofern diese Kommandos auf dem Webserver-Rechner verfügbar sind (Windows hat beispielsweise kein uname).

Mit diesem Instrumentarium bewaffnet kann man nun auch ohne Telnet-Zugang feststellen, ob allfällige weitere inhaltliche Anforderungen auf dem Webserver-Rechner gegeben sind.
(Tip für das nächste auszuprobierende Kommando: perl -V, das produziert eine sehr detaillierte Beschreibung des Installationsumfangs des Perl-Interpreters ...)

nach obennach unten

Checkliste

Wenn bei der Inbetriebnahme eines CGI-Skripts irgendetwas nicht funktioniert, dann kann es hilfreich sein, die Punkte der nachfolgenden Liste zu überprüfen. Die angegebenen Symptome können nur als Hinweise dienen und sind weder garantiert noch eindeutig.

  1. Befindet sich das CGI-Programm mit dem richtigen nach oben Namen im richtigen nach oben Verzeichnis, in dem es durch die angeforderte URL erwartet wird?
    (Symptom: http-Fehler 404 "Document not found")
  2. Hat das CGI-Programm an seinem nach oben Installationsort und unter seinem konkreten Dateinamen überhaupt nach oben CGI-Berechtigung?
    (Symptom: http-Fehler 200 "Forbidden")
  3. Ist der nach oben Inhalt des CGI-Programms unbeschadet auf dem Server-Rechner angekommen (Skript-Dateien im ASCII-Modus, Maschinenprogramme im Binärmodus übertragen)?
    (Symptom: http-Fehler 500 "Internal Server Error")
  4. Erkennt der Webserver, daß der die Datei nach oben als CGI-Anwendung interpretieren soll?
    (Symptom: Dokumentinhalt wird im Browser angezeigt)
  5. Ist die CGI-Programmdatei hinreichend nach oben ausführbar?
    (Symptom: http-Fehler 200 "Forbidden")
  6. Kann und darf der Webserver den nach oben Interpreter eines CGI-Skripts aktivieren?
    (Symptom: http-Fehler 500 "Internal Server Error")
  7. Stellt die CGI-Anwendung spezielle nach oben technische Anforderungen an den Webserver-Rechner, etwa eine nach oben Betriebssystemplattform, eine bestimmte Version eines Interpreters usw.?
    (Symptom: http-Fehler 500 "Internal Server Error")

Wenn all diese Voraussetzungen erfüllt sind, aber die CGI-Anwendung immer noch nicht funktionieren will, dann sollte man den Webmaster um Hilfe bitten. An dieser Stelle ist es wahrscheinlich, daß er entweder zusätzliche Berechtigungen erteilen oder zusätzliche Software installieren müßte, um die Anwendung funktionsfähig werden zu lassen. Und wenn er dazu nicht bereit ist, dann wird die Sache scheitern.

In diese Kategorie gehören u. a.

Solche Sachen sollte man eigentlich als Allererstes klären, weil ggf. die ganze Aktion gar keine Chance auf Erfolg hat, wenn sich hier unüberwindliche Probleme auftun. Hier scheitert beispielsweise schon der Versuch, auf der Homepage eines Massenproviders überhaupt eine CGI-Berechtigung zu bekommen.
Leider ist es nicht immer ganz einfach, solche Fallstricke schon am Anfang zu erkennen. Mein Leitsatz: "Jede zusätzliche Abhängigkeit ist von Übel."

nach obennach unten

Literatur

deutschsprachige Seite CGI-Scripts auf öffentlichem WWW-Server installieren

Das SELFHTML-Kapitel zum Thema.

englischsprachige Seite Apache Server Frequently Asked Questions

Der Abschnitt englischsprachige Seite Dynamic Content (CGI and SSI) beschäftigt sich mit häufig auftretenden Problemen bei der Verwendung dieser beiden features.

englischsprachige Seite Sherlock Holmes and the Case of the Broken CGI Script

Ein ebenso lehrreicher wie unterhaltsamer Artikel von Selena Sol für die Web Developer's Virtual Library über die richtige Einstellung bei Lösen von Problemen mit CGI-Anwendungen (Beispiele in Perl).

englischsprachige Seite The Common Gateway Interface Specification

Die Spezifikation der CGI-Schnittstelle (Version 1.1).

Teil von SELFHTML aktuell Teil von Artikel Teil von CGI/Perl

© 2007 bereichsübergreifende Seite Impressum