Aus Linux-Magazin 05/2005

Apache-Interna mit Mod_perl programmieren

Wer bei der Webentwicklung alle Schritte vom Request bis zum Response im Detail kontrollieren will, muss sich tief ins Innere des Servers begeben. Perl-Programmierer greifen dafür zu Mod_perl.

Nachdem der Webserver Apache im April 2002 die stabile Version 2 erreicht hat, biegt nun auch Mod_perl 2 in die Zielgerade ein[1]. Wer das Modul nicht kennt, denkt vielleicht, es handle sich um ein Pendant für PHP oder CGI. Das ist zwar nicht falsch, doch »mod_perl« ist wesentlich mächtiger. Webentwickler können damit in alle Phasen der Bearbeitung einer Anfrage eingreifen und Dinge tun, die mit CGI-Skripten oder Ähnlichem unmöglich sind.

Aufpasser und Arbeiter

Apache 2 benutzt mit seinen Multi-Processing-Modulen (MPM) ein Arbeitsmodell, das auf Prozesse oder auf Threads setzt[2]. Der Server arbeitet nach einem Supervisor-Worker-Prinzip: Direkt nach dem Start ist nur der Supervisor aktiv. Er liest die Konfigurationsdatei und startet dann eine Reihe so genannter Worker. Bei ihnen handelt es sich um Prozesse (Prefork MPM) oder Threads (Threaded MPM). Neben reinen Varianten gibt es auch Mischformen.

Nach der Konfiguration überwacht der Supervisor die einzelnen Worker, die eingehende Webrequests bearbeiten. Er startet und beendet Worker nach Bedarf. Abbildung 1 veranschaulicht das Modell und zeigt mögliche Eingriffspunkte für Apache-Perl-Programmierer. Der Artikel bezieht sich im Folgenden auf das Prefork-MPM und Mod_perl-2.0RC3. Geringfügige Änderungen am API sind bis zur endgültigen Version möglich, aber ziemlich unwahrscheinlich.

Jede Phase stellt einen bestimmten Abschnitt der Aktivität des Servers oder in der Bearbeitung einer Anfrage dar. Module können Handler für diese Phasen registrieren, die Apache zum entsprechenden Zeitpunkt abarbeitet. Konfigurationsanweisungen nach dem Muster »Perl NameHandler« weisen Mod_perl dazu an, in den entsprechenden Phasen Funktionen auszuführen. Dabei ersetzt man » Name« durch den entsprechenden Phasennamen. Beispielsweise registriert ein »PerlOpenLogsHandler« in der Apache-Konfiguration eine Funktion für die »OpenLogs«-Phase.

Direkt nach dem Start liest der Apache-Server die Konfiguration ein. Der Perl-Interpreter startet normalerweise am Anfang der »OpenLogs«-Phase. Es gibt allerdings zwei Fälle, in denen er früher startet: bei einem Block »<Perl>…</Perl>« in der Konfigurationsdatei sowie bei einer »PerlLoadModule«-Anweisung. Im Anschluss an die »PostConfig«-Phase startet Apache neu, um zu testen, ob ein Restart auch zu einem späteren Zeitpunkt erfolgreich wäre. Er durchläuft die »OpenLogs«- und »PostConfig«-Abschnitte also mehrmals.

Normalerweise öffnen Module in der »OpenLogs«-Phase ihre Logfiles. Auch Apache selbst beginnt dann damit, seine Logfiles »TransferLog« und »ErrorLog« zu schreiben. Über die »PerlOpenLogsHandler«-Anweisung können Perl-Module hier zum ersten Mal in den Ablauf eingreifen.

Konfiguration ändern

Danach tritt Apache in die »PostConfig«-Phase ein. In ihr ist sein Konfigurationsbaum bereits vollständig eingelesen. Hier kann ein Perl-Modul also auch auf die Konfiguration anderer Module zugreifen. Der in Listing 1 gezeigte Ausschnitt aus der Apache-Konfiguration fügt den »ServerTokens« den Wert der »User«-Anweisung hinzu. Diese Zeilen gehören am besten in eine separate Konfigurationsdatei, die Apache beim Starten liest, zum Beispiel in die »/etc/httpd/conf.d/perltest.conf«.

Damit das Beispiel funktioniert, muss die Konfigurationsvariable »ServerTokens« auf »Full« gesetzt sein (Zeile 12). Viele Distributionen setzen diese Direktive auf »OS«, um nicht mehr Informationen preiszugeben als nötig. Nach dem Ausprobieren sollte man also wieder den Defaultwert einstellen. Gibt es Probleme mit dem Beispiel, hilft der Kasten “Fehlersuche und Module” weiter.

Die Auswirkung dieser Konfiguration zeigt ein Aufruf mit dem Kommandozeilen-Client »curl«. Die Option »-I« sorgt dafür, dass das Programm die HTTP- Header ausgibt:

> curl -I http://localhost
HTTP/1.1 200 OK
Date: Sun, 16 Jan 2005 12:10:28 GMT
Server: Apache/2.0.52 (Linux/SUSE) 
  User/wwwrun mod_ssl/2.0.52 
  ...

Mit dem Beispiel-Handler zeigt Apache nun auch den Benutzernamen an, den der Server annimmt, hier »wwwrun«. Ansonsten läuft der Code in dieser Phase mit der User-ID, mit der Apache gestartet wurde, also meist Root.

Abbildung 1: Die Supervisor-Komponente von Apache startet mehrere Worker. Sie laufen bis zu ihrem Lebensende in einem Zyklus und bedienen Webrequests.

Abbildung 1: Die Supervisor-Komponente von Apache startet mehrere Worker. Sie laufen bis zu ihrem Lebensende in einem Zyklus und bedienen Webrequests.

Apache kennt noch eine »PreConfig«-Phase, die jedoch mit Perl nicht nutzbar ist, da zu dieser Zeit noch kein Perl-Interpreter läuft. Während die beiden bisher behandelten Abschnitte Sache des Supervisors sind, betreffen alle anderen nur die Worker.

Fehlersuche und
Module

Mod_perl richtet sich nach dem objektorientierten Modell. Allerdings hat es einige Eigenheiten, die das Beispiel der »Apache::RequestRec«-Klasse demonstriert. So werden alle Handler des HTTP-Anfragezyklus mit einem Objekt dieser Klasse als Parameter aufgerufen. Das Modul enthält aber nur die Basisklasse. Für mehr Funktionalität muss das Perl-Skript weitere Module laden. Diese erzeugen aber keine neuen Klassen, sondern erweitern »Apache ::RequestRec«. So verhält es sich auch mit anderen Mod_perl-Klassen. Einige Beispiele für solche Erweiterungsmodule sind »Apache::Filter« und »Apache::RequestUtil«.

Dieser Ansatz hat einige praktische Auswirkungen bei der Fehlersuche, wenn zum Beispiel im »error_log« eine Zeile ähnlich der folgenden auftaucht:

[client 127.0.0.1] Can't locate object 
method "dir_config" via package 
"Apache::RequestRec" at 
/etc/httpd/conf.d/perltest.conf line 7

Das Perl-Modul findet offensichtlich die Methode »dir_config« nicht, obwohl das Modul »Apache::RequestRec« eingebunden ist. Der Grund ist, dass das Erweiterungsmodul »Apache::RequestUtil« die Methode implementiert.

Methoden finden mit Perl

Mod_perl hilft mit einem Modul dabei, Methoden zu finden:»ModPerl::MethodLookup«, das die Funktion»print_method« implementiert. So sucht folgendesKommando nach der fehlenden »dir_config«-Methode:

perl -MApache2 -MModPerl::MethodLookup 
 -e print_method dir_config

Dieses Konstrukt findet die gesuchten Methoden. Ein Bash-Alias vereinfacht den Prozess nochmals:

alias lookup="perl -MApache2 
 -MModPerl::MethodLookup -e print_method"

Nun genügt zur Suche »lookup Name«:

> lookup dir_config
There is more than one class with method 
 'dir_config'
try one of:
        use Apache::RequestUtil ();
        use Apache::ServerUtil ();

Das Ergebnis: »mod_perl« findet zwei Module, die eine Methode dieses Namens implementieren. Um zu entscheiden, welche die richtige ist, hilft ein Blick in die Dokumentation des Moduls – je nach Installation mit »perldoc«, »mp2doc« oder »man«.

Die passende Dokumentation ist selbstverständlich auch auf der Webseite von Mod_perl zu finden. Der Modulname ist in diesem Fall hinter der Adresse [http://perl.apache.org/docs/2.0/api/] einzutragen. Allerdings sind dabei die Doppelpunkte »::« zwischen den Klassennamen durch einen Schrägstrich »/« zu ersetzen, also zum Beispiel für das Modul »Apache::RequestUtil«: [http://perl.apache.org/docs/2.0/api/Apache/RequestUtil]

Bevor ein Worker in den Anfragezyklus eintritt, bearbeitet er die »ChildInit«-Phase (Konfigurationsanweisung »PerlChildInitHandler«). Da jeder Worker diese Phase nur einmal durchläuft, eignet sie sich zum Belegen globaler Ressourcen wie etwa Datenbankverbin-dungen. »ChildInit« ist die erste Gelegenheit, Perl-Code mit der richtigen Serveridentität auszuführen: Der Server hat »User«- und »Group«-Anweisungen dann schon abgearbeitet.

Hat ein Worker den Anfragezyklus beendet, tritt er in die »ChildExit«-Phase ein (Konfiguration: »PerlChildExitHandler«). Sie bietet sich an, um globale Ressourcen wieder freizugeben. In diesen Zustand geht ein Worker übrigens nicht nur beim Beenden von Apache über: Mit der Anweisung »MaxRequestsPerChild« kann (und sollte) der Programmierer die Anzahl der Requests, die ein einzelner Worker bearbeitet, begrenzen.

Anfragen bearbeiten

Für Perl-Programmierer ist vor allem der Anfragezyklus interessant. Er besteht im Grunde nur aus zwei Phasen: »PreConnection« und »ProcessConnection« (Abbildung 2). In »PreConnection« tritt ein Worker ein, wenn er einen Verbindungswunsch angenommen hat. Er hat dann noch keine Daten gelesen, es besteht lediglich die TCP-Verbindung zum Client (Browser). In dieser Phase kann er sich zum Beispiel aufgrund der Client-IP-Adresse entscheiden, ob die Verbindung abzulehnen ist. Module können in dieser Phase die Verbindungsdatenstrukturen von Apache ändern, beispielsweise Filter hinzufügen.

Listing 1:
»PerlPostConfig«-Handler

01 <Perl>
02 package My::VersionComponent;
03 use Apache::Directive ();
04 
05 sub add {
06   $_[3]->add_version_component
07     ( 'User/'.Apache::Directive::conftree()->lookup ('User') );
08 }
09 </Perl>
10 
11 PerlPostConfigHandler My::VersionComponent::add
12 ServerTokens Full
Abbildung 2: Ein Perl-Modul kann sich kurz vor der Verarbeitung einer Verbindung in den Ablauf einklinken (»PreConnection«) oder sie vollständig selbst bearbeiten (»ProcessConnection«).

Abbildung 2: Ein Perl-Modul kann sich kurz vor der Verarbeitung einer Verbindung in den Ablauf einklinken (»PreConnection«) oder sie vollständig selbst bearbeiten (»ProcessConnection«).

Zu diesem Zeitpunkt ist die Anfrage schon einem eventuell vorhandenen IP-basierten virtuellen Server zugeordnet, da zumindest die IP-Adresse des Servers bekannt ist. »ServerName«-basierte virtuelle Hosts (Konfiguration: »NameVirtualServer«) sind noch nicht initialisiert. Sie benötigen das Host-Headerfeld des HTTP-1.1-Protokolls, das jetzt noch nicht zugänglich ist.

In der »ProcessConnection«-Phase wird die Anfrage dann endlich bearbeitet. Ein Modul kann diesen Bereich vollständig übernehmen und so auch ein völlig anderes Protokoll implementieren. Apache::SMTP beispielsweise implementiert auf diese Weise einen Mailserver auf Apache-Basis. Im Normalfall übernimmt aber der Apache-interne HTTP-Anfragezyklus die »ProcessConnection«-Phase. Dieser Zyklus besteht selbst aus zwölf Abschnitten (Abbildung 3).

Während Apache für jede Client-Verbindung die »PreConnection«- und »ProcessConnection«-Phasen nur einmal bearbeitet, durchläuft er den HTTP-Anfragezyklus für jede HTTP-Anfrage. Diese Unterscheidung ist wichtig, denn HTTP1.1 erlaubt es, pro Verbindung mehrere Anfragen zu übermitteln und zu beantworten. Außerdem kann Apache intern selbst virtuelle Anfragen erzeugen, die einen leicht modifizierten Zyklus durchlaufen und »PostRead-Request« und »Log« überspringen.

Beispielsweise erzeugt das Modul »mod_dir« solche virtuellen Anfragen: Gibt ein Benutzer im Browser die Adresse »/ x/ y/ z/« ein, will er meist die HTML-Seite »/ x/ y/ z/index.html« sehen. Um diesen Wunsch zu erfüllen, registriert »mod_dir« einen passenden Handler für die »Fixup«-Phase. Bei einem Aufruf von »/ x/ y/ z/« erkennt der Handler, dass damit ein Verzeichnis gemeint ist, und probiert für alle mit »DirectoryIndex« konfigurierten Dokumente eine virtuelle Anfrage. Ist eine davon erfolgreich, gibt der Handler das gefundene Dokument aus.

Alle während des HTTP-Anfragezyklus aufgerufenen »mod_perl«-Handler sind einfache Perl-Funktionen. Sie starten mit einem Argument vom Typ »Apache::RequestRec«, das die Anfrage repräsentiert.

Überspringen von Phasen

Normalerweise durchläuft Apache den HTTP-Anfragezyklus linear. Falls in einem Bereich ein Fehler auftritt, kann ein Modul die Bearbeitung abbrechen und sofort in die Logging-Phase springen. Abschnitte können auch leer sein und nur zum nächsten weiterleiten.

Falls kein spezieller Handler für die »ProcessConnection«-Phase definiert ist, wechselt Apache nach dem »PreConnection«- in den »PostReadRequest«-Abschnitt. Zu diesem Zeitpunkt hat er bereits die Anfrage mit allen HTTP-Headerfeldern eingelesen. Damit ist die Anfrage nun auch einem eventuell vorhandenen »ServerName«-basierten virtuellen Server zugeordnet. Der Inhalt einer Anfrage (zum Beispiel bei »POST«-Requests) steht noch nicht zur Verfügung.

Einige Module nutzen die »PostReadRequest«-Phase für Initialisierungen des Anfragezyklus. So initialisiert Mod_unique_id dort die Umgebungsvariable »UNIQUE_ID«, die eine Anfrage eindeutig kennzeichnet. Sie ist dann in den folgenden Abschnitten verfügbar.

Nach der »PostReadRequest«-Phase folgt die URI-Übersetzung in der Translation. Hier können Module den angefragten URI verändern. So mächtige Module wie Mod_rewrite oder Mod_alias verrichten den Großteil ihrer Arbeit in der »Trans«-Phase. In Apache 1.3 hatte sie zusätzlich noch die Aufgabe, den URI auf ein Objekt im Dateisystem abzubilden. In Apache 2 übernimmt allerdings »MapToStorage« diese Aufgabe. Benutzt ein Modul dazu trotzdem die URI-Translation, überspringt Apache den »MapToStorage«-Abschnitt.

URLs übersetzen

Bis zu dieser Phase können Module verzeichnisbasierte Konfigurationsanweisungen nicht auswerten, da die Abbildung auf das Dateisystem noch aussteht. Deshalb ist zum Beispiel die »PerlTransHandler«-Anweisung in einem »Directory«-Block nicht erlaubt. Die URI-basierten Konfigurationen (»Location«-Blocks) wertet Apache zweimal aus: einmal vor der URI-Translationsphase und noch einmal nach »MapToStorage«, wenn der Server auch die Direktiven »Directory« und »Files« sowie ».htaccess« auswertet. Da Module mitunter in der Translationsphase den Anfrage-URI verändern, kann beim zweiten Durchlauf durchaus ein anderer »Location«-Block ausgewertet werden. Listing 2 zeigt dafür ein Beispiel.

Abbildung 3: Der HTTP-Anfragezyklus besteht aus zwölf Phasen, in die sich Mod_perl-Programme einklinken können.

Abbildung 3: Der HTTP-Anfragezyklus besteht aus zwölf Phasen, in die sich Mod_perl-Programme einklinken können.

In der URI-Translationsphase verändert das Modul den URI »/L1« zu »/L2« (Zeilen 16 bis 18). Der Aufruf von »http:// Servername/L1« zeigt im »error_log«:

PostReadRequest: Location=0
Trans: Location=1
HeaderParser: Location=2

Zu Beginn von »PostReadRequest« hat Apache noch keinen »Location«-Block ausgewertet, deshalb hat »Location« den Wert 0. In der URI-Übersetzungsphase »Trans« zeigen sich die Auswirkungen von »Location /L1«. Schließlich setzt das Modul vor dem Abschnitt »HeaderParser« den endgültigen Wert 2.

In der »HeaderParser«-Phase steht endlich die volle Server-Konfiguration zur Verfügung. Daher bietet sie sich für Initialisierungen an, die alle Apache-Einstellungen benötigen. Es gibt sogar eine eigene Mod_perl-Anweisung (»PerlInitHandler«), die sich außerhalb eines »<Directory>«-Blocks wie ein »PerlPostReadRequestHandler« verhält. Innerhalb eines solchen Blocks führt »PerlInitHandler« zum gleichen Ergebnis wie »PerlHeaderParserHandler«.

Zugriffskontrolle

Die nächsten drei Phasen (»Access«, »Authen« und »Authz«) regeln die Zugriffsberechtigungen. »Access« trifft Entscheidungen aufgrund der Verbindungsparameter und der HTTP-Anfrage, die Identität des Clients ist noch ungeklärt. Hier ist die richtige Gelegenheit, um zum Beispiel den Zugriff auf das Verzeichnis »/admin« aus dem Netz 192.168.* nur von 9:00 bis 18:00 Uhr zu erlauben. Das Modul »mod_access« arbeitet in der »Access«-Phase.

Die »Authen«-Phase (Authentication) klärt die Identität des Benutzers, gewöhnlich über die in RFC2617 beschriebenen HTTP-Header. Module können an dieser Stelle aber auch andere Informationen heranziehen, zum Beispiel Cookies. Die erfolgreiche Beendigung von »Authen« entspricht einer erfolgreichen Authentifizierung. In der »Authz«-Phase (Authorization) ermitteln Module, ob der Benutzer Zugriff auf eine bestimmte Ressource erhalten darf.

Nach der Überprüfung der Zugriffsberechtigung beginnt Apache die Antwort (Response) zu erzeugen. In der Typ-Überprüfungsphase »Type« ermittelt er den voraussichtlichen Content-Type. Das übernehmen meist die Standardmodule Mod_mime oder Mod_mime_magic, indem sie Namen oder Inhalt des auszuliefernden Dokuments untersuchen.

Die »Fixup«-Phase schließt die Vorbereitung der Antwort ab. Sie ist der letzte mögliche Eingriffspunkt für Module. Hier realisiert »mod_rewrite« die Umschreibregeln (»RewriteRule«) aus »Directory«-Blocks oder »SetEnv«-Anweisungen von Mod_env.

Die folgende »Response«-Phase setzt die Antwort zusammen und schickt sie an den Browser. Die meisten Webanwendungen (JSP, PHP …) laufen nur in dieser Phase, was noch einmal den Unterschied zu Mod_perl verdeutlicht.

Der »Log«-Abschnitt schreibt die bekannten Protokolldateien. In der »Cleanup«-Phase gibt Apache belegte Ressourcen wieder frei. Bei ihr handelt es sich eigentlich gar nicht um eine Apache-Phase. Den entsprechenden Handler ruft »mod_perl« einfach direkt vor der Freigabe des Anfrage-Objekts auf. Dabei ist die Antwort vollständig an den Browser übertragen und die Verbindung schon geschlossen – sofern sie nicht vom Typ Keep-Alive war.

Laut Mod_perl-Dokumentation eignet sich diese Phase für länger dauernde Aufräumarbeiten. Bei Keep-Alive-Verbindungen und dem Prefork-MPM trifft das aber nicht zu, denn Apache ist weiterhin beschäftigt. Er kann erst dann einen neuen Anfragezyklus starten, wenn »Cleanup« abgeschlossen ist.

Apache-Filter

Filter sind Funktionen, die den Datenstrom vom Browser zum Server und umgekehrt on the Fly bearbeiten, bevor er die eigentlichen Verarbeitungsphasen erreicht respektive nachdem er diese verlassen hat. Damit ähneln sie den bekannten Unix-Programmen »sed« und »awk«, die sich auf der Kommandozeile mit Pipes verketten lassen. Das Apache-Modul Mod_ext_filter bietet sogar die Möglichkeit an, solche Programme als Filter in Apache einzubinden. Grundsätzlich unterscheidet Apache zwischen Input- und Output-Filtern. Input-Filter bearbeiten den Datenstrom vom Browser zum Server, Output-Filter den in entgegengesetzter Richtung.

Listing 2:
Location-Auswertung

01 <Perl>
02 use Apache::RequestRec;
03 use Apache::RequestUtil;
04 package My::Location;
05 
06 sub postreadrequest {
07   my $r=shift;
08 
09   warn "PostReadRequest: Location=".$r->dir_config('Location')."n";;
10   return Apache::DECLINED;
11 }
12 
13 sub trans {
14   my $r=shift;
15 
16   if( $r->uri eq '/L1' ) {
17     $r->uri('/L2');
18   }
19   warn "Trans: Location=".$r->dir_config('Location')."n";;
20   return Apache::DECLINED;
21 }
22 
23 sub headerparser {
24   my $r=shift;
25 
26   warn "HeaderParser: Location=".$r->dir_config('Location')."n";;
27   return Apache::DECLINED;
28 }
29 </Perl>
30 
31 PerlPostReadRequestHandler My::Location::postreadrequest
32 PerlTransHandler My::Location::trans
33 PerlHeaderParserHandler My::Location::headerparser
34 
35 PerlSetVar Location 0
36 
37 <Location /L1>
38 PerlSetVar Location 1
39 </Location>
40 
41 <Location /L2>
42 PerlSetVar Location 2
43 </Location>

Mod_perl kennt zwei Filterklassen: verbindungs- und anfrageorientierte. Verbindungsorientierte Filter können den gesamten Datenstrom bearbeiten, der über eine Verbindung läuft. Sie haben Zugriff auf alle HTTP-Header, müssen aber auch das HTTP-Protokoll beherrschen, wenn sie die Daten ändern wollen. Anfrageorientierte Filter dagegen sehen nur den Inhalt einer Anfrage oder Antwort. Beispiele für anfrageorientierte Filter sind Mod_include oder Mod_deflate. Das Modul Mod_ssl realisiert einen verbindungsorientierten Filter.

Das Perl-API für Apache-Filter ist nicht ganz so mächtig wie sein C-Gegenstück. Deshalb soll die Einteilung in die beiden für Perl-Programmierer wichtigen Klassen genügen. Diese Beschränkung ist auch den Mod_perl-Programmierern als Problem bewusst. In der nächsten größeren Release werden sie das Modul deshalb wohl erweitern.

Die Filterbearbeitung lässt sich keiner konkreten Phase des Anfragezyklus zuordnen. Filter werden immer beim Lesen und Schreiben von Daten aufgerufen. Sie müssen damit rechnen, nicht alle Anfrage- oder Antwortdaten auf einmal bearbeiten zu können. So ruft Apache einzelne Filter unter Umständen mehrmals pro Anfrage für unterschiedliche Datenblöcke auf.

Von der Theorie zur Praxis

Mod_perl bietet mehr als einfache CGI-Skripte. Es erlaubt dem Perl-Programmierer sich in alle Arbeitsschritte des Apache-Servers einzuklinken. Das Wissen um die Apache-Bearbeitungsphasen und die Filterarchitektur bilden dafür die Basis. Weitere Tipps finden sich im Online-Buch zu Mod_perl[3] sowie im gedruckten Werk[4], das allerdings nicht ganz auf dem neuesten Stand ist. Eine Fortsetzung dieses Artikels demonstriert Workshop-artig den Einsatz von Mod_perl 2 an einem voll funktionsfähigen Modul zum User-Tracking. (ofr)

Infos

[1] Mod_perl: [http://perl.apache.org]

[2] Apache-Schwerpunkt im Linux-Magazin 10/02, S. 29

[3] Online-Buch zu Mod_perl: [http://modperlbook.org/html/part5.html]

[4] Lincoln Stein, Doug MacEachern, “Writing Apache Modules with Perl and C”: O\’Reilly 1999

Der Autor

Dipl.-Inf. Torsten Förtsch arbeitet als Freiberufler für mehrere Websites. Seine ersten Programmiererfahrungen sammelte er vor vielen Jahren in Nowosibirsk und Dubna. Hin und wieder liefert er Patches zu Open-Source-Projekten wie Perl, Mod_perl, Curl, SSH und zum Linux-Kernel.

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben