Open Source im professionellen Einsatz
Linux-Magazin 11/2008
© timmeyy, Pixelio.de

© timmeyy, Pixelio.de

Perl-Skript realisiert das singende, klingende Internet

Das Log als Ohrwurm

Statt eingehende Requests nur in der Logdatei des Webservers zu verfolgen, macht ein Soundserver sie für den Systemadministrator hörbar. Nun kann man die Surfer nebenbei belauschen.

922

Immer wenn ich eine neue Ausgabe unseres USA-Familien-Rundbriefs [1] hochlade, eine Ankündigungs-E-Mail abschicke und das RSS-Feed auffrische, sehe ich danach gerne im Accesslog des Webservers zu, wie die ersten Infohungrigen die Berichte lesen und hochaufgelöste Versionen der Bilder herunterladen.

Allerdings ist das Verfolgen des Serverlogs recht monoton. Viel besser wäre, wenn ich die Abrufe im Hintergrund registrieren und mich derweil anderen Aufgaben widmen könnte. Etwa indem ich den Surfern akustisch über die Schulter schauen könnte. In dem Buch "Netscape Time" von Jim Clark [2] las ich vor vielen Jahren einmal, dass die frühen Netscapeler, nachdem sie eine neue Release fertiggestellt hatten, die eintrudelnden Hits für den Download akustisch über den PC-Lautsprecher ausgaben.

Ein Browser-Download für Windows führte zu einem Froschquaken, für Macs wurde das Geräusch zerbrechenden Glases gespielt und für die Unix-Plattform löste sich ein Kanonenschuss. So erfreuten sich die Internetpioniere in ihren Cubicles am hörbaren Erfolg.

Etwas Ähnliches lässt sich leicht in Perl implementieren. Allerdings ist die Lage in meinem Fall ein wenig verzwickter, denn der Webserver läuft bei einem Hosting-Provider, der zwar einen Shell-Zugang über SSH erlaubt, aber keine Töne an mich übermitteln kann.

Firewall-Tunnel

Abhilfe schafft das Skript »boom-sender« auf dem Mietserver, das die »access.log«-Datei des Webservers überwacht und bei ausgewählten URLs Nachrichten über einen SSH-Tunnel an einen Soundserver »boom-receiver« auf meinem heimischen Rechner schickt.

Abbildung 1 zeigt den Aufbau: Der Soundserver ist ein mit dem CPAN-Modul POE realisiertes Skript, das auf Port 8080 des lokalen Rechners auf Befehle wartet. Auf der Seite des Hosting-Providers läuft ein weiteres POE-Skript, das bei Änderungen im Accesslog anspringt und als TCP-Client Nachrichten abschickt. Da mein Heimrechner hinter einer Firewall steckt, kann ihn der Logchecker »boom-sender« nicht direkt kontaktieren. Stattdessen verbindet ein Tunnel, den das Kommando

ssh -R 8080:localhost:8080 host.xyz-hosting.com

vom Heimrechner aus anlegt, die beiden Gesprächspartner. Das Logskript auf dem gehosteten Rechner muss seine Nachrichten nur an seinen Port 8080 schicken, damit sie durch den Tunnel wie durch Zauberei auf Port 8080 des Heimrechners ankommen, ganz so, als gäbe es die Firewall gar nicht.

Abbildung 1: Das Skript, das die Accesslog-Datei des Webservers auf dem Hostingrechner überwacht, kommuniziert über den SSH-Tunnel mit dem Sound erzeugenden Desktop.

Auf Befehl Sound

Die lokale Soundmaschine empfängt auf diese Weise Namen von Tondateien und spielt sie anschließend mit dem Play-Utility aus dem Fundus des Programmpakets Sox unter Linux ab. Das Programm »play« kommt standardmäßig mit Ubuntu und kann nicht nur WAV-Dateien, sondern auch MP3s ausgeben, falls Ubuntu dafür konfiguriert ist.

Abbildung 2 illustriert die Interaktion eines Testclients mit dem laufenden Soundserver: Ein »telnet« auf den Verbindungs-Port von Localhost zeigt zunächst eine Grußnachricht des Servers und alle Sounddateien, die dieser anbietet. Schickt der Client den Namen eines dieser WAV-Files an den Server, spielt der es ab. Das Skript in Listing 1 legt in Zeile 9 in »$SOUND_DIR« das Verzeichnis fest, in dem die Sounddateien liegen müssen. Aus Sicherheitsgründen sind nur Dateinamen und keine Pfade erlaubt. Voreingestellt ist das aktuelle Verzeichnis (».«).

Abbildung 2: Der Testclient Telnet verbindet sich mit dem Empfänger-Server, der auf Kommando eine Sounddatei abspielt.

POE bietet sich als Technologie sowohl für die Server- als auch für die Client-Seite an, weil es hier ausreicht, seine Komponenten nach dem Baukastenprinzip zusammenzustecken.

Eine recht gute Einführung in POE geben die Website [7] oder das Kapitel über POE in [3]. Der Server in Listing 1 definiert Callbacks für die Zustände »ClientConnected« (Client hat angedockt), »ClientInput« (Client hat eine Textzeile übermittelt) sowie einen speziellen Parameter »InlineStates« mit etlichen Zuständen, der für die weiter unten erklärten Abräumarbeiten nach dem Abspielen eines Geräuschs verantwortlich ist.

Der Server bearbeitet viele Clientverbindungen quasi gleichzeitig. Die in der POE-Komponente versteckte Logik sorgt für den reibungslosen Ablauf hinter den Kulissen. Wie bei jedem POE-Skript legt der Programmcode zunächst das Verhalten bei allen möglichen Events fest, um dann den POE-Kernel mit »POE::Kernel->run()« zu starten. Der läuft dann bis zum Programmende.

Listing 1:
»boom-receiver«

01 #!/usr/local/bin/perl -w
02 use strict;
03 use POE;
04 use POE::Component::Server::TCP;
05 use POE::Wheel::Run;
06 use File::Basename;
07 use Log::Log4perl qw(:easy);
08 
09 my $SOUND_DIR = ".";
10 my @SOUND_FILES = map { basename $_ }
11          <$SOUND_DIR/*.wav>;
12 
13 Log::Log4perl->easy_init($DEBUG);
14 
15 POE::Component::Server::TCP->new(
16  Port => 8080,
17 
18  ClientConnected => sub {
19   $_[HEAP]{client}->put("Soundfiles: [".
20    join(", ", @SOUND_FILES) . "]" );
21 
22   $_[HEAP]{client}->put(
23    "Ready when you are.");
24  },
25 
26  ClientInput => sub {
27   my $client_input = $_[ARG0];
28 
29   if( $client_input !~ /^[w.-]+$/ ) {
30     $_[HEAP]{client}->put(
31      "Illegal input.");
32     return;
33   }
34 
35   if( $client_input eq "q" ) {
36     POE::Kernel->yield("shutdown");
37     return;
38   }
39 
40   my $msg = sound_play(
41         $_[HEAP],
42         basename($client_input));
43 
44   $_[HEAP]{client}->put( $msg );
45  },
46 
47  InlineStates => {
48   sound_ended => sub {
49    my ($heap, $wid) = @_[HEAP, ARG0];
50    DEBUG "Deleting wheel $wid";
51    delete $heap->{players}->{$wid};
52   },
53  },
54 );
55 
56 POE::Kernel->run();
57 exit;
58 
59 ###########################################
60 sub sound_play {
61 ###########################################
62  my($heap, $file) = @_;
63 
64  if(! -f "$SOUND_DIR/$file") {
65   return "$file doesn't exist";
66  }
67 
68  POE::Kernel->sig(CHLD => "reaped");
69 
70  my $wheel =
71   POE::Wheel::Run->new(
72    Program   => "/usr/bin/play",
73    ProgramArgs => ["$SOUND_DIR/$file"],
74    StderrEvent => 'ignore',
75    CloseEvent => 'sound_ended',
76  );
77 
78  DEBUG "Creating wheel ", $wheel->ID;
79  $heap->{players}->{ $wheel->ID } = $wheel;
80 
81  return "Played $file";
82 }

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • tleW etrhekreV

    Der Titel des Beatles-Songs "Revolution 9" soll nach einer Verschwörungstheorie rückwärts gespielt einen Hinweis offenbaren, dass das Management die Band gezwungen habe, den toten Paul McCartney durch einen Doppelgänger zu ersetzen. Perl macht klar: alles Schwindel!

  • Schöner schicken

    Eigentlich brauchen lokale Mailclients nur während des Sendens einen sicheren Weg zum SMTP-Server. Ein in Perl selbst gebauter Daemon bohrt darum nur temporär einen SSH-Tunnel.

     

  • Episodenfilm

    Ein Perl-Skript mit GTK-2-Oberfläche merkt sich, wie weit sein Anwender gespeicherte Videos angesehen hat, und fährt auf Wunsch an der Stelle der letzten Unterbrechung wieder fort.

  • Am Fließband

    Beim halbautomatischen Umwandeln von gedruckten Zeitschriftenartikeln ins PDF-Format hilft das heute vorgestellte Perl-Skript. Den Ablauf triggert ein Taster am Scanner.

  • Pulseaudio 5.0 mit neuen Modulen

    Der freie Sound-Server Pulseaudio macht einen recht großen Sprung in der Versionsnummer, bringt aber nur kleinere Änderungen mit. Die größten Neuerungen sind die Unterstützung von BlueZ 5 und das Log von Systemd.

comments powered by Disqus

Stellenmarkt

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.