Aus Linux-Magazin 06/2011

Open Search Server durchsucht das Web, Datenbanken und Files

© Pawel Szpytma, 123RF.com

Freie Suchmaschinen gibt es viele, doch was der Open Search Server zu bieten hat, sucht seinesgleichen. Dieser Artikel nimmt die noch recht junge Version der Indexer-Suite mit Management-GUI und XML-API unter die Lupe und zeigt, wie sich die Suche mit PHP in Webseiten integriert.

Paris, Februar 2010. Das französische Startup Jaeksoft nimmt seine Arbeit auf. Ein Jahr später veröffentlicht der Hersteller bereits Version 1.2 seiner Such- und Indizierungssuite Open Search Server [1]. Das jugendliche Stadium zeigt sich zwar noch an einigen ärgerlichen Ecken und Kanten, doch der üppige Funktionsumfang überrascht. Da zeigt sich dann, dass Entwickler bereits seit 2007 an dem Projekt arbeiten – bis 2010 allerdings hinter verschlossenen Türen.

Freies Indizieren

Der Open Search Server (OSS) scannt Webseiten, lokale Dateisysteme und Datenbanken. Sein Indexer versteht eine lange Liste von Dateiformaten, ein API ermöglicht den unkomplizierten und schnellen Zugriff auf die Ergebnisse sowie auf die meisten der zahlreichen Funktionen (Abbildung 1). Im Hintergrund werkelt Java in einem Tomcat-Server [2]. Dazu kommt die Lucene-Search-Engine [3], deren Query-Parser-Syntax und Score-Funktionen Admins und Entwickler nicht nur im Management-Interface nutzen können (siehe Kasten “Lucene”). Als Scheduler setzt OSS auf Quartz [4]. Das flotte und flexible GUI (Abbildung 2) ist mit Zkoss [5] implementiert und funktioniert mit allen Ajax-fähigen Browsern.

Enterprise-Support

Über die freie Variante hinaus, die ihrer modularen Natur gemäß auf einem ganzen Bündel von Lizenzen (darunter auch AGPL und GPLv3) aufbaut, bietet Hersteller Jaeksoft auch eine Enterprise-Version mit optionalem Support, SLAs und erweiterten Funktionen in Form von Zusatzmodulen an.

Ab 3600 Euro pro Jahr erhalten Kunden Basissupport (Silver), das “Enterprise Pack Platinum” kostet mehr als 6000 Euro, bietet aber neben kürzeren Reaktionszeiten auch Remote-Wartung, Monitoring und Weiterbildung in Form von vierteljährlichen Webinaren. Und natürlich hat der Hersteller auch Entwicklung, Implementierung und Optimierung von Zusatzmodulen im Angebot.

Voraussetzung sind ein funktionierender Webserver mit PHP5, »php5-curl« und einem Java Runtime Environment. Die Community-Edition ist schnell installiert: Von der Webseite lädt sich der Admin ein Tar.gz-File herunter (dieser Artikel testet die Version »open-search-server-1.2.1-r987.tar.gz« vom 30.3.2011), entpackt es auf einem Webserver und ruft an der Shell das Skript »start.sh« auf. Auf Windows erledigt dies »start.bat« .

Ein Init-Skript fehlt dem Paket, wer den Server permanent laufen lassen möchte, muss dafür noch selbst Hand anlegen. Leider gibt’s nur wenig mehr Details zur Installation im noch recht spärlichen Wiki von OSS [6].

Erster Start

Im Unterverzeichnis »apache-tomcat -6.0.32« des ausgepackten Archivs finden sich alte Bekannte: Hier liegt der vorkonfigurierte Tomcat-Applikationsserver mit seinen Binaries, Logfiles und Config-Dateien. Wenn etwas nicht funktioniert, lohnt sich ein Blick in die Protokolldatei »catalina.out« . Hier hinterlässt der Kater deutliche Kratzspuren, wenn ihm etwas nicht passt. Die Indexe liegen unter »data« , dort findet sich auch ein Unterverzeichnis mit der Index-Konfiguration in Klartext-XML-Dateien. Hier lassen sich per Skript URLs und Patterns hinzufügen, aber danach ist ein Restart des OSS notwendig.

Abbildung 1: Lucene, Tomcat und ein flexibles API ergeben den Open Search Server.

Abbildung 1: Lucene, Tomcat und ein flexibles API ergeben den Open Search Server.

Voller Features: Das Web-Interface

Nach dem Start lauscht Tomcat auf dem Standardport 8080. Diesen Port sollte eine Firewall vor unbefugtem Zugriff schützen und ihn nur lokalen Diensten verfügbar machen. Wer mit seinem Browser auf die URL [http://localhost:8080] zugreift, bekommt das Management-Interface zu Gesicht, vorerst nur mit den Reitern »Index« und »Privileges« . Hier legt der Admin zunächst einen neuen Index oder einen privilegierten Benutzer an. Für Indexe stehen drei Templates zur Verfügung (»Empty index« , »file crawler« und »web crawler« ). Später kann er aus der Liste unten einen existierenden Index zum Bearbeiten auswählen. Mit geladenem Index bevölkern zahlreiche Reiter das Menü des OSS, ganz ähnlich wie in Abbildung 2.

Mangels Dokumentation ist der Admin mit den zahlreichen Tabs, Konfigurationsoptionen und Untereinträgen recht allein gelassen, doch die Templates und (meist) selbsterklärenden Funktionen erleichtern das Einarbeiten. Unter »Schema« editiert er Details der Suchfunktionen, in »Query« setzt er eigene Anfragen ab oder koordiniert beispielsweise die Form der Ergebnisausgabe. OSS kann die Ergebnisse zusammenfassen (»Query | Collapsing« ), wenn bestimmte Kriterien darauf schließen lassen, dass beispielsweise identische Webseiten vorliegen.

Abbildung 2: Der OSS durchforstet die Webseite des Linux-Magazins. Als irreführend erweist sich das Eingabefeld »Maximum number of URLs per host«: Wer hier zu hohe Werte eingibt, dem geht schnell der RAM aus.

Abbildung 2: Der OSS durchforstet die Webseite des Linux-Magazins. Als irreführend erweist sich das Eingabefeld »Maximum number of URLs per host«: Wer hier zu hohe Werte eingibt, dem geht schnell der RAM aus.

Als Modi dafür stehen »full« , »cluster« und »optimized« zur Verfügung. Welcher sich für ein Projekt besser eignet, lässt sich mangels Dokumentation nur durch individuelles Ausprobieren herausfinden. Die »Snippet fields« (bei einer aktiven Abfrage ebenfalls im Reiter »Query« ) bestimmen das Format der Ausgabe. Sowohl die Felder als auch deren Länge kann der Admin hier festlegen und so die Ergebnislisten konfigurieren.

Im Reiter »Crawler« trägt er das Ziel seiner Suchmaschine ein: Webseiten, Datenbanken oder ein Filesystem, wobei ihm zahlreiche Filter bei der Anpassung helfen. Abbildung 2 zeigt das Unterfenster »Crawl process« einer Maschine, welche die komplette Linux-Magazin-Webseite indiziert.

Dabei erwies sich eine Einstellung als irreführend: Wer hier glaubt, für einen umfangreichen Webserver müsse er die maximale Anzahl der Webseiten pro Host erhöhen, tappt in die Falle. Der Wert sagt nur, wie viele Seiten OSS in einer Session holen soll, bevor er diese seinem Index hinzufügt. Wer das zu hoch dreht, braucht viel RAM oder bekommt irgendwann die Fehlermeldung aus Abbildung  3, häufig blieben OSS oder der Java-Prozess auch einfach hängen, wenn ihnen der Speicher ausging.

Abbildung 3: Zkoss meldet »Java heap space« – meist deutet diese Fehlermeldung auf zu wenig Arbeitsspeicher für die JVM hin.

Abbildung 3: Zkoss meldet »Java heap space« – meist deutet diese Fehlermeldung auf zu wenig Arbeitsspeicher für die JVM hin.

Wer große Webseiten indizieren will, sollte also genug Speicherriegel im System vorhalten oder etwas Zeit einplanen. Um die Java Virtual Machine mit 2 GByte RAM zu versorgen, braucht es im Startskript zusätzlich die beiden folgenden Zeilen:

CATALINA_OPTS="-Xms2G -Xmx2G -server" export CATALINA_OPTS

Mehr als 2 GByte sind nur mit 64-Bit-Betriebssystem und 64-Bit-Java möglich. Dann aktivieren die folgenden Optionen 6 GByte Arbeitspeicher für Java:

CATALINA_OPTS="-d64 -Xms6G -Xmx6G -server" export CATALINA_OPTS

Monitoring-Tools wie das simple Darkstat (Abbildung 4, [7], in den Debian-Repositories) überwachen gleichzeitig den erzeugten Traffic. Manche Firewalls oder Webserver klassifizieren allzu häufige systematische Anfragewellen als DoS-Angriff und weisen den Client ab.

Abbildung 4: Das Monitoring-Tool Darkstat zeigt: Schön vorsichtig, mit deutlich unter 100 KByte/s saugt der lokale Open Search Server den zu crawlenden Webserver aus, weil der Admin in der Konfiguration unter anderem die maximale Thread-Anzahl und die Abfragefrequenz beschränkt hat.

Abbildung 4: Das Monitoring-Tool Darkstat zeigt: Schön vorsichtig, mit deutlich unter 100 KByte/s saugt der lokale Open Search Server den zu crawlenden Webserver aus, weil der Admin in der Konfiguration unter anderem die maximale Thread-Anzahl und die Abfragefrequenz beschränkt hat.

Beim Indizieren unterstützt OSS laut Hersteller 16 Sprachen, Wörter kann es sowohl komplett als auch in Fragmenten oder Varianten der Grundform erkennen (Lemmata, [8]). Die Liste der Dokumentformate umfasst XML, HTML/XHTML, PDF, Microsoft Word, Powerpoint, Open Office, RTF, Plaintext, Torrent, Audiofiles (MP3/MP4, OGG, FLAC, WMA) und viele andere. Die komplette Liste der jeweiligen Installation findet sich unter »Schema | Parser List« .

Query und Lemma

Abfragen lassen sich übers XML-Interface via HTTP-Queries abwickeln und mit einer PHP-Client-Library in eigene Webseiten integrieren. Doch auch das Management-Interface hat unter »Query | Edit | Query« eine Eingabemaske (»Pattern Query« ), mit der der Admin im Index suchen kann. Listing 1 zeigt die Default-Vorgabe der früheren Versionen, sie funktioniert aber auch in 1.2 und lässt sich leicht erweitern. »$$« steht dabei für den Suchbegriff, ein »^« gefolgt von einer Zahl definiert die Gewichtung, Schlüsselbegriffe wie »title« oder »urlSplit« bestimmen, wo und wie genau der Suchbegriff vorkommen soll.

Listing 1

OSS Query

01 title:($$)^10 OR title:("$$")^10 02 OR 03 titleExact:($$)^10 OR titleExact:("$$")^10 04 OR url:($$)^5 OR 05 url:("$$")^5 06 OR urlSplit:($$)^5 OR urlSplit:("$$")^5 07 OR 08 urlExact:($$)^5 09 OR urlExact:("$$")^5 10 OR content:($$) OR 11 content:("$$") 12 OR 13 contentExact:($$) OR contentExact:("$$")

Der Teufel steckt dabei oft im Detail: Während Urlsplit die URL [http://www.open-search-server.com] auf »http« , »www« , »ope« , »search« und »serv« reduziert (lemmatisiert), interpretiert Urlexakt die gleiche URL auf »http« , »www« , »open« , »search« und »server« . Laut den Entwicklern verwendet OSS dabei verschiedene Analyzer: Der »text« -Analyzer erkennt auch ähnliche Schreibweisen, während »urlExact« , »titleExact« und »contentExact« auf den Standard-Analyser zurückgreifen.

Unter dem Reiter »Scheduler« trägt der Admin Cronjobs ein, die den OSS steuern, zum Beispiel für die empfehlenswerten Rebuilds des Indexes (»Optimize« ). In »Runtime« erhält er wertvolles Feedback über und Zugriff auf den Zustand von Index, Cache und System. Auch für HA-Setups ist OSS vorbereitet: Auf dem Reiter »Replication« finden sich Eingabefelder für URLs und Indexnamen weiterer OSS-Instanzen.

API und PHP

In den Unterverzeichnissen »open-search-server/examples/php/OSSquery« und »open-search-server/php/example« liegen einige Beispiele für simple PHP-Skripte, die sich in eigene Webseiten integrieren lassen und so die Suchfunktion aus dem Management-Interface in den Browser des Clients bringen.

In »webSearch.php« beispielsweise trägt der Admin seinen Index als Standard ein, und schon hat er ein (zumindest teilweise) funktionierendes Suchfrontend. Allerdings hatte es im Test schon mit Umlauten Probleme und konnte die Parameter der Lucene-Query-Language nur bedingt umsetzen. Das gelingt der Query im Web-GUI besser, aber auch nicht immer (Abbildung 5).

Abbildung 5: Wer direkt in der Query versucht speziellere Lucene-Parameter zu verwenden (im Beispiel die unscharfe Suche mit »~« ), der scheitert bisweilen an der OSS-Implementierung.

Abbildung 5: Wer direkt in der Query versucht speziellere Lucene-Parameter zu verwenden (im Beispiel die unscharfe Suche mit »~« ), der scheitert bisweilen an der OSS-Implementierung.

Zu empfehlen ist dafür das XML-API. Mit ihm können Programmierer in nahezu jeder beliebigen Sprache den Index durchsuchen und die Ergebnisse darstellen. An den passenden HTTP-Request hängen sie einfach via »GET« -Request die erforderlichen Parameter:

http://localhost:8080/select?use=  Index  &qt=  Query &q=  Suchbegriff .

Auf derlei Anfragen liefert der Server eine XML-Datei zurück, welche die Treffer und die entsprechenden Vorschautexte (die Snippets) enthält. Ein Programmierer braucht also nur

  • die Usereingaben zu filtern und zu prüfen (Vorsicht, das API erlaubt auch das Löschen von Dokumenten aus dem Index!),
  • den String für die Abfrage des API zusammenzubauen,
  • das zurückgelieferte XML-Dokument zu parsen und formatiert auszugeben.

Listing 2 zeigt einen Auszug aus einem einfachen PHP-Skript, das die Query für das API zusammenstellt. In den Zeilen 4 und 20 enthält es einen minimalen Schutz vor schädlichem Code. Gegen Cross Site Scripting hilft Zeile 4, Zeile 20 löscht den Parameter »delete« , falls es einem Angreifer dennoch gelungen ist, ihn einzuschleusen. Der assoziative Array »Params« stellt alle Parameter für die API-Abfrage zusammen, »use« , »qt« und »q« sind verpflichtend, die anderen optional. Das Query-Template »search« steht von Anfang an im Open Search Server zur Verfügung und bietet eine sehr einfache Abfrage für den Index.

Listing 2

build-query.php

01 function build_query($q){ 02 $params=array(); // Für alle Parameter 03 // Entferne Tags 04 $this->q=substr(trim(strip_tags($q),0,80)); 05 // Grund-Parameter 06 $params['use']='meinIndex'; // verwendeter Index 07 $params['qt']='search'; // verwendetes Query-Template 08 // Collapsing 09 $params['collapse.mode']='cluster'; 10 $params['collapse.field']='host'; 11 $params['collapse.max']=1; 12 // Pagination 13 if(isset($_GET['page'])) $params['start']=((int) $_GET['page']*10)-9; 14 else $params['start']=1; 15 $params['rows']=$this->rpp; 16 $params['query']=trim($q); // der eigent­liche Suchbegriff 17 $params['sort']='score'; // für umgekehrte Reihenfolge Minuszeichen voranstellen 18 $host='http://127.0.0.1:8080/select'; // URL des OSS-Host 19 // Falls jemand den Parameter "Delete" einge­schmuggelt hat: 20 unset($params['delete']); 21 $this->query=$host.'?'.http_build_query($params); 22 }

Jetzt gibt der Admin im Backend des OSS im Reiter »Query | Returned Fields« an, welche Felder er in der XML-Antwort zurückgeliefert haben will. In dem einfachen Beispiel oben sind das die beiden Felder »url« und »host« . Die drei Parameter für das Collapsing geben an, ob OSS Treffer zusammenfassen soll. Das maßgebliche Feld ist frei wählbar, zum Beispiel der Host oder der Titel einer Seite. Auf diese Weise lassen sich im Ergebnis ähnliche Treffer auch erst nach einem weiteren Klick anzeigen, was die Übersichtlichkeit deutlich erhöht.

In Listing 2 passiert das in den Zeilen 9 bis 11. Beim Modus »cluster« ist als Maximalanzahl nur eine 1 möglich, gleichwohl darf dieser Parameter aber nicht fehlen. Die vorletzte Zeile verknüpft schließlich die Query-Parameter mit der Host-URL und kodiert sie. Um die so erstellte API-Abfrage auszuführen, genügt ein einfacher Aufruf mittels »simplexml_load_file($this->query)« . Er liefert ein XML-Dokument zurück, zum Beispiel das aus Listing 3.

Listing 3

XML-Antwort

01 <?xml version="1.0" encoding="UTF-8"?> 02 <response> 03 <header> 04 <status>0</status> 05 <query>Query_Name</query> 06 </header> 07 <result name="response" numFound="111" collapsedDocCount="0" start="1" rows="10" maxScore="NaN" time="11"> 08 <doc score="0.4523" pos="1"> 09 <field name="url">http://www.meinserver.de/Pfad/Datei.html</field> 10 <field name="host">www.meinserver.de</field> 11 <snippet name="title" highlighted="yes">Titel der Seite</snippet> 12 <snippet name="content" highlighted="yes">Kurze Voransicht des Treffers und seiner Nachbarschaft...</snippet> 13 </doc> 14 </xml>

Die eigentlichen Ergebnisse stehen hier innerhalb von »result« als »doc« zur Verfügung. Eine »foreach ($hits->result->doc as $doc)« -Schleife geht Eintrag für Eintrag durch. Mit den beiden Beispiel-PHP-Dateien vom Online-Plus des Linux-Magazins funktionieren dann auch Lucene-Features wie die unscharfe Suche mit »~« , die bisher – wie in Abbildung 5 – noch Probleme bereitete.

Neu in 1.2 und Roadmap

In die jüngste Version 1.2 halten einige lobenswerte Features Einzug. Der Web-Crawler zeigt jetzt, wann er eine Seite im Index aktualisiert hat, merkt sich anhand von Unique Keys, welche Seiten identisch sind, und erlaubt das Ignorieren von »robots.txt« -Dateien. Der Datenbank-Crawler versteht jetzt auch SQL-Querys, sowohl Pattern- als auch Exklusion-Listen lassen sich deaktivieren und die Abfragen erkennen ähnliche Dokumente besser.

Das »modified« -Tag stellt aktuell noch ein mittleres Problem dar. Es erkennt bisher nur, ob eine Seite verändert wurde, nicht aber, ob vielleicht nur die Anzeige darin ausgetauscht wurde oder der Text sich verändert hat, weil beispielsweise ein RSS-Feed integriert ist. Bei eigenen Webservern lässt sich das mit CSS verbessern, indem ein Div-Tag Menüs, Werbung und Feeds vor dem Indexer verbirgt:

<div class="opensearchserver.ignore"></div>

Zahlreiche Features sind in Arbeit: Eine Art Pagerank (basierend auf Lucenes Score-Funktion) ist laut Entwickler Emmanuel Keller schon teilweise integriert. Fertig sind wohl die Funktionen »score« , »ord« , »rord« , »byte« , »float« , »int« und »short« . Ein gültiges Beispiel in einer Query wäre demnach »score() + rord(‘modified_date’)« . Die nächste Version bekommt außerdem eine Screenshot-Funktion und bringt eine Rendering-Extension (Abbildung 6) mit.

Abbildung 6: Schon im GUI formatiert der geplante Renderer in künftigen Versionen die Suchergebnisse.

Abbildung 6: Schon im GUI formatiert der geplante Renderer in künftigen Versionen die Suchergebnisse.

Darauf zu warten mag sich lohnen, vor allem die Roadmap macht Lust auf mehr. Der Open Search Server ist sicherlich noch nicht perfekt, aber auf einem guten Weg. Und er ist schnell: Auf einem Desktop-PC gestartet, beantwortet er Suchanfragen im alle 25000 Webseiten des Linux-Magazins umfassenden Index sehr schnell. Nur selten braucht er mehr als eine halbe Sekunde, was auch ein Test mit zwei Millionen zufällig ausgewählten HTML-Seiten im Index bestätigte.

Lucene

Der Kern jeder modernen Suchmaschine ist der Indexer. Mit der freien Java-Bibliothek Lucene gebaute, skalierbare Indexer brauchen sich hinter kommerziellen Suchmaschinenprodukten nicht zu verstecken.

Analyzer, Indexer und Felder

Das Grundprinzip ist einfach: Ein Analyzer zerpflückt die Dokumente und verteilt deren Metadaten und Textkomponenten auf vorgegebene Felder. Anschließend erstellt daraus ein Index-Builder den eigentlichen Index. Der ist üblicherweise im Kern ein Transduktor-Automat, der über die Eingabe eines Terms zu einer Liste von Links führt. Das nennen Experten dann “Inverted Files”, weil ein Index zwar mehr oder weniger dem Originalkorpus entspricht, aber die Wörter nicht mehr in ihrer natürlichen Reihenfolge gespeichert sind, sondern in einer alphabetischen Ordnung mit einem Vermerk ihrer Originalposition.

Die Erstellung und Pflege des Automaten während der Laufzeit und die kompakte Ablage der Links im Dateisystem ist normalerweise eine trickreiche Aufgabe, die Lucene sehr elegant löst. Indexierungsleistungen von 30 MByte pro Sekunde auf einem modernen Rechner schafft es spielend, ebenso die Reduktion der Ausgangstexte im Index auf etwa 20 Prozent ihrer Größe. Dies hängt natürlich davon ab, wie sehr der Suchmaschinenentwickler ein Dokument zerpflückt und auf Felder verteilt.

Boost und Pagerank

Anhand der Felder von Lucene kann der Programmierer beispielsweise dem Titel einen besonderen Boost verpassen, etwa indem er Überschriften bevorzugt oder externe Metadaten wie den Dateinamen oder den Autor als besonders relevante Textdeskriptoren nutzt. Kommt der Suchbegriff in diesen Feldern vor, dann erhält der Treffer einen höheren Wert im Ranking, als wenn er nur irgendwo im Body erscheint. Die richtige Gewichtung dieser Felder zueinander ergibt dann das (hoffentlich richtige) Ranking, das sich der User wünscht.

Trotzdem lassen sich auch bei Lucene gezielt einzelne Felder befragen oder die Suchergebnisse nach ihnen sortieren. Dabei sind nicht nur Textfelder, sondern auch Range-Abfragen mit verschiedensten Feldtypen möglich.

Neben vergleichsweise langweiligen booleschen Abfragen sind so auch Wildcard- oder fehlertolerante Suchen möglich. Dabei geht es nicht nur darum, Treffer mit einem identischen Prefix zu finden (wie in SQL mit »’Linux-Mag%’« ), sondern auch unterschiedliche Schreibweisen. Über das Levenshtein-Distanz-Verfahren lassen sich mit einer eigenen Syntax ohne nennenswerte Geschwindigkeitseinbußen beispielsweise alle Schreibweisen von »Schmie?[dt]+« oder »M[ae][iy]e?r« finden.

Distanz bitte!

Eine andere Form von Distanzabfragen erlaubt der Proximity-Operator (»~« ) bei Multiword-Queries. Er findet alle Abschnitte von Texten, bei denen mehrere Wörter innerhalb eines definierbaren Maximalabstands erscheinen. Als Kontrast zu den eher statischen Dokumenten- oder Feldgewichten lassen sich während der Abfragezeit auch Terme höher gewichten als andere. Der Termboost-Operator (»^« ) erlaubt es, bei Multiword-Queries einzelne Suchbegriffe wichtiger einzustufen als den Rest.

Doch bei der idealen Suchmaschine braucht sich der Anwender damit gar nicht zu beschäftigen, weil die den relevantesten Treffer ohnehin an erster Stelle liefert, auch ohne Operatoren. Der Indexer von Lucene bringt dafür schon sehr viele Hausmittel mit.

Online PLUS

Zwei einfache, aber vollständige PHP-Skripte für den Open Search Server finden Sie unter dieser URL: [https://www.linux-magazin.de/plus/2011/06]

DELUG-DVD

Auf der Delug-DVD findet sich der Open Search Server sowohl als Installationspaket als auch als virtuelle Maschine mit einem vorbereiteten Index von über 50 000 Seiten von [https://www.linux-magazin.de].

Infos

  1. Open Search Server: http://www.open-search-server.com
  2. Peter Roßbach, “Reicher schwarzer Kater”: ADMIN-Magazin 03/08, S.38
  3. Lucene bei Apache: http://lucene.apache.org/java/docs/index.html
  4. Quartz-Scheduler: http://www.quartz-scheduler.org
  5. Carsten Zerbst, Nils Magnus, “Allzweckmittel”: Linux-Magazin 05/10, S. 104
  6. OSS-Wiki: http://www.open-search-server.com/wiki/en/index.php/Main_Page
  7. Darkstat: http://dmr.ath.cx/net/darkstat/
  8. Lemma: http://de.wikipedia.org/wiki/Lemma_(Lexikografie)
DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 5 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
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
Nach oben