CGI mit Perl -
Der klassische Weg zu dynamischen Webseiten
Stefan Sell, tes@tursa.franken.de
KNF-Kongreß 26.11.2000
$Revision: 1.3 $
Was passiert beim Aufruf einer Webseite?
- Browser (Client) nimmt mit einem Server über TCP/IP eine
Verbindung auf
- Client fordert vom Server eine bestimmte Seite (URL, Uniform
Resource Locator) an
- Kommunikation zwischen Client und Server wird über HTTP
(Hypertext Transfer Protocol) definiert
- Server schickt Antwort in Form von HTML (Hypertext Markup
Language)
- Browser interpretiert HTML und stellt die Seite dar
"Statisches" HTML
Was sind "dynamische" Webseiten?
- Sammelbegriff für verschiedene unterschiedliche
Techniken
- Webseite wird erst zum Zeitpunkt der Darstellung
vollständig erzeugt
- Automatisch auf dem Server oder durch Einwirken des
Anwenders
- Client-Seitig: Der Browser interpretiert in HTML eingebettete
Befehle einer Programmiersprache (Java, Javascript, VBScript,
...)
- Server-Seitig: Das zurückgelieferte HTML wird nicht aus
einer statischen Datei gelesen, sondern dynamisch durch ein
Programm beim Aufbau erzeugt (CGI, PHP, ASP, JSP, mod_perl,
...)
Was bedeutet CGI (Common Gateway Interface)?
- Statt einer statischen HTML-Datei wird vom Server ein Programm
aufgerufen
- Das CGI-Programm kann (theoretisch) in jeder beliebigen
Programmiersprache erstellt werden
- Die erste Ausgabezeile muß (!) den Typ des Inhalts
angeben (gefolgt von einer Leerzeile)
- Die Ausgabe des CGI-Programms wird vom Browser ausgewertet und
muß daher (bei Typ HTML) gültiges HTML sein
- Dem CGI-Programm können über die URL Parameter
übergeben werden
- Das CGI-Programm kann alles machen, was ein Programm machen
kann: Kontrollstrukturen, Dateizugriffe, Datenbankaufrufe, ...
- Voraussetzung zum CGI-Programmieren: Kenntnisse von HTML,
CGI-Standards, Programmiersprache, ggf Server-Betriebssystem
Beispiel-Anwendungen für CGI
- Gästebücher
- Zugriffszähler
- Formularerfassung
- Bestellsystem / Web-Shop
- Suchanfragen für Datenbanken
- Web-basierte Diskussionsforen
- ...
CGI im Vergleich
- CGI hat im Vergleich zu anderen server-basierten dynamischen
HTML-Techniken
- Vorteile:
- Alte Technologie
- Bewährt
- Weit verbreitet
- Offener Standard
- Unabhängig von Hardware, Server, Browser,
Betriebssystem, Programmiersprache
- Nachteile:
- Alte Technologie
- In vielen Fällen nicht die schnellste Lösung
- Sicherheitsprobleme für Web-Server-Betreiber
(gilt auch für andere Server-Techniken)
Welche Programmiersprache für CGI?
- Theoretisch können CGI-Skripte in jeder beliebigen
Programmiersprache erstellt werden
- Die meisten CGI-Skripte werden mit "Perl" erstellt:
- Sehr mächtige Skript-Sprache, Programme werden nicht
direkt ausgeführt sondern interpretiert
- Kommt ursprünglich aus der UNIX-Welt, ist aber auch
für andere Plattformen verfügbar
- Aktuell sind die 5er Versionen
- Vorteile:
- Freeware, Open Source
- portabel, plattformübergreifend
- mächtig
- weite Verbreitung
- großer Bestand an fertigen Modulen und
Beispielen
- viele Freiheiten, viele Wege führen zum Ziel
- Nachteile:
- viele Wege führen zum Ziel
- bisweilen etwas kryptisch
Einfaches Beispiel
"Hello World" per CGI mit Perl:
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "<HTML><HEAD><TITLE>\n";
print "Hello World!\n";
print "</TITLE></HEAD><BODY>\n";
print "Hello World! " . `date '+%d.%m.%y %H:%M:%S'` . "\n";
print "</BODY></HTML>\n";
- Wenn die erste (!) Zeile mit "#!" beginnt, wird unter
Unix/Linux mitgeteilt, von welchem Programm das Skript
interpretiert werden soll (hier "/usr/bin/perl")
- Für andere Webserver ist der Pfad zum Perl-Interpreter
ggf anzupassen
- Das Beispiel kann unter der URL http://www.franken.de/users/tursa/cgi-bin/hello.cgi
aufgerufen werden
Web-Server
- CGI ist nur mit einem Web-Server möglich
- Der Web-Server muß für den Einsatz von CGI
vorbereitet sein
- Verschiedene Einstellungen oder Restriktionen können vom
Web-Server-Administrator verändert werden
- Aus Sicherheitsgründen ist meist kein
uneingeschränkter Zugriff möglich, z.B.
- Nur bestimmte Sprachen sind zugelassen
- Beschränkung auf bestimmtes Verzeichnis
- Beschränkung der aufrufbaren Programme
- ...
- Vor dem Erstellen von CGI's sollte man die Rahmenbedingungen
des Web-Servers prüfen!
Lokaler Web-Server
- CGI's sollte man vor dem Hochladen auf einen öffentlichen
WWW-Server lokal testen
- Vorrausetzung: Web-Server (z.B. Apache), Browser, TCP/IP
- Der Web-Server muß gegebenenfalls für den Einsatz
von CGI konfiguriert werden (Angabe von Zulässigen Endungen
und Verzeichnissen)
- Näheres sollte in der Doku des jeweiligen Web-Servers
nachgelesen werden
CGI-Skripte auf www.franken.de
- Web-Server: Apache unter Linux
- Voraussetzung: KNF-Mitglied/Teilnehmer, WWW-Account
vorhanden
(Falls nicht: Mail an webmaster@franken.de)
- Dateien können dann per FTP zu ftp.franken.de hochgeladen
werden (ASCII-Modus!)
- User können eigene CGI-Skripte unter ihrem Home im
Unterverzeichnis "cgi-bin" erstellen
- Alle CGI-Scripte müssen die Endung ".cgi" haben
- Das Script muss mit der UID/GID des jeweiligen Benutzers
laufen (Standard)
- Alle CGI-Scripte müssen ausführbar und sollten
für andere nicht beschreibbar sein (chmod 0755)
- Die CGI-Scripte laufen in einem "Sandkasten"
(chroot-Umgebung): Nur bestimmte Dateien sind "sichtbar", nur
bestimmte Befehle können aufgerufen werden
- 'sendmail' kann nicht aufgerufen werden, stattdessen kann man
zum Versenden von Mails das Perl-SMTP-Modul verwenden
Hochladen von CGI-Skripten auf www.franken.de
Als Beispiel mit der WWW-Userkennung "w3tursa" und dem Standard
FTP-Client:
tes@tursa.franken.de:~/www/cgi-bin> ftp ftp.franken.de
Connected to ilsa.franken.de.
...
220 ProFTPD 1.2.0 Server (KNF ftp Server) [ilsa.franken.de]
Name (ilsa.franken.de:tes): w3tursa
331 Password required for w3tursa.
Password: XXXXXXXX
230 User w3tursa logged in.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> mkdir cgi-bin
257 "/cgi-bin" - Directory successfully created.
ftp> chmod og-rw cgi-bin
200 SITE CHMOD command successful.
...
ftp> cd cgi-bin
250 CWD command successful.
ftp> asc
200 Type set to A.
ftp> put hello.cgi
local: hello.cgi remote: hello.cgi
200 PORT command successful.
150 Opening BINARY mode data connection for hello.cgi.
226 Transfer complete.
341 bytes sent in 0.00402 secs (83 Kbytes/sec)
ftp> chmod 0755 hello.cgi
200 SITE CHMOD command successful.
Das Skript kann nun unter der URL http://www.franken.de/users/tursa/cgi-bin/hello.cgi
aufgerufen werden.
Daneben gibt es auch diverse komfortablere grafische FTP-Clients
für verschiedene Plattformen.
CGI-Skripte auf shell.franken.de
- Neben dem WWW-Server können auch auf shell.franken.de
CGI-Skripte ausgeführt werden
- Web-Server: Apache unter Linux
- CGI-Skripte müssen in ~/public_html/cgi-bin/ liegen und
auf .cgi enden
- Zugriff kann mit einer ".htaccess" Datei gesteuert werden
(für Apache-Direktiven, z.B. Paßwortschutz)
- Das CGI-Skript kann dann alles machen, was der User auf
shell.franken.de auch machen kann (z.B. Datenbankabfragen mit
MySQL)
- Aufruf z.B. http://shell.franken.de/~tursa/cgi-bin/hello.cgi
- Nähere Infos und Einrichten von Accounts für
KNF-Mitglieder/Teilnehmer: http://shell.franken.de/
oder Mail an shellmaster@franken.de
Aufruf von CGI-Skripten aus HTML
Ein CGI-Script kann aus einer HTML-Datei heraus auf verschiedene
Arten aufgerufen werden:
- Verweis
<a href="cgi-bin/hello.cgi">Testprogramm
anzeigen</a>
- Formular:
<form action="cgi-bin/simpleform.cgi" method="get">
- Grafikreferenz: Das CGI-Script muß hierbei Grafikdatei
(GIF/JPEG) zurückliefern
<img src="cgi-bin/counter.cgi">
- SSI - Server Side Include Anweisung (Web-Server muß das
unterstützen, derzeit bei www.franken.de nicht
möglich)
<!-- #exec cgi="cgi-bin/counter.cgi" -->
- automatisches Laden über <meta>-Befehl
<meta http-equiv="refresh" content="0;
URL=cgi-bin/hello.cgi">
CGI-Umgebungsvariablen
- Web-Server stellt dem CGI-Script besondere
CGI-Umgebungsvariablen zur Verfügung
- Bei jedem Aufruf werden diese mit spezifischen Werten
gefüllt
- Auslesen in Perl z.B. mit $get_meth =
$ENV{'REQUEST_METHOD'};
- Auswahl interessanter Umgebungsvariablen:
- REQUEST_METHOD: Aufruf-Methode für CGI (GET oder
POST)
- CONTENT_LENGTH: Anzahl Zeichen bei POST-Methode
- QUERY_STRING: Daten bei GET-Methode
- SERVER_NAME: Name des Servers (z.B. www.franken.de)
- HTTP_USER_AGENT: Informationen zum Browser des
Benutzers
- ...
Formulare
- Eingabe von Benutzerdaten
- Verschiedene HTML-Tags: FORM, INPUT, TEXTAREA, ...
- Beim Abschicken kann CGI-Skript aufgerufen werden. Die
Eingabedaten werden dann in der URL codiert:
cgi-bin/simpleform.cgi?Kommentar=Dies+ist+ein+Kommentar
- GET-Methode:
- Formular-Daten werden in der CGI-Umgebungsvariablen
QUERY_STRING übergeben
- POST-Methode:
- Formular-Daten werden auf Standard-Eingabe
übergeben
- Länge der Daten wird in der CGI-Umgebungsvariablen
CONTENT_LENGTH übergeben
Beispiel-Formular: Einfache Eingabe
simpleform.html:
<HTML><HEAD>
<TITLE>Kommentar</TITLE>
</HEAD><BODY>
<FORM action="cgi-bin/simplefile.cgi" method=get>
<p>Geben Sie bitte ihren Kommentar ein:</p>
<TEXTAREA name="Kommentar" rows="10" cols="50">
</TEXTAREA><BR>
<INPUT type=submit value="Absenden">
</FORM>
</BODY></HTML>
Das entsprechende HTML-Formular kann unter der URL http://www.franken.de/users/tursa/simpleform.html
aufgerufen werden.
Beispiel: Benutzereingabe in Datei speichern
simplefile.cgi:
#!/usr/bin/perl
$get_meth = $ENV{'REQUEST_METHOD'};
if ($get_meth eq "POST") {
$data = <STDIN>; chomp $data;
} elsif ($get_meth eq "GET") {
$data = $ENV{'QUERY_STRING'};
}
# Initialisierungen:
$cntfile = "simplecnt";
$msgnr=0;
# Zählerdatei einlesen, wenn vorhanden:
if (-s $cntfile) {
open (CNT, "<$cntfile");
$msgnr=<CNT>; close (CNT); }
$msgnr++;
# Eintrag schreiben:
open (ENTRY, ">simple${msgnr}.ent");
print ENTRY "$data";
close (ENTRY);
# Zählerdatei aktualisieren:
open (CNT, ">$cntfile");
print CNT "$msgnr\n";
close (CNT);
# HTML Ausgeben:
print "Content-type: text/html\n\n";
print "<HTML><HEAD><TITLE>\n";
print "Ihre Daten wurden verarbeitet\n";
print "</TITLE></HEAD><BODY>\n";
print "Ihre Daten wurden verarbeitet. ";
print "Sie hatten die Nummer ". $msgnr . "\n";
print "</BODY></HTML>\n";
Beispiel: Eingelesene Formulardaten als Mail versenden (1)
simplemail.cgi mit Perl-SMTP-Modul (für www.franken.de):
#!/usr/bin/perl
use Net::SMTP;
$mailto = "tes\@tursa.franken.de";
$get_meth = $ENV{'REQUEST_METHOD'};
if ($get_meth eq "POST") {
$data = <STDIN>; chomp $data;
} elsif ($get_meth eq "GET") {
$data = $ENV{'QUERY_STRING'};
}
$smtp = Net::SMTP->new("mail-n.franken.de");
$smtp->mail($mailto);
$smtp->to($mailto);
$smtp->data();
$smtp->datasend("To: " . $mailto . "\n");
$smtp->datasend("From: CGI Skript\n");
$smtp->datasend("Subject: Hello\n\n");
$smtp->datasend("$data\n");
$smtp->dataend();
$smtp->quit;
print "Content-type: text/html\n\n";
print "<HTML><HEAD><TITLE>\n";
print "Ihre Daten wurden verarbeitet\n";
print "</TITLE></HEAD><BODY>\n";
print "Ihre Daten wurden verarbeitet. \n";
print "</BODY></HTML>\n";
Das entsprechende HTML-Formular kann unter der URL http://www.franken.de/users/tursa/simplemail.html
aufgerufen werden.
Beispiel: Eingelesene Formulardaten als Mail versenden (2)
simplemail.cgi mit sendmail (nicht für www.franken.de, aber
z.B. für andere Web-Server):
...
open (MAIL, "|/usr/sbin/sendmail " . $mailto)
|| die "Can't open /usr/lib/sendmail!\n";
print MAIL "From: CGI Skript\n";
print MAIL "To: " . $mailto . "\n";
print MAIL "Subject: Hello\n\n";
print MAIL "$data\n");
close(MAIL);
...
Testen/Debuggen
- Problem: Fehlermeldungen (z.B. Perl-Syntax-Fehler, Probleme
bei Öffnen oder Schreiben von Dateien, Probleme beim Aufruf
anderer Programme) werden in der Error/Log-Datei des Web-Servers
ausgegeben
- Das CGI-Skript sollte daher vorher auf dem lokalen Server gut
getestet werden
- Auf einem fremden Web-Server kann ggf ein "Wrapper"-Skript
helfen, das das zu testende CGI-Skript aufruft und dessen
Fehlermeldungen (stderr) ausgibt
Weiterführende Links
- Spezifikationen
- Kurse, Tutorials
- Perl
- Web-Server
- Beispiel-CGI-Skripte
- KNF