Bitte Beachten: Dieser Blog wird hier nicht weiter geführt! Kommentare und neue Blogposts gibt es unter http://feitel.indeedgeek.de. Dort bitte auch neue Kommentare zu diesen Beiträge erstellen.

Montag, 10. November 2008

ID3-Cover von Kopf bis Fuß

ID3 steht für Identify an MP3 wobei die aktuellen Versionen weit über das bloße Identifizieren hinaus gehen. In der Version 2.4 sind 83 Verschiedene Tags definiert die von "Internet radio station owner" bis "Original album/movie/show title" reichen. (Daneben kochen noch einige Player wie ITunes ihr eigenes Süppchen).

Versionen

In Version 1 gab es nur wenige Tags die auf eine fixe Größe begrenzt waren. (Zudem noch ein Haufen anderer Nachteile...) In Version 2 wurde vieles verbessert so ist zum Beispiel die Länge nicht mehr Fix und es gibt haufenweise neue Tag-Felder. Alle Versionen bis 2.3 gelten als veraltet. Und werden nur von wenigen Programmen und Geräten noch geschrieben. Die aktuelle Version ist 2.4 wobei man am häufigsten noch 2.3 antrifft.

Der Größte Unterschied zwischen 2.3 und 2.4 ist die Möglichkeit Tags nun auch als UFT-8 abzuspeichern (vorher nur ISO 8859-1 und UTF-16). Außerdem ist nun die Platzierung der Tags anpassbar. Bisher musste es immer am Anfang der Datei stehen was vor allem bei Streaming Probleme machen kann. Weiterführendes zu den Änderungen: in der offiziellen Doku.

Technische Umsetzung

Die gesamten ID3 Informationen beginnen immer mit einem Header. Dort ist gekennzeichnet, dass es sich um einen ID3 Tag mit der entsprechenden Version handelt außerdem sind dort noch Flags und die Größe angegeben.

Je nach dem wie es in den Flags angegeben wurde folgt danach ein extended Header. Dort lassen sich unter anderem einige Restriktionen machen die auch für das Cover interessant ist. So kann hier das Format (PNG oder JPEG) angegeben werden oder auch die maximale Auflösung wie zum Beispiel (256x256 oder kleiner).

Anschließend folgen die Tags auch Frames genannt. Der Header eines Frames besteht aus einer zum Teil kryptischen, eindeutigen Kennung wie TDEN für "Encoding time", der Länge der Daten und einigen Flags. Flags können zum Beispiel die Kodierung, ein Read-Only-Flag, Compression oder Verschlüsselung sein. Anschließend folgen die Daten selbst. Weiterführendes zu den Frames in der offiziellen Doku.

Zuletzt kann noch ein Buffer oder ein Footer kommen.

Image-Tag

Nun zum eigentlichen Image-Tag: Nicht erst seit ITunes Cover-Flow möchte man gerne die Cover eines Albums mit abspeichern. Ist das Cover einfach in einer Datei enthalten hat man wieder die Probleme wie man die Datei benennt und außerdem muss man aufpassen das sie nicht mal verloren geht. (So macht es glaub ich der Windows Media Player indem er eine Folder.jpg anlegt. (die nebenbei auch von meinem N95 erkannt wird (Siehe unten (fast wie LISP :D)))) Deshalb geht man dazu über die Cover-Informationen im Track selber zu speichern. Dazu gibt es ein extra Frame mit der Kennung APIC. Hier kann man allerdings nicht nur das Cover abspeichern sondern eine Vielzahl weiterer Bilder die den Track betreffen. Hier die Komplette Auflistung aus Version 2.4:

  • Other
  • 32x32 pixels 'file icon' (PNG only)
  • Other file icon
  • Cover (front)
  • Cover (back)
  • Leaflet page
  • Media (e.g. label side of CD)
  • Lead artist/lead performer/soloist
  • Artist/performer
  • Conductor
  • Band/Orchestra
  • Composer
  • Lyricist/text writer
  • Recording Location
  • During recording
  • During performance
  • Movie/video screen capture
  • A bright coloured fish
  • Illustration
  • Band/artist logotype
  • Publisher/Studio logotype

Es können auch mehrere Bilder pro Datei mit unterschiedlichen Typen angegeben werden. Zu Jedem Eintrag kann dann noch eine Beschreibung eingetragen werden (Kodierung hier nicht vergessen einzutragen). Das Bild selbst sollte entweder ein PNG oder ein JPEG-Format haben kann aber auch alles andere sein da man den MIME-Type sowieso angeben muss.

Außerdem besteht noch die Möglichkeit als MIME-Type "-->" anzugeben und dann als Bild nur den Verweis auf eine Bilddatei zu speichern. Beispiel wäre: "../cover.png" oder "http://example.com/cover.jpg". Aber ob das ein Player unterstützt??

Test-Script

Die Kompatibilität ist sowieso der Grund warum ich mich mit der Thematik beschäftigt habe. Mein neues Handy (Nokia N95) wollte nur ein Teil meiner Covers erkennen. Um zu Testen was es kann habe ich mir folgendes Skript gebastelt was MP3-Dateien in allen möglichen Kombinationen erstellt.

Also zum Beispiel das Bild als "Cover (front)" im PNG-Format und ID3v2.4 wäre eine denkbare Kombination.

Das Script benötigt Python und die eyeD3 Library. Zudem wird ein Soundfile benötigt (ich hatte complete.mp3 mit 4 Sekunden Länge) und ein Bild in den entsprechenden Formaten (ich hatte ok.{png,bmp,jpg,gif}). In dem Download-Package ist beides vorhanden.

import eyeD3
from shutil import copy

filename = "complete.mp3"
imagefile = "ok."
versions = [eyeD3.ID3_V2_3, eyeD3.ID3_V2_4]
formats = ["bmp", "gif", "jpg", "png"] 
id = 0 

for type in range(eyeD3.frames.ImageFrame.MIN_TYPE, eyeD3.frames.ImageFrame.MAX_TYPE + 1): 
  for version in versions:
    for format in formats:
      str = { 
            "id"      : id
          , "type"    : eyeD3.frames.ImageFrame.picTypeToString(type)
          , "version" : eyeD3.utils.versionToString(version)
          , "format"  : format
      }   
      newFilename  = "test-%(id)03d-%(type)s-%(version)s-%(format)s.mp3" % str 
      copy(filename, newFilename)
      tag = eyeD3.Tag(newFilename)
      tag.remove(eyeD3.ID3_ANY_VERSION)
      tag.header.setVersion(version)
      tag.addImage(type, imagefile+format, u"")
      tag.update()
      id+=1

Es werden so 167 Dateien erstellt die entsprechend benamt sind. Nun kann man damit sein Player füllen und sehen was er alles unterstützt. In meinem Fall konnte das Nokia N95 nur JPEG im korrekten "Cover (Front)"-Feld wobei ihm die Version (ID3v2.{3,4}) egal war.

Testen, Testen, Testen

Ich musste das ganze natürlich gleich mit ein paar Programmen ausprobieren. Amarok konnte natürlich alles darstellen ebenso ITunes. Der Windows-Explorer hingegen schafft unter Vista leider nur ID3v2 dafür aber auch alle Formate. Winamp schafft mit Plugin grade einmal JPEG-Formate.

Wenn ihr noch etwas testet dann lasst mir doch die Ergebnisse zukommen. Ich werde sie hier auch noch rein stellen. Dazu habe ich kein Archiv mit den benötigten Dateien gepackt welches hier runtergeladen werden kann: download

Der Fisch

Aufmerksamen Lesern wir das Feld "A bright coloured fish" aufgefallen sein. Ich habe echt kein Plan für was das gut sein soll. Ich finds ein sehr lustiges Easteregg :D. Wenn jemand den Fisch in freier Wildbahn findet muss er mir unbedingt Bescheid sagen!

eye3D kommentiert es nur folgendermaßen: BRIGHT_COLORED_FISH = 0x11; # There's always room for porno.

Montag, 4. August 2008

Backups

Für eine anständige Backup-Strategie bin ich schon fast so lange am überlegen wie für meine Groupware-Verwaltung. Nachdem ich mir extra dafür eine externe 500 GB Festplatte gekauft hatte, fehlte nur noch die passende Softwarelösung. Neidisch schaut man im ersten Moment auf Apple's TimeMachine. Rein Objektiv ist dies aber auch nichts anderes als ein Inkrementelles Backup mit kurzen Iterationszeiten und einer netten GUI. Alternativen für Linux wie Flyback sind vorhanden. Allerdings ist dies nicht die einzige Möglichkeit eines sinnvollen Backups.

Fakt ist wohl, ein Backup sollte möglichst nicht jedes mal eine eins-zu-eins Kopie anlegen, da so viel zu viel Speicher verbraucht wird. Lösung sind Inkrementelle oder Differenzielle Backups. So werden nur die Änderungen gespeichert die sich verändert haben. Fast jede Lösung bietet dieses Konzept mittlerweile an. Außerdem wollte ich ein Backup auf Datei-Ebene und nicht auf Partitionsebenen wie es zum Beispiel das Tool dd anbietet. Da ich denke so Flexibler bin und außerdem glaube ich nicht das Inkrementelle Backups auf Partitionsebene möglich ist.

Zuerst plante ich ein Backup mit einem Selbstgeschriebenden Skriptes. Über die Linux-Boardmittel lassen sich eine Vielzahl der der Anforderungen wie Verschlüsselung und Komprimierung recht einfach implementieren. Allerdings wenn man alle Möglichkeiten mit allen kombinieren möchte so wird es irgendwann richtig komplex. So habe ich meine ersten Versuche verworfen und plante mit einem umfangreichen Backup-Programm wie BoxBackup oder Bacula. Hier habe ich aber auch recht schnell erkannt das diese für große Netzwerke ausgelegt sind und für meinen kleinen Laptop etwas überdimensioniert sind. Etwas einfaches musste her!

Über Chaosradio bin ich auf ZFS gestoßen. Ein Filesystem mit einer unglaublichen Feature-Liste. Angefangen von automatischer Größen-Anpassung von Partitionen über automatische Komprimierung bis hin zu gesicherter Konsistenz des Dateisystems bietet es alles was man sich wünschen kann. ZFS bietet auch die Möglichkeit von Snapshots auf Block-Ebene an. Man kann die Daten, die sich geändert haben, einfach über die alten drüber kopieren und anschließend ein Snapshot machen. So hat man im Grunde jedes mal ein Vollbackup obwohl man nur die geänderten Blöcke speichern muss. Leider kommt ZFS aus der Solaris-Welt und kann in den Linux-Kernel im Moment wegen Lizenzproblemen nicht integriert werden. Es existiert zwar eine FUSE-Erweiterung, aber alles noch recht Beta. Das Risiko wollte ich leider nicht beim Backup eingehen und musste mich so nach Alternativen umschauen.

Das System mit den Snapshots hat mir aber gefallen und so bin ich auf das recht populäre Tool rsnapshot gestoßen. Das Programm setzt auf Hardlinks auf. Bei normalen (Soft-)Links hat man eine Datei und erstellt dann Referenzen auf diese Datei. Löscht man eine Referenz interessiert das niemanden. Löscht man die ursprüngliche Datei werden alle Referenzen ungültig. Bei Hardlinks referenziert man nicht auf eine Datei sondern auf ein INode-Eintrag. Also sozusagen eine Ebene Tiefer. Der Vorteil ist, alle Hardlinks sind gleichberechtigt. Die eigentlichen Daten werden erst gelöscht, wenn kein Hardlink mehr darauf verweist. Das Prinzip von rsnapshot ist dadurch recht einfach: Man kopiert das letzte Backup mittels Hardlinks in ein neues Verzeichnis und ändert dann über rsync die veränderten Dateien. So erhält man jeden Tag ein Vollbackup welches nur den Speicherplatz der Änderungen verbraucht.

Ein weiters sehr nützliches Feature ist die Möglichkeit eigene Scripte (z.B. um ein Datenbankdump zu erstellen) in das Backup einzubinden. Und wenn man zum Beispiel einen zweiten Computer mit sichern will, so ist es möglich Daten von diesem über ssh+rsync zu hohlen. Somit sichere ich mein Laptop mein Server und die Datenbank auf meinem Server recht einfach mit nur einem Programm

Leider kann rsnapshot, anders wie ZFS nur auf Datei-Ebene arbeiten. So wird eine Datei in der sich nur ein Buchstabe ändert komplett neu übertragen. Auch wird es nicht erkannt wenn man ein Verzeichnis oder eine Datei umbenennt. Auch in diesem Fall wird die Datei neu abgespeichert. Aber wenn man sich der Problematik bewusst ist, stört sie kaum.

Programme wie Storebackup umgehen das Problem indem sie zu jeder Datei Prüfsummen anlegen und diese vergleichen. Allerdings ergibt sich so ein worst-case-Aufwand von O(n^2) da ja jede Checksumme erst einmal erstellt, und dann mit jeder Datei verglichen werden muss. Man sieht schon, diese Lösung braucht um einiges länger als mein rsnapshot. (180 GB in ca 10 Minuten täglich bei einem diff von gerade mal einigen hundert MB). Außerdem wollte ich auch ein gut getestetes Konzept und habe mich so für das weit verbreitete rsnapshot entschieden satt das (evtl gar nicht mehr weiter entwickelte) Storebackup.

Und nun die Zuschauerfrage: Wie macht ihr eure Backups? Ich denke jeder der am Computer arbeitet braucht ein Backup, da Datenverlust nur eine Frage des Wann ist. Und wenn die Dateien nur einmal pro Woche auf DVD gebrannt werden. Auf jeden Fall würde mich euer Setup interessieren. Gerne auch in einem eigenen Blog-Post bei euch. Verlinkt euch einfach in den Kommentaren!

Freitag, 1. August 2008

Groupware Protokolle

Wer träumt nicht von einer zentralen Verwaltung seiner PIM-Informationen? Groupware-Systeme unterstützten diesen Prozess indem sie die Daten zentral verwaltet und verschiedene Schnittstellen anbietet. In vielen Fällen wird eine Groupware nach ihrem Web-Frontend bewertet. Leider spielt diese eigentlich nur eine sehr untergeordnete Rolle. Das Hauptproblem konzentriert sich darauf, möglichst viele Clients mit dem System verbinden zu können. Deshalb möchte ich kurz einige interessante Techniken auflisten um den Austausch der Daten zu Realisieren.

Formate

Zumindest hier zeichnet sich langsam ein Standard ab. Für Termine hat iCalendar (oder kurz ical) langsam den älteren Konkurrenten vCalendar abgelöst. Mit iCalendar lassen sich allerdings nicht nur Termine sondern auch todo's oder Journaleinträge damit verwalten. Leider ist das Format nicht ganz so schön (man ist ja langsam überall XML gewohnt) aber zumindest die meisten Datenfelder werden überall verstanden. Da man aber auch selbst Erweiterungen definieren kann, ist es doch möglich das Details in verschiedenen Anwendungen anders verstanden werden. Bei Kontakten hat sich vCard durchgesetzt, wofür weitgehend das selbe wie bei iCalendar gilt.

Protokolle

Leider sind dies ja nur Dateiformate. Meistens möchte man ja aber diese Daten zentral hinterlegen und mit verschiedenen Clients darauf zugreifen. Dazu sind einige Protokolle nötig, die diesen Transport realisieren. Hier möchte ich auch mein eigentliches Hauptaugenmerk legen.

Email

Hier ist es noch am einfachsten. POP ist Tot. IMAP ist Standard. Viel mehr muss man dazu nicht sagen. Interessant sind allerdings einige Erweiterungen für IMAP. Einmal wäre da IMAP-IDLE. Dabei meldet sich der Client am Server an und senden anschließend nur ab und zu keep-alive-Pakete. Der Server hingegen antwortet sobald eine neue Mail eintrifft. So hat man ein wunderbaren Mail-PUSH ohne jeden Aufwand. Erwähnenswert ist noch Sieve. Sieve. Stieve ist eine Programmiersprache in der sich Regeln wie zum Beispiel Abwesenheitsnachrichten, oder Spamregeln definieren lassen. Außerdem ist meistens nicht bekannt das man mit IMAP auch komplexe ACL's definieren kann. So ist es möglich ein Postfach auch mehreren Personen zugänglich zu machen.

Kalender und Kontakte

XML-RPC

Einige Projekte wie eGroupware oder PHProject setzten auf XML-RPC zur Synchronisation. Zwar lässt sich so sehr einfach dagegen programmieren aber leider ist dies immer sehr Spezifisch auf die einzelne Anwendung. Deshalb finde ich diese Idee nicht sonderlich toll. Lieber ein standardisiertes Protokoll für alle!

WebDav

Eine sehr einfache Möglichkeit ist der Einsatz von WebDav wie er auch von subversion benutzt wird. WebDav ist eine Erweiterung zu HTTP, die es ermöglicht Dateien auch hochzuladen. So kann man einfach die jeweilige Datei (ical oder vcard) auf dem Server plazieren und diese herunter laden oder eben wieder schreiben. Das Problem ist nur: Jedes mal muss die gesamte Datei mit allen Einträgen heruntergeladen werden und bei Änderungen auf dem Server übertragen. Das kostet Zeit und macht verteiltes Arbeiten recht schwierig.

GroupDAV

GroupDav ist eine kleine Erweiterung zu WebDav die einfach nur festlegt jeder Event oder Kontakt liegt in einer einzelnen Datei in einem jeweiligen Unterordner. So muss immer nur eine Datei übertragen werden. Diese Idee finde ich noch von allen die beste Möglichkeit da man so auch einfach den Ordner lokal für offline Arbeit zwischenspeichern kann.

IMAP

Kolab definiert versteckte IMAP Ordner. Der jeweilige Client speichert Kontakte oder Termine als Email in den jeweiligen versteckten Ordner mit entsprechendem XML-Anhang. Die gesamte Kommunikation läuft so über IMAP Ordner. Ist eine nette Idee, allerdings finde ich den Gedanken sehr unschön meine Kontakte und Termine als XML-Anhang an eine versteckte Email ranzukleben. Ist irgendwie sehr umständlich und sicher nicht Sinn der Sache.

SyncML

SyncML hat sich ja längst auf allen Handys festgesetzt und auch erste Plugins für Desktop-Anwendungen sind verfügbar. Dazu beigetragen hat sicherlich funambol (früher Sync4J). Dies ist ein freier SyncML-Server der von Google-Anwendungen über Groupdav bis hin zum IPhone alles miteinander Syncen kann.

Kalender only

CalDav ist spätestens seit es Google in seinem Kalender unterstützt etwas populärer als GroupDAV. Es basiert ebenfalls auf WebDav allerdings kann man auch komplexere Abfrage-Queries an den Server stellen. Das macht es einerseits natürlich etwas effektiver als GroupDav allerdings auch komplexer zu Implementieren. Für Apache gibt es übrigens ein CalDav-Modul. Leider muss man Apache dafür neue übersetzten (was ich auf einem Server sehr ungern tue).

Kontakte only

Hier ist sicherlich eine der wichtigsten Lösungen LDAP. Fast jedes Programm kann auf LDAP zugreifen. Es bietet sehr gute Such Möglichkeiten und ist einfach zu erweitern. Leider hat man hier immer das Problem das man auf ein LDAP nur lesend zugreifen kann. Will man Einträge hinzufügen oder bearbeiten muss dies manuell auf dem Server geschehen. Deshalb wird von vielen Groupware-Systemen LDAP nur als Read-Only-Verzeichnis genutzt. Die eigentlichen Änderungen laufen über andere Protokolle. Serverseitig werden diese dann ins LDAP überführt.

Sonstiges

Eigentlich erwarte ich von einer Groupware, dass sie mehr als nur Emails, Kontakte, Termine und Todos unterstützt. Allerdings sieht es hier noch schlechter aus, als in den anderen Bereichen. Wünschenswerte Features wären zum Beispiel RSS (was leider meistens nur read-only für den Client ist. Also sprich der Client kann dem Server nicht mitteilen welche Items ich gelesen habe. Kennt hier jemand eine Lösung??), XMPP, IRC (Wäre doch Klasse wenn der komplette Verlauf, zum jeweiligen Kontakt, zentral abgespeichert wird) oder auch Bookmarks (ganz im grandiosen (neuen) delicious.com-Style). Aber von solchen Ideen sind wir wohl noch ähnlich weit entfernt wie zu dieser Vision: Assoziative Gedächtnishilfe für mobile Datensammler

Ich hoffe ich konnte kurz einen Überblick über mögliche Techniken geben. Vielleicht kanntet ihr ja das ein oder Andere noch nicht. Sollte ich was vergessen haben, einfach in den Kommentaren melden! Zum Schluss mein Wunsch-Setup: IMAP (mit IDLE und Sieve), GroupDav, LDAP (read-only) und Funambol-Connector. SOGo (ein Fork von OpenGroupware.org) bietet mir zwar genau das, allerdings habe ich mit dem Kompilieren des Objective-C Quellcodes einige Probleme ;-).

Anmerkung 1: Ich konnte (noch) nicht alle Produkte und Protokolle ausprobieren, deshalb sind die Kommentare alle nur persönliche Empfindungen

Anmerkung 2: Mir ist aufgefallen ich verlinke sehr wenig auf andere Seiten. Ich hab diesmal sehr viel (vor allen) auf Wikipedia verlinkt. Findet ihr das besser?

Freitag, 25. Juli 2008

Wissen ist nutzlos - Weisheit ist Macht!

Man wird die gesamte Schulzeit, und leider nun im Studium auch noch weitgehend, darauf getrimmt Dinge einfach zu Wissen. Großteils geschieht dieser Vorgang durch stupides Auswendiglernen relevanter Teilbereiche. Selbst bei Mathematik oder Physik, die beide sehr viel mit Verstehen zu tun haben, muss man manchmal einfach Definitionen oder Rechenvorschriften auswendig lernen. Und sogar Deutsch bleibt nicht verschont. (Ich erinnere mich noch mit Grauen daran, als ich die Gliederungssymbolreihenfolge im Inhaltsverzeichnis von Textanalysen auswendig lernen musste). Und am Ende hat kann man zwar Teile auswendig, aber wirklich viel mehr weiß man dadurch nicht. Das Beigebrachte beschränkt sich meist nur auf einige kleine Teilaspekte, die bis ins letzte Eck beleuchtet werden, und doch werden andere zum Teil grundlegende Themengebiete weg gelassen. Und spätestens nach der Prüfung ist sowieso alles vergessen.

Man sieht oft nicht den Sinn hinter dem Ganzen. Das gesamte Lernen erscheint einem als unnötige Zeitverschwendung. Der beste Weg ist diese Methodik sicher nicht, allerdings darf man nicht in die Einstellung verfallen, man müsste nur lernen was man später auch einmal braucht. Vieles von dem was man lernt sollte als Allgemeinbildung angesehen werden. Außerdem denke ich, eine Schulnote im Zeugnis repräsentiert nicht zwingend den Wissenstand sondern viel mehr die Motivation etwas zu lernen (auch wenn es einem zeitweise als unwichtig erscheint).

Nun ist es aber so dass sich das gesamte Wissen unserer Gesellschaft ca. alle 5 Jahre verdoppelt!! (Leider habe ich für die Behauptung keine gute Quelle. Allerdings habe ich mehrere Angaben zwischen 2 und 7 Jahre gefunden). Dieser unglaubliche Wissenswachstum lässt jegliches Auswendiglernen gradezu lächerlich erscheinen. Früher gab es immer das Zitat "Wissen ist Macht" ich denke aber, im Kontrast zu der momentanen, rasanten Forschung sollte man dieses Zitat, nach fast 400 Jahren, doch noch einmal überdenken. Es ist heute schon unmöglich auch nur in einem Teilbereich alles zu wissen. Und so gewinnt die oben genannte Schul- oder vielmehr Lehrkritik wieder an Bedeutung.

Ich denke eine gewisse Allgemeinbildung muss vorhanden sein, allerdings sollte im allgemeinen (und nicht nur auf die Schulen bezogen) Detailwissen viel weniger von Bedeutung sein. Es sollte mehr auf Strukturierte Informationsaufbereitung und -verarbeitung Wert gelegt werden, als auf die Informationen selbst. Wie man so schön sagt: "... man muss nur wissen wo es steht". Zudem gewinnt Erfahrung und breitgefächertes Kenntnis immer mehr an Bedeutung.

Gerade für uns Informatiker stellt sich immer wieder das Problem der richtigen Informationsverwaltung. Ich habe zum Beispiel im Moment 174 Rss-Feeds abonniert, von denen ich pro Tag mehrere Hundert neue Beiträge bekomme. Davon schau ich mir ca. 60 an und lese vielleicht gerade einmal 10. Hinzu kommt noch IM und EMail. Um keine Informationen zu vergessen sammle ich seit langem Links bei Del.icio.us und habe mir ein privates Wiki aufgesetzt um Wichtiges länger zu speichern. Doch das wichtigste Mittel um den Informationen Herr zu werden ist und bleibt die Volltextsuche. Semantische Auszeichnung und automatisierte Verarbeitung durch KI ist noch ein ferner Traum obwohl die Grundsteine gelegt sind. Bleibt abzuwarten was sich auf diesem Feld tut. Ich persönlich denke diese maschinelle Verarbeitung wird über kurz oder lange ein wichtiger Hauptbestandteil unserer Informatik.

Wahrscheinlich lernt man irgendwann in der Schule keine Jahreszahlen mehr sondern nur noch Suchbegriffsyntax, reguläre Ausdrücke und ganz wichtig die Bewertung von gefundenen Informationen... Ist dann Wissen überflüssig? Ob diese Vorstellung so viel besser ist?

Sonntag, 13. Juli 2008

GEZ ein unabdingbares Übel - Teil 2

Heute wie versprochen den zweiten und letzten Teil meiner Pro-Contra-Argumentierung zur GEZ. Nachdem ich im ersten Teil geschrieben habe warum ich die Rundfunkgebühren gut finde gibts heut meine Meinung warum ich die GEZ schlecht finde.

Mhmm, interessting ... but!

Wie vorher schon angekündigt, stehe ich nicht dem Abrechnungssystem als ganzes Kritisch gegenüber, sondern viel mehr der GEZ an sich. Leider wird Kritik an den Methoden der GEZ und dem der gesamten Gebührenverwaltung oft vermischt obwohl sie eigentlich nicht viel miteinander zu tun haben.

Vor allem seit Anfang 2008 die sogenannte Abgabe auf neuartige Rundfunkempfangsgeräte in Kraft getreten ist, werden immer wieder Beispiele herangezogen um die Abbrechungen zu kritisieren. Sicherlich sind Fälle wie "Wenn der Sohn ein Einkommen hat, bei den Eltern wohn und einen eigenen Fernseher nutzt muss dieser auch angemeldet werden" oder "Wenn ein Computer bei einem Selbstständigen in einem abgetrennten Arbeitszimmer steht so ist zusätzlich ein gewerblicher Gebrauch anzumelden" nicht gerade schön zu lesen, allerdings halte ich nichts davon, ein System aufgrund von Einzelfällen zu bewerten. Ich denke die Berechnung hat einige gravierende Lücken und ist sicher nicht mehr auf dem aktuellen Stand, allerdings ist eine hundertprozentige Zufriedenheit aller Beteiligten bei solch komplexen Angelegenheiten unmöglich.

Ob nun eine Abgabe auf Computer und Handys zulässig sind oder nicht lässt sich lange diskutieren. Ich möchte in diesen Bereich auch gar nicht zu tief wühlen da ich mir selber keiner Meinung sicher bin. Einerseits ist es fraglich in wie weit, mit zum Beispiel dem Handy, Dienste der ÖR genutzt werden und ob eine Video-on-Demand Lösung, wie sie aktuell üblich ist, mit dem ursprünglichen Streaming-Gedanken von Radio oder Fernsehen vereinbar ist. Auf der anderen Seite bieten die ÖR ein sehr umfassendes und vor allem qualitativ hochwertiges Angebot im Internet, so dass eine Zahlung eigentlich schon gerechtfertigt ist. (Notiz am Rande: Selbst Chaosradio ist durch Rundfunkgebühren finanziert).

Sicherlich ein sehr größer Kritikpunkt ist die Datenspeicherung der GEZ. Die GEZ hat zentral mehr Daten über die Bundesbürger gespeichert, als alle Einwohnermeldeämter zusammen. Die GEZ bekommt nicht nur Adressdaten von Einwohnerämtern sondern kauft diese auch extern bei kommerziellen Adresshändlern ein. Zudem kommen noch einige freiberufliche Gebührenfahnder die provisionsbasierend Arbeiten. Sollte man einmal bei der GEZ gemeldet sein so bleiben die Daten auch vorhanden selbst wenn man sich wieder abmeldet. Somit verfügt die GEZ bundesweit über den umfassendsten Datenbestand zu Privatpersonen. Intern beschäftigt die GEZ zwar Datenschutzbeauftragte allerdings wird sie nicht extern kontrolliert so dass immer wieder Datenschutzvergehen auffliegen.

Die GEZ hat (zurecht) mit einem sehr negativen Bild zu kämpfen. Schaut man sich die Briefe, die Werbung oder auch das Vorgehen der Außendienstmitarbeiter an, so erkennt man ein sehr restriktives Vorgehen, bei dem der Anschein erweckt wird man muss augenblicklich mit drakonischen Strafen rechnen, da man ein zu einem Verdächtigen in einem Kapitalverbrechen degradiert wurde. Auf der anderen Seite versucht die GEZ ihren Ruf zu verbessern indem sie Medien abmahnte, die als Beispiel statt Rundfunkgebühr von einer GEZ-Gebühr sprachen oder das Wort Rundfunkgebührenbeauftragter durch einen GEZ-Fahnder vereinfachten. Leider scheinen die Verantwortlichen noch nicht begriffen zu haben dass man sein negatives Bild nicht durch Abmahnungen gegen eben diese negative Einstellung bereinigt.

Alles in allem muss ich sagen ich finde es gut, dass es die Rundfunkgebühren gibt und auch das System mit dem sie eingetrieben werden. Nur kann ich auf der einen Seite die Berechnungskriterien nicht immer nachvollziehen und auf der anderen Seite sind die Verfahren der GEZ in keinster Weise tolerierbar.

Disclaimer

ALLES was in diesem Text geschrieben wurde basiert auf meinen persönlichen Ansichten und Ansichtsweisen. Da ich auf diesem Gebiet selbst nur Laie bin, und mir die Infos nur angelesen habe, schließe ich auch Inhaltliche Fehler und Unvollständigkeiten nicht aus. Berichtigungen und Kritik sind aber auf jeden Fall willkommen.

Samstag, 12. Juli 2008

GEZ ein unabdingbares Übel - Teil 1

Ist es nicht manchmal seltsam? Man findet etwas persönlich schlecht, weiß aber eigentlich, dass der Sachverhalt so korrekt abläuft. Genauso geht es mir mit der GEZ. Ich kann die GEZ, wie so viele andere auch, nicht leiden und doch weiß ich, dass eine Gebührenpflicht für Öffentlich-rechtlicher Rundfunk notwendig und gut ist.

Fangen wir mit den positiven Punkten der Rundfunkgebühr an. Aufgrund von aktuellen Beschwerden werde ich diesen Beitrag in zwei Teile aufsplitten. Heute gibts Pro-GEZ und morgen folgt das große Aber. Zusätzlich zu den normalen Kommentaren bitte ich heute mal auch Kritik zu den Beiträgen in die Kommentare zu schreiben. Findet ihr Splitten gut? Sind Beiträge zu komplex bzw. zu lange?

Gebührenverteilung

Kurz möchte ich meine Sicht der Gebührenverteilung erläutern. Diese Sicht ist zum einen etwas vereinfacht und zum anderen an dieser Stelle ein deutlicher Verweiß auf den Disclaimer am Ende des Beitrags.

Zentral von Bedeutung sind sicher erst einmal die Öffentlich Rechtlichen (ÖR), die dazu verpflichtet sind (siehe Grundgesetz Artikel 5 - Rundfunkfreiheit) ein von staatlichen Einflüssen unabhängiges Programm zu senden. Zusätzlich dazu ist eine Wirtschaftliche Unabhängigkeit aber ebenso von Bedeutung. Ziel dieser Bestimmung ist es eben eine gezielte Beeinflussung der ÖR zu vermeiden. Statt dessen sollen die betroffen Medien frei über staatliche und wirtschaftliche Misstände berichten dürfen, ohne an dieser Stelle von einer höheren Instanz eingeschränkt zu werden. In so weit sollte, denke ich, jeder mit der Notwendigkeit einer solchen Einrichtung übereinstimmen.

Das große Problem an dieser Geschichte ist allerdings die Umsetzung. Fakt ist, dass eine Finanzierung über Steuern unmöglich ist, da Steuern vom Staat erhoben und verteilt werden. Somit wäre eine staatliche Unabhängigkeit nicht mehr gegeben. Der Staat könnte, mit einem steuerfinanzierten System, willkürlich die ÖR durch Geldzahlungen (oder vielmehr durch ausbleiben von Zahlungen) in eine gewollte Richtung lenken.

Auf der Anderen Seite ist eine Finanzierung über zum Beispiel Werbeeinnahmen ebenfalls ausgeschlossen, da man hier die Einflussnahme der Wirtschaft nicht ausschließen kann. In Deutschland ist es durch die Duale Finanzierung allerdings trotzdem möglich auch durch Werbung Geldeinnahmen verbuchen zu können. Wichtig ist allerdings hier die Tatsache, dass ÖR (eigentlich) kein Gewinn erwirtschaften können. Eine Handlung/Haltung ausschließlich zur Gewinnmaximierung fällt an dieser Stelle also schon mal weg.

Eine Lösung die man dafür geschaffen hat ist die Gebühreneinzugszentrale der öffentlich-rechtlichen Rundfunkanstalten in der Bundesrepublik Deutschland (GEZ). Diese Verwaltungsgemeinschaft ist zum einen ebenfalls staatsfern organisiert, aber auch unabhängig von den ÖR. Sie nimmt das Geld der Empfänger, zieht seinen Anteil ab (ca. 2,2%) und verteilt den Rest auf die ÖR. So ist eine gerechte Verteilung an alle beteiligten Programmen gegeben.

Nun kann die GEZ nicht nach belieben Geld eintreiben. Die ÖR vermelden an die jeweiligen Länder (Rundfunkgebühren ist Ländersache) ihren Bedarf, der diese Vorschläge objektiv bewertet (Kommission zur Ermittlung des Finanzbedarfs der Rundfunkanstalten - KEF) und die Höhe der zu zahlenden Rundfunkgebühren festsetzt.

Missverständnisse

Durch dieses gesamte, zugegeben recht komplexe Modell, ist eine Unabhängige Berichterstattung der ÖR weitgehend sichergestellt. Da allerdings der Bürger unzufrieden ist wenn er Geld abdrücken muss, gibt es immer wieder rufe nach einem Abschaffen der Rundfunkgebühren beziehungsweise einem alternativen Abrechnungssystem. Vor allem Sätze wie "Warum soll ich für ÖR zahlen wenn ich doch nur RTL schaue?" hört man immer wieder. Aber auch wenn sich, vor allem bildungsfernere Gesellschaftsschichten, mit dem Angebot der aktuellen Privatsender zufrieden geben so ist eine Abbrechung nach Nutzen sehr fatal (und sogar per Gesetz ausgeschlossen). Die ÖR müsste mit ihrem Programm so versuchen ein möglichst breites Publikum zu erreichen, da sie auf die Zahlungen angewiesen sind. Resultat wäre kaum mehr ein wirtschaftlich und staatlich unabhängiges Medium sondern viel mehr eine sensationslüstere und unseriöse Berichterstattung wie sie bei den Privatsendern schon zum Standard geworden ist. Außerdem leben die ÖR davon dass Alle einzahlen und vielleicht kann man doch noch hoffen dass ich der ein oder andere Privatsendergeschädigte auf einen Öffentlich-rechtlichen Kanal verirrt.

Soweit zum Positiven Gedanken der GEZ. Morgen gibts den zweiten Teil mit meinen Negativen Erfahrungen.

Disclaimer

ALLES was in diesem Text geschrieben wurde basiert auf meinen persönlichen Ansichten und Ansichtsweisen. Da ich auf diesem Gebiet selbst nur Laie bin, und mir die Infos nur angelesen habe, schließe ich auch Inhaltliche Fehler und Unvollständigkeiten nicht aus. Berichtigungen und Kritik sind aber auf jeden Fall willkommen.

Mittwoch, 18. Juni 2008

Peinlich, Mozilla, Peinlich!

Mozilla wirbt seit Tagen für seinen Rekordversuch bei dem sie mit Firefox 3.0 die meisten Downloads in 24 Stunden erreichen wollen. Seit dies bekannt gegeben worden ist, steht die Frage im Raum, wie viele Downloads überhaupt nötig sind. Gerade habe ich die Antwort darauf gelesen:

Das Guiness muss den Rekord allerdings noch anerkennen, denn die Kategorie gab es bisher noch nicht. (via)

Das heißt im Grunde die Frage ist nicht ob man genug Rekordversuche zusammen bekommt sondern legentlich ob der Rekordversuch auch anerkannt wird. Wird er anerkannt hätte wohl auch ein Download gereicht. Wird er nicht anerkannt war sowieso alles umsonst. Und die ganzen 8,2 Millionen Leute hätten ihr Zertifikat wohl ganz umsonst ausgedruckt.

Ich fand die gesamte Aktion nur eine schlechte Marketing-Aktion die mein sowieso schon schlechtes Bild auf Mozilla nur noch mehr beschädigt hat. Allgemein scheint sich die PR-Abteilung, im Moment, komplett im Urlaub zu befinden. Nur so kann ich mir solche Vergleiche erklären. Allgemein versucht man die Masse durch absolut blödsinnige Werbetexte zu begeistern. So scheut man sich auch nicht davor, mit 100% Bio-Software zu werben. Traut man den Firefox Nutzern gar keine Intelligenz zu? Es ist jedenfalls schön zu lesen das ich mein Studium damit zubringe Blaupausen zu malen, die zeigen wie Software im innersten funktioniert. Wie muss man sich Bio-Software vorstellen? Darf ich nun meine Software nicht mehr zur Konservierung radioaktiv bestrahlen? Oder darf ich einfach nur keine synthetischen Schutzmittel mehr verwenden um meine Software frei von Bugs zu halten? Ich finde es gut das eine Firma auf die Idee gekommen ist mit Freier Software zu werben, aber dann soll man dem Kunden doch dies auch zumuten und nicht noch mehr verwirren.

Etwas weiter am Anfang lobt sich Mozilla damit nicht von "Profitmaximierung" getrieben zu werden. Auch diese Erkenntnis war neu für mich. Hat man nicht noch Ende letzten Jahres Thunderbird abgestoßen da dieser zu wenig Geld einspielt? Bei Firefox sieht das schon anders aus. Allein was Google, für die Suchleiste, an Geld rein steckt! Wenn man nun etwas die Gerüchte schüren möchte könnte man glatt behaupten Thunderbird geht zugunsten gmails unter. Wie man kurz darauf gesehen hat wurde es sogar den Core-Entwicklern zu bunt. Auch schön finde ich die Datensammlungspläne von Mozilla um "Einschaltquoten" von Webseiten zu ermitteln. Also so rein, wie sie Mozilla gerne hätte, ist ihre Weste nicht.

Was mich aber nun direkt an Firefox stört? Generell lässt sich das Problem mit dem Satz "Was die Masse gut findet kann nur schlecht sein!" beschreiben. Allerdings will ich mich, zumindest in diesem Post, nur auf das Problem Firefox beziehen. Am meisten stört mich Mozilla! Einmal aus den oben genannten Gründen auf der anderen Seite aber auch ihre Open-Source Politik. Klar Firefox ist (u.a.) unter der GPL veröffentlicht allerdings versucht, meiner Meinung nach Mozilla möglichst alles unter sich zu behalten. Wenn man mal überlegt was alle Open-Source Produkte gemeinsam haben sind dies wohl die Forks. Bei Firefox ist mir nur Flock bekannt. Alle anderen sind gescheitert weil Mozilla keinerlei Hilfe gibt. Ich erinnere mich noch an den Versuch Firefox der auf GTK+ basiert auf QT zu portieren. Leider ist das Projekt unter gegangen da Mozilla hier komplett dicht gemacht hat. Ein anderes Beispiel ist der Namensstreit zwischen Debian und Mozilla bei dem sich Debian vom Namen und Logo gelöst hat. Seit dem bin auch ich bin seit dem demonstrativ auf Iceweasle umgestiegen.

An Firefox merkt man finde ich ganz deutlich: Dieser Browser ist für die Masse gemacht! Es finden sich kaum Einstellungsmöglichkeiten und die Konfiguration erinnert mich an den GAU namens Windows Registry. Schon mal versucht Tastenkombinationen anzupassen? Oder gar einzustellen, welcher Dateityp mit welchem Programm zu öffnen ist? Klar, die Masse an Windowsnutzer braucht so was nicht. Die sind schon froh wenn im Gegensatz zum IE Webseiten korrekt angezeigt werden. Für die Windowsnutzer scheint die Software auch optimiert zu sein. Ich kann mir sonst nicht erklären warum Firefox unter Linux so langsam rendert. Allgemein leidet Firefox an dem Problem der Plattformunabhängigkeit. Dazu kann zwar Firefox selbst nichts, aber ich finde es immer unschön wenn sich ein Programm in keinster Weiße in den Desktop integriert. Bestes Beispiel ist hier wohl der Passwort-Manager. Klar Windowsnutzer kennen so etwas wie Integration nicht, aber gerade Mac OS und auch unter den Linux Desktops werden den Anwendern schöne Systeme geboten um gerade so etwas wichtiges wie Passwörter zentral abzuspeichern. Andere Beispiele finden sich ebenfalls zu Haufen.

Wozu allerdings Firefox etwas kann ist die Integration ins Internet. Klar, Firefox zeigt Webseiten an, aber damit ist es auch schon getan. Zum Beispiel die ursprüngliche Angekündigte Unterstützung von Microformats im Firefox 3 wurde schon nach kurzem in eine API für Erweiterungen herabgestuft. Flock geht, meiner Meinung nach, hier schon eher den richtigen allerdings ist auch dieser Browser weit davon entfernt mir zu gefallen.

Alternativen? Ich nutze auch noch Firefox! ... Leider. Es gibt zwar schon noch einige Browser wie, allerdings sind die alle nicht besser. Konqueror zum Beispiel gefällt mir echt gut, aber leider fehlen mir hier die Plugins. Das ist auch eins der wenigen Dinge die Firefox absolut genial hinbekommen hat! Opera ist leider nicht Frei, weshalb ich ihn auch nie ausprobiert habe. Und sonst? Für den Gnome Desktop gibt es noch einige kleinere Browser wie Epiphany oder Galeon allerdings sind auch diese nicht das Gelbe vom Ei.

Ich warte gespannt auf einen minimalistischen Linux-Fork. Einfach so Dinge wie Bookmarkverwaltung und Passwort-Manager weglassen und statt dessen auf Performance und Konfigurierbarkeit achten. Features sollten dann bei Bedarf einfach über Plugins nachgerüstet werden können. Auf jeden Fall denke ich das Firefox langsam aber sicher seinen Höhepunkt erreicht hat. Zeit für einen neuen Browser!

PS: Dieser Blogbeitrag ist zu 100% Biologisch abbaubar... Wenn er schon nicht ganz Objektiv ist ;-)

Sonntag, 25. Mai 2008

Wissenswertes über Erlang(en)

Viele haben es ja schon mitbekommen, aber nun noch mal für den Rest der Welt: Ich habe ein neues Spielzeug gefunden! Ich bin vor kurzem durch eine Folge im Chaosradio auf die Programmiersprache Erlang gestoßen. Erlang lässt sich mit nur einem Wort beschreiben: anders (alternativ auch genial ;-).

Erlang bezeichnet sich selbst als COPL (Concurrency Oriented Programming Language). Diese Bezeichnung halte ich für sehr treffend. In Objektorientierten Sprachen dreht sich alles um Objekte und in Erlang sind es statt dessen die Prozesse. Ich habe vor kurzem einen Artikel gelesen, in dem es darum ging, dass Prozesse in Erlang doch im Grunde nichts anderes als Objekte in anderen Sprachen sind. Ich halte diesen Vergleich etwas unglücklich, da Erlang eine Funktionale Sprache ist. Am ehesten erinnerte mich Erlang an Prolog, da ich hier auch eine Art Regeln spezifizieren kann und es möglich ist darauf durch Abfragen über Matching zu zugreifen. Allerdings ist Erlang weitaus mächtiger.

Erlang wurde ursprünglich 1987 von Ericsson für Telefonanlagen entwickelt. Und ich muss sagen sie haben sehr gute Arbeit geleistet. Nichts passt besser zu Telefonanlagen als Erlang: In Erlang läuft so gut wie alles parallel. Die Prozesse sind so leichtgewichtig das auch mehrere tausende gleichzeitig von der Performance kaum Auswirkungen haben. Erlang ist hochgradig Fehlertolerant: Sollte ein Prozess abstürzen kann ein anderer diesen einfach neu starten. Und zu guter Letzt: Es ist in Erlang einfach möglich während der Laufzeit Codeteile durch neue zu ersetzen; ohne Unterbrechung der Ausführung.

Durch die Entwicklung in der Praxis ist Erlang keine akademische Sprache sondern (relativ) oft in freier Wildbahn anzutreffen. Spätestens nach der Open Source Variante, die 1998 veröffentlicht wurde, stieg die Beliebtheit rasch an. So gibt es heute eine Vielzahl von Projekten die auf Erlang aufbauen: Das berühmteste Beispiel ist wohl ejabberd ein Jabberserver. Außerdem setzt Amazon mit ihrer SimpleDB ebenso wie Facebook auf Erlang. Es gibt einen hochperformanten Webserver namens yaws und einem gigantischen Benchmark-Tool (Tsung) für z.B. Webserver. Außerdem gibt es eine Datenbank namens Mnesia die sich perfekt in Erlang integriert. Man hat so keine Tabellen mehr wie in Relationale Datenbanken sondern nutzt die Erlang eigenen Datentypen um mit der Datenbank zu kommunizieren. Außerdem kann Mnesia wie eigentlich alles in Erlang verteilt laufen so das es möglich wäre, auf einem Computer die DB im RAM (für Performance) zu halten und auf einem anderen die Datenbank auf Festplatte als Backup. Eine weitere Datenbank die auf Erlang setzt ist couchdb die Dokumenten-orientiert arbeitet.

Doch was macht Erlang so besonders? Programmiert man in einer der üblichen Sprachen macht man immer ein neuen Thread auf wenn man muss. In Erlang macht man immer einen neuen Prozess auf sobald man kann. So ist es theoretisch möglich das ein Erlang Programm auf einer Maschine mit 16 Prozessoren 16 mal schneller als auf einem Prozessor läuft. Die Prozesse in Erlang sind extrem leicht zu erstellen (sowohl von der Syntax als auch von dem Ressourcenverbrauch). Es ist möglich in Millisekunden einfach so mal 30000 Prozesse zu erstellen und wieder zu beenden ohne das die Prozessorauslastung sonderlich steigt.

Threads? Prozesse? Was den nun? So gut wie alle Sprachen bieten Threads für Nebenläufigkeiten an. Erlang hingegen nur Prozesse. Der Hauptunterschied ist: Threads haben gemeinsam genutzten Speicher. Dadurch kommt es immer wieder zu Verklemmungen und Konflikte. Ein Hoher Aufwand muss betrieben werden um dies zu vermeiden. In Erlang geht man einen anderen Weg: Dort hat jeder Prozess exklusiv einen festen Speicher. Kein anderer Prozess kann ihm dazwischen funken. Die Prozesse kommunizieren untereinander durch einfache Nachrichten. Durch dieses Prinzip ist es zum Beispiel möglich ein Programm (fast) ohne umschreiben von einer Einplatzlösung auf mehrere Computer zu verteilen so dass die Programmteile miteinander kommunizieren.

Der andere Vorteil von Erlang ist seine Eigenschaft als funktionale Sprache. So gut wie alle Probleme werden Rekursiv gelöst weshalb es auch keine Schleifen gibt. Außerdem kann man Funktionen einfach in Variablen speichern wodurch man gigantische Möglichkeiten bekommt. Am Anfang muss man sich doch sehr daran gewöhnen das Variablen, die einmal gesetzt wurden nicht wieder überschrieben werden können. Erlang arbeitet nur mit simplen Datentypen wie Tupeln und Listen, allerdings ist die Sprache so gebaut das diese einfachen Konstrukte vollkommen ausreichen. Und das Beste von allem: Der Index dieser Datentypen fängt bei 1 an! (und nicht wie üblich bei 0)

Die Sprache eignet sich perfekt für Serveranwendungen auf die gleichzeitig viele Benutzer zugreifen, allerdings lässt sich auch das tk-GUI Toolkit verwenden wodurch GUI Anwendungen ebenso möglich sind. Sogar ein 3D-Modellierer namens Wings3D ist in Erlang geschrieben.

Wer mehr über Erlang wissen will, dem kann ich nur die oben schon verlinkte Chaosradio-Sendung empfehlen. Die Dokumentation findet Großteils in man-Pages statt, was für Viele etwas ungewohnt ist. Allerdings findet man auch ein sehr gutes Tutorial welches einem die Konzepte näher bringt. Zu der Entstehung der Sprache existiert ein großartiges Video welches ihr unbedingt anschauen müsst! Und zu Letzt muss ich noch unbedingt das Outro von Chaosradio verlinken welches auch ein Grund war die Sprache zu lernen (Foyer des Arts - Wissenswertes über Erlangen).

Ich dachte mir, evtl. besteht ja Interesse an einem kleinen Tutorial hier auf diesem Blog? Wenn ihr sagt euch würde die Sprache interessieren starte ich mal den Versuch ein kleines Tutorial über Erlang zu schreiben.

Donnerstag, 8. Mai 2008

Massendownload

Wie oft steht man vor einem Problem wie es simpler nicht sein könnte? Doch weil man eine besonders elegante Lösung möchte verrenkt man sich dabei beide Arme... So erging es mir gestern wieder. Mein Gedanke war aus einem Directory-Index, wie er von jedem Webserver generiert wird, alle Dateien auszulesen und herunter zu laden. Das Ergebnis sollte allerdings möglichst kurz sein und in nur einem Befehl, ohne irgendwelche Hilfsdateien anlegen zu müssen, abgeschlossen sein.

Nach stundenlangen Versuchen mit sed habe ich nun endlich heute eine Lösung gefunden mit der ich leben kann:

wget -qO- $PARAM | ruby -e "STDIN.each_line{|line| file=line.gsub!(/^<img .*> <a href=\"(.*)\">.*$/, '\1'); puts('wget '+'$PARAM'+file) unless file.nil?}"

Dabei enthält die Variable PARAM meine Webseite und evtl. weitere Parameter. Ein Beispiel wäre eine benötigte Authentifizierung: PARAM="--http-user=XY --http-passwd=XYZ http://example.org/";.

Allerdings ist meine Lösung ist mit ca. 300 Zeichen sicher nicht die kürzeste/eleganteste deshalb hier mein Aufruf: Wer schafft es besser??

Anmerkung: 1.) Überprüft meine Zeile nicht ob es sich wirklich um eine Index Seite handelt und 2.) weiß ich nicht ob es bei allen Index-Seiten funktioniert. Bisher habe ich es glaube ich nur mit Apache-generierten Standard Seiten getestet. Diese kann man allerdings nach belieben anpassen so das es dann evtl. nicht mehr funktioniert. Beim ISS bin ich recht sicher das es nicht geht ... wird der getrost ignoriert. Wenn jemand sonst noch ein Szenario hat, immer her damit!

Montag, 5. Mai 2008

Sinnlose Spielerei ...

... aber trotzdem interessant. Gerade habe ich etwas mit meinen Boot Optionen herum gespielt. Dabei bin ich zufällig auf ein nettes Tool namens Bootchart gestoßen. Dieses Programm analysiert den Boot Prozess und stellt diesen Grafisch da. Ich geb mal eine Kurzeinführung wie man das Programm unter Gentoo zum laufen bringt. Für andere Distributionen sollte die Installation ähnlich verlaufen. Alternativ gibt es in der README noch eine andere Möglichkeit.

Zuerst muss das Paket app-benchmarks/bootchart installiert werden. Da das Programm als masked gekennzeichnet ist muss man die folgende Zeile in die Datei einfügen: echo "~app-benchmarks/bootchart-0.9 ~x86" > /etc/portage/package.keywords. Anschließend das Paket gleich mergen. Dabei unbedingt darauf achten, dass das Java UseFlag aktiviert ist, da sonst später nicht automatisch Bilder erstellt werden.

Nun kommt die Konfiguration dran. In der Datei /etc/conf.d/rc die folgende Option einstellen: RC_BOOTCHART="yes" außerdem in /etc/bootchartd.conf die Option AUTO_RENDER="yes" aktivieren. Wenn man sonst noch etwas wünscht wie zum Beispiel ein anderer Outputpfad oder ein anderes Format kann man dies hier ebenfalls angeben.

Wenn man nun neu startet kann man eine grafische Darstellung des Bootprozesses unter /var/log/bootchart.png (oder so ähnlich, je nach Einstellungen in der Config-Datei) bewundern.

Um ehrlich zu sein ist das ganze (wie Benchmarks allgemein) relativ sinnlos, aber nett anzusehen. Deshalb los, los, ich will euren Bootprozess bewundern ;-). Ich mach schon mal den Anfang:

Donnerstag, 24. April 2008

R.I.P. Lidl

Lidl ist durch ihre Mitarbeiter / Kundenüberwachung in letzter Zeit eigentlich genug in Kritik geraten. Man sollte sich nach diesen Vorwürfen nochmal überlegen ob man dort wirklich einkaufen will. Aber bei diesem Super Angebot heute konnte ich nicht widerstehen:

500 GB externe SATA Festplatte in Aluminiumgehäuse mit Netzwerk-, eSATA- und USB-Anschluss für gerade mal 139 EURO

Und da meine eine externe Festplatte vor kurzem sowieso seinen Geist aufgegeben hat, war dies (trotz Lidl) ein verlockendes Angebot. Soweit zur Theorie... Ich also vor genau drei Wochen um 9:00 Uhr vor dem Lidl gestanden und wollte eben diese Festplatte. Nachdem ich sie nirgends gefunden habe bin ich gleich an die Kasse um dort nachzufragen. Ich dachte ja ich höre nicht recht als man mir sagte, dass die Filiale nur zwei Festplatten geliefert bekommen hat. Ich mich natürlich erstmal total aufgeregt da dies ja nicht das erste Mal ist, dass Lidl vorher groß Werbung macht und dann kaum Exemplare auf Lager hat.

Die Mitarbeiterin, verwies mich allerdings sofort (anscheinend passiert das öfters...) auf die Service-Hotline die groß über dem Ausgang hängt. Ich natürlich gleich mein Handy ausgepackt und versucht dort anzurufen. Aber ich war wohl nicht der Einzige, der mit Lidl seine Probleme hatte. Gegen 11:30 habe ich dann endlich jemanden erreicht, der mir versicherte, dass es eigentlich nicht möglich sei. Er würde versuchen eine andere Festplatte vom Lager zu meiner Filiale zu schicken. Nachdem ich ihm (zugegeben etwas ungern) meine Kontaktdaten gegeben habe versprach er die Festplatte auf meinem Namen zu hinterlegen.

Eine Woche später wurde ich wieder angerufen. Im Lager sind noch Festplatten verfügbar und wenn ich noch Interesse habe, würde man mir eine in meine Filiale schicken. Ich hab mich natürlich erstmal gefreut und gewartet das sich, wie versprochen, meine Filiale meldet sobald die Platte dort eingetroffen ist.

Nachdem ich am Dienstag noch immer nichts von meiner Platte gehört habe, fragte ich halt nochmal nach (Die Nummer hatte ich ja mittlerweile eingespeichert). Wer hätte es gedacht? Mein Platte ist natürlich schon längst in der Filiale, man hatte nur vergessen mich anzurufen. Ich also gleich Abends zum Lidl und Platte abgeholt.

Ab hier wird es Technisch: Nachdem das Teil ja ein Netzwerkanschluss mitbringt bin ich davon ausgegangen das dort ein UNIX sein Dienst verrichtet und mir die Daten per SMB, FTP, NFS etc. zur Verfügung stellt. Das ganze kann man dann über ein Webinterface Verwalten (IP/DHCP etc.). Die Realität sah leider etwas anders aus: Das Laufwerk war von Targa und arbeitete mit ndas dazu in Wikipedia:

Network Direct Attached Storage (NDAS) ist ein proprietäres System für Speichermedien (meist Festplatten), die ohne einen PC oder Server direkt an ein Netzwerk angeschlossen werden können und auf dem Zielsystem wie ein lokaler Datenträger erscheinen.

Software war natürlich dafür nur Windows dabei allerdings habe ich auf der Herstellerseite auch ein "Source"-Paket gefunden. Bis auf ein paar Libs, die nur binär vorliegen, kann man es sich also kompilieren. Das Gentoo-Paket hat etwas ärger gemacht, deswegen habe ich es selbst kompiliert.

Das ganze läuft nun so ab: Die Platte hat eine eindeutige ID. Über die muss man die Platte auf jedem PC, auf dem man sie nutzen möchte, registrieren. Anschließend muss man einen ndas Dienst starten der schaut ob die Platte im Netzwerk ist. Wenn ja erscheint sie dann als Blockdevice und man kann sie wie gewohnt mounten. Blöder weiße kann immer nur ein Computer die Festplatte mounten und zwei mal ist mir beim unmount mein Laptop eingefroren (was mir unter Linux zuvor noch nie passiert ist). Und was das Fass zum überlaufen brachte: Die Funktion mit der ich ein erneutes Suchen nach der Platte anstoßen kann ist nicht eingebaut. So muss man immer den Dienst neu starten um zu suchen. Alles in allem muss ich sagen die Technik ist absoluter Bullshit!

Fazit: Ich habe die Platte gestern zurück getragen und hab mein Geld wieder abgeholt. Auch wenn das Angebot wirklich gut war, ist die Technik dahinter einfach nicht zu gebrauchen. Dann leg ich lieber noch 20€ drauf und hab eine funktionierende Festplatte. Ich muss sagen ich bin einerseits davon enttäuscht wie Lidl verkauft, da sie einfach absichtlich möglichst wenig Festplatten ausliefern. Andererseits auch was Lidl verkauft. Würde nicht mein Miteinkäufer unbedingt immer bei Lidl einkaufen wollen, würde ich wohl in nächster Zeit einen großen Bogen um Lidl machen. (Außer evtl. zum Spaß)

Montag, 7. April 2008

Ich kann nicht Programmieren...

... zumindest kam es mir letzte Woche so vor. Für eine Vorlesung musste ich einen (bis jetzt) vereinfachten Single Sign On - Server schreiben. Da wie gesagt dies bisher nur ein Prototyp ist, war die Implementierung relativ simpel und die Anwendung lief recht schnell. Die nächste Aufgabe bestand daraus den Prototyp mit vorgegebenen Unittests zu testen.

GRAUSAM! Ich dachte naja, zwei drei Tests werden wohl rot sein, aber das gut 60% fehlschlägt hat mich dann doch sehr betroffen gemacht. Die meisten Fehler waren einfach eine fehlende Überprüfung auf Null oder eine vergessene Negation in einer If Abfrage. Ich habe mich darauf hin gleich gefragt warum die Tests so schlecht ausgefallen sind bzw. was man besser machen könnte um solche Fehler zu vermeiden.

Natürlich Methoden wie Unittests, Design by Contract, TDD, etc. sind in aller Munde aber mal ehrlich, nutzt ihr die bei jedem Projekt so ausführlich wie man sollte? Ich bestreite nicht den Nutzen dieser Techniken, auch bin ich mir durchaus benutzt das diese bzw. vergleichbare Techniken in ernsthaften Projekten unabdingbar sind aber ich finde es sind immer noch zu viele Barrieren vorhanden so das die Techniken wirklich Sinn geben. Ich weiß nicht genau wie ich sagen soll, deshalb gibt es mal paar Beispiele:

Ein Unittest ist schnell geschrieben, aber man muss ja prinzipiell jede Mögliche Kombination von Input und Output Werten bzw. auch an Zuständen im System Abdecken. Ein enges System aus Unittests halte ich für sehr sinnvoll, aber wenn sich beispielsweise ein Nutzer mit Name und Passwort an einem Server anmelden will. Was muss ich alles Testen? Was ist wenn Nutzername und/oder Passwort Null sind? Was ist wenn Nutzer und/oder Passwort falsch sind? Was ist wenn der Server nicht erreichbar ist? Was ist wenn der Nutzer bereits angemeldet ist? Was ist wenn der Nutzer überhaupt nicht im System vorhanden ist? Was ist wenn Nutzername und/oder Passwort ein Leerer String sind? Und so weiter. Mir fällt bestimmt noch mehr ein. Und das nur für einen Vorgang! Man stelle sich das mal in einem Komplexen System vor! Außerdem ergibt sich früher oder später die otwendigkeit von Mock Objekten und GUI Tests. Diese Spirale dreht sich so lange hoch bis ich irgendwann mehr Testcode als produktiven Code habe. Und genau hier tritt für mich ein Widerspruch zwischen Theorie und Praxis auf. Ich weiß das es gut ist, ich weiß das man es braucht, aber ich habe keine Ahnung wie man sinnvoll (sowohl logistisch als auch zeitlich) alle Fälle abdecken soll.

Andere Möglichkeit sind Pre- Postconditons. Hier tritt, außer dem Umfangproblem der Unittests, auch noch das Problem der Mangelnden Verbreitung auf. Die Sprachen, die ich mehr oder weniger kenne (Java, Ruby, C(++), Python, Bash, Prolog(:D), ...) bringen Conditions von Haus aus nicht mit. Deshalb bleiben mir zwei Möglichkeiten: Entweder ich lade mir eine zusätzliche Erweiterung der Programmiersprache dazu (was leider wieder andere Probleme wie Kompatibilität und Overhead mit sich bringt) oder ich arbeite mit Asserts. Bringt meine Sprache der Wahl schon Asserts mit habe ich es etwas einfacher. Ansonsten muss man sich erst eine Assert Funktion schreiben (wofür es gerade in Ruby einige sehr schöne Ansätze gibt!). Das Problem was ich hier wieder sehe ist einfach das es keine gezielte Notation der Conditions gibt. Ich habe einfach am Anfang (oder auch am Ende) meiner Funktion 10,20 oder auch mehr Zeilen mit Assert Statements die alle Fälle die mir einfallen abdecken sollten. Blöd nur wenn die Methode selbst nur 5 Zeilen hat. Besser wäre ein Ansatz mit dem man durch die Erweiterung der Sprache eine gesonderte Syntax innerhalb des Methodenkopfes einführt. Und selbst da macht einem die Vielzahl der Möglichen Input- und Output-Werte Kopfzerbrechen.

Ich habe jetzt mal die beiden Methoden herausgegriffen und meine Bedenken dazu geäußert. Ich komme aber irgendwie aus diesem Widerspruch nicht heraus. Um robusten Code zu schreiben muss ich alle Fälle abdecken, wenn ich alle Fälle abdecke, komme ich nicht dazu Code zu schreiben. Klar der Mittelweg ist der beste, aber das dachte ich bei meinem Projekt auch und dann waren doch 60% rot. Es muss doch eine Möglichkeit geben schnell und kurz während ich die Methode schreibe alle Fälle auszuschließen die nicht auftreten dürfen. So eine Technik kann nur funktionieren wenn sei nebenbei, schon fast automatisch, abläuft (sei es nun wirklich automatisiert oder einfach nur durch den Autor). Aber irgendwie kämpfen die Methoden die mir spontan einfallen alle mit massig Overhead.

Wie handhabt ihr das? Schon mal TDD versucht? Geht es euch Ähnlich? Ich bin für Vorschläge dankbar!

Montag, 31. März 2008

Kurzes Statement an alle Programmierer

Aus aktuellem Anlass 3 kurze Statements an alle Programmierer da draußen:

Wenn ihr glaubt man kann durch das Einsetzten toller Tools, Editoren oder Libraries bessere Programme schreiben, dann könnt ihr nicht programmieren!
Ich sehe es an Eclipse: IntelliSense, Projektverwaltung, Wizards alles schön und gut, ich arbeite trotzdem ungern damit! Eclipse hat tausend Einstellungsmöglichkeiten aber versucht mal die Einrückung auf zwei Leerzeichen einzustellen. Warum zum Teufel mach ich tausend Menüpunkte statt einer Configdatei? Warum muss ich eine halbe Minute warten bis ich Eclipse gestartet hab nur um zu schauen ob Änderungen im SVN sind? VIM ist für mich mit Abstand der beste Editor obwohl ich ihn bei weitem noch nicht so bedienen kann wie ich es gerne hätte. Dort ist einfach alles einstellbar, so wie es für jeden richtig ist. Für was brauche ich IntelliSense wenn ich eine Doku hab? Für was brauche ich ein SVN-Plugin wenn ich svn als Programm habe? Eclipse steht nur im Weg wenn man programmiert. Sicher Programmiert es sich so schneller weil man einfach nur seinen Methodennamen vervollständigen lassen muss aber genau in dem Moment gibt man das Denken an die IDE ab. Bevor ich in Eclipse ein Projekt erstellt habe bin ich mit VIM fertig.
Wenn ihr glaubt man kann aus einem UML-Diagramm, einem GUI-Designer oder Anderweitig auch nur Programmteile zusammenklicken, dann konntet ihr noch nie programmieren!
Programmieren hat zu einem kleinen Teil etwas mit einer planbaren Engineeringtätigkeit zu tun. Der Rest besteht aus Erfahrung und einem künstlerischem Prozess. Mit Kunst meine ich keine schöne GUI sondern viel mehr ist es eine Art von künstlerischem Ausdruck. Etwas, das durchaus mit dem spielen eines Instrumentes gleich kommt. KEIN Editor schafft es dies durch ein paar Code-Templates die man im Hintergrund platziert zu komprimieren. Sie gaukeln nur ein schnelles Ergebnis vor bis man ein gewissen Detailgrad erreicht hat und dann kommt der GAU weil der Editor nur noch im Weg steht und komplexe Dinge nicht mehr möglich sind.
Wenn ihr glaub, man muss nicht stetig weiterlernen, dann werdet ihr auch nie programmieren können!
Je nach dem was man als Programmiersprache definiert sollten zwei neue Sprachen im Jahr locker drinnen sein. Jeden Monat ein Buch zu einem neuen Thema sollte auch möglich sein. Bevor man sich mit einem neuen Thema beschäftigt => Buch lesen. Bevor man versucht etwas durch probieren zum laufen zu bekommen => Buch lesen. Ziel ist es zu wissen was man tut und nicht Beispiele aus einem Online Tutorial herauszukopieren und zu hoffen das es Funktioniert!

Schlechte Programme sind das Übel der Neuzeit. Früher gab es die Pest, heute reichen dazu ein paar Programmierer. Programmieren hat nichts mit Syntax zu tun. Programmieren ist einfach ein Gefühl welches sich durch Code ausdrückt!

Anmerkung: Das ganze ist natürlich (mal wieder) übertrieben und nicht ganz ernst gemeint. Deswegen ist es leider nicht weniger wahr.

Samstag, 15. März 2008

ssh-agent Startscript

Nachdem ich zufällig auf einige interessante Möglichkeiten von SSH gestoßen bin entschloss ich mich vor meinen Semesterferien das Buch "SSH, The Secure Shell" auszuleihen. Ich muss sagen wenn dieses Buch ist schon fast die SSH Spezifikation. Dort steht wirklich alles drinnen. Zum Lesen völlig ungeeignet allerdings für Ideen und zum Nachblättern gar nicht mal so schlecht.

So bin ich auch auf Authentifikation über SSH-Keys gestoßen. Normalerweise gibt man sein Passwort ein, wenn man sich auf einem Server anmeldet. SSH-Keys funktionieren allerdings eher wie GPG Verschlüsselung. Man generiert einen Public Key, den man auf allen Servern, bei denen man sich anmelden möchte, hinterlegt. Außerdem noch einen Privat Key mit dem sich jeder, bei allen Server auf denen der Public Key hinterlegt ist, anmelden kann. Das funktioniert einfach, in dem der Server mit dem Public-Key eine Challenge verschlüsselt und diese dem Client zusendet. Dieser entschlüsselt die Nachricht wieder und sendet es zurück. Stimmen die Nachrichten beim Server überein wird der Nutzer rein gelassen. Allerdings kann dann wie schon gesagt jeder der den Private Key kennt auch auf den Server zugreifen. Um dies etwas zu erschweren kann man ein Passwort definieren das für den Privaten Key benötigt wird. Man sieht schon, im Grunde nichts anderes als GPG. In Wirklichkeit kann man sogar (mit den nötigen Einstellungen) seinen GPG Key dafür nutzen.

Nun hat man zwar SSH-Key, allerdings darf man nun wieder jedes mal sein Passwort eingeben. Man hat also nichts gewonnen. Dafür gibt es nun (ebenfalls aus der GPG-Welt bekannt) einen Agent, der die Key einmal lädt, dabei das Passwort abfragt und anschließend auf Anfragen reagiert. So muss man nicht jedes mal neu sein Passwort eingeben. Sehr praktische Geschichte! Leider ist die Syntax etwas umständlich und auch muss jeder Key einzeln geladen werden. Deshalb habe ich mir etwas den Kopf zerbrochen wie man dies automatisieren kann. Dabei ist das folgende Script entstanden. Es schaut bei jedem Aufruf (in der Regel sobald sich eine neue Shell öffnet) ob der SSH-Agent läuft. Außerdem lädt es die Keys Automatisch so das man nur noch die Passwörter eingeben muss. Außerdem ermöglicht es über die beiden Funktionen start-ssh-agent und load-ssh-indentities dies auch Manuell durchzuführen.

Um zu verstehen wie das Script funktioniert muss man sich erst einmal anschauen wie der ssh-agent bekannt gibt es es ihn gibt. Ruft man ihn einfach mit dem ssh-agent Kommando auf (was der falsche Weg ist), erscheinen einige Variablen. Diese Variablen sind wichtig damit der ssh-Client auf den Agent zugreifen kann. Der Agent selbst läuft vom Terminal losgelöst. Er wird also nicht beendet wenn die Session beendet wird sondern läuft im Hintergrund weiter. Einer der richtigen Wege (es gibt mehrere Möglichkeiten) wäre eval `ssh-agent`. Hier wird zuerst der ssh-agent aufgerufen und die Ausgaben ausgeführt. So werden die Variablen im aktuellen Terminal bekannt gegeben. Möchte man nun auch in einer anderen Session auf den Agent zugreifen muss man dort auch einfach nur die Variablen bekannt machen. Da der Agent wie gesagt unabhängig von der aktuellen Session läuft interessiert es nicht aus welcher Shell er gestartet wurde.

$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-Yvpvk13029/agent.13029; export SSH_AUTH_SOCK;
SSH_AGENT_PID=13045; export SSH_AGENT_PID;
echo Agent pid 13045;

Mein kleines Script macht im Grunde nichts anderes als diese Variablen in einer Datei zu speichern und bei jedem anmelden diese einzulesen. Außerdem lädt es alle Identitäten die in in dem Verzeichnis ~/.ssh/keys/ liegen. Wichtig ist, dass dort nur Private-Keys liegen dürfen; keine Public-Keys!

# Lädt alle Indentitäten im Verzeichnis ~/.ssh/keys/
function load-ssh-indentities() {
  # Prüft erst ob ein tty verfügbar ist
  if tty -s ; then
    for FILE in ~/.ssh/keys/* ; do
      ssh-add $FILE
    done
  fi
}

# Startet den SSH-Agent mit einer Indentitäten-Lifetime von einer Stunde
# und schreibt die Variablen in die ~/.ssh_agent_vars Datei
function start-ssh-agent() {
  eval `ssh-agent -s -t 3600`
  echo -e "export SSH_AGENT_PID=$SSH_AGENT_PID\nexport SSH_AUTH_SOCK=$SSH_AUTH_SOCK" > ~/.ssh_agent_vars \
  && echo "SSH-Agent gestartet"
}

# Fragt erst nach ob Indentitäten geladern werden sollen.
function _ask_load_ssh_indentities() {
  echo "Indentitäten laden? (y/N)"
  read ANSWER
  ( [ "$ANSWER" = "y" ] || [ "$ANSWER" = "Y" ] ) && load-ssh-Indentitäten
}

# Die Variable SSH_AUTH_SOCK wird für den SSH-Agent benötigt und sollte gesetzt sein wenn er läuft.
if [ "$SSH_AUTH_SOCK" = "" ]; then
  # Es wird geprüft ob die Datei ~/.ssh_agent_vars vorhanden ist.
  if [ -f ~/.ssh_agent_vars ]; then
    # Wenn ja wird diese Includiert und geprüft ob die Variablen darin noch gültig sind.
    source ~/.ssh_agent_vars

    # Prüft ob es ein ssh-agent Prozess mit der PID gibt und das Socket existiert.
    if ( ps -p $SSH_AGENT_PID  | grep -q ssh-agent ) && [ -e $SSH_AUTH_SOCK ]; then
      # SSH-Agent ist gestartet Vorhandene Indentitäten werden angezeigt.
      echo "SSH-Agent ist bereits gestartet Geladene Indentitäten:"
      ssh-add -l
    else
      # Die Variablen sind nicht mehr gültig. Datei wird gelöscht und SSH-Agent wird neu gestartet.
      echo "~/.ssh_agent_vars Datei existiert aber es ist kein Agent gestartet. Starte Agent."
      rm ~/.ssh_agent_vars
      start-ssh-agent && _ask_load_ssh_indentities
    fi
  else
    # Datei ist nicht vorhanden. Es wird geprüft ob SSH-Agent läuft.
    if ps u -C ssh-agent | grep -q ssh-agent ; then 
      echo "SSH-Agent läuft aber es existiert keine ~/.ssh_agent_vars Datei!"
      echo "SSH-Agent muss gestoppt werden und mit 'start-ssh-agent' neu gestartet"
      # Weiteres Vorgehen dem User überlassen
    else
      # Wenn nicht wird er gestartet.
      start-ssh-agent && _ask_load_ssh_indentities
    fi
  fi
else
  # Variable ist schon gesetzt. Es wird geprüft ob SSH-Agent auch wirklich läuft
  if ps u -C ssh-agent | grep -q ssh-agent ; then 
    echo "SSH-Agent ist bereits gestartet. Geladen Indentitäten:"
    ssh-add -l
  else
    # Tritt nur bei Subshells auf, wenn die Variable in die Subshell
    # übergeben wurde obwohl der Agent schon beendet wurde.
    echo "SSH_AUTH_SOCK Variable ist gesetzt aber SSH-Agent läuft nicht!"
    # Weiteres Vorgehen dem User überlassen
  fi
fi

Das Script muss am besten in die Datei ~/.bashrc eingefügt werden. Dabei ist wichtig, dass dies nicht in einer Subshell ausgeführt werden darf. Deshalb direkt in die bashrc kopieren oder mittels source einbinden. Da es sonst Namespace-Probleme mit Variablen und Funktionen gibt darf es nicht über exec eingebunden werden (deshalb auch kein #!/bin/bash am Anfang).

Für Kritik und Verbesserungsvorschläge bin ich immer offen. Getestet habe ich das Script bis jetzt mit Bash 3.2.17 und zsh 4.3.4. Einziger Kritikpunkt den ich schon jetzt von meiner Seite habe: Das Script merkt natürlich nicht wenn der User nicht mehr angemeldet ist. Da der Agent unabhängig von der Session ist läuft er einfach weiter auch wenn der User schon längst über alle Berge ist. Das ist in so weit ein Problem da man theoretisch einen Speicherdump des ssh-agent Prozesses machen kann und dann alle Keys vorfindet. Um dies zu verhindern habe ich die 60 Minuten Sperre eingebaut. So scheißt der Agent nach 60 Minuten alle Keys raus und man muss sie neu laden. Leider ist das etwas unschön. Ich habe allerdings (noch) keine bessere Idee.

Montag, 10. März 2008

Fortgeschrittene Paketverwaltung mit Gentoo

Wer kennt das nicht. Man installiert ein Programm und irgend eine Kleinigkeit passt einem nicht. Sei es ein kleiner Bug oder ein fehlendes Feature. Oftmals kann man dies durch ein kurzes Patchen des Source Codes ausbügeln. Bisher unter Debian basierenden Distributionen war dies immer ein reißen Problem. Man musste manuell die Source herunterladen diese Patchen alle Abhängigkeiten herausfinden und installieren, Kompilieren und schließlich auch noch ein DEB-Paket erstellen und in die Paketverwaltung zurückführen. Wer das öfters machen muss wird wahnsinnig.

Bei der Installation von Gentoo bin ich auf ein richtig Cooles Feature gestoßen. Es gibt die Möglichkeit von Overlays. Das sind im Grunde weitere Repositories, die ebuilds, also die Gentoo-Pakete, enthalten. Richtig komfortabel wird dies da man über das Programm Layman einfach ein solches Repository bei sich einfügen kann, um dann daraus Software zu installieren. Im Prinzip wie bei Debian auch, nur das es viel anpassbarer ist. So besteht z.B. die Möglichkeiten das Repository über rsync, svn, git, bzr, etc. abzurufen und so zu aktualisieren. Im Gegensatz dazu sind auch Lokale Overlays möglich. Dabei legt man einfach ein Verzeichnis an und schmeißt die ebuilds die man installieren möchte einfach rein. Sehr komfortabel da man so kein Unterschied merkt ob diese Pakete nun Lokal in einem Overlay liegen oder aus dem offiziellen Portagetree kommen.

Hier ein kurzes Beispiel für ein Ebuild das aus einem lokalen Overlay installiert wird. Zuerst einmal das entsprechend Verzeichnis anlegen. Ich habe es unter /usr/portage/local/ gelegt, da dort auch Layman seine Dateien ablegt. Empfohlen wird normal /usr/local/portage/ allerdings sollte das relativ egal sein.

Ich zeige das ganze mal am Beispiel von Eqonomize. Dazu schmeißen wir einfach das heruntergeladen Ebuild in den Unterordner app-office/eqonomize. Anschließend noch kurz ein ebuild app-office/eqonomize/eqonomize-0.5.ebuild digest. Dies erstellt ein Manifest was einfach einige Checksummen zur Überprüfung enthält. Jetzt muss nur noch das Lokale Overlay in Portage bekannt gemacht werden. Das geschieht einfach über die Variable PORTDIR_OVERLAY="/usr/portage/local/local-overlay" die wir in der Datei /etc/make.conf hinzufügen müssen. Das einzige was noch fehlt ist das synchronisieren des Portage. Ich nutze dazu eix-sync da mir einfach die Ausgaben besser gefallen. Mit emerge geht's natürlich genauso.

Soweit meine Kurzeinführung in Lokale Overlays. Jetzt aber zu dem eigentlichen Feature. Ich bin es Leid bei ntfs3g jedes mal locale=de_DE.utf8 mitzugeben damit Umlaute richtig dargestellt werden. Deshalb möchte ich es gerne automatisch einfügen wenn ich mount.ntfs aufrufe. Das löse ich einfach über ein Patch im Lokalen Overlay. Ob dieses Beispiel jetzt sinnvoll bzw. der Aufwand gerechtfertigt ist sei mal dahin gestellt.

Dazu erst einmal ein Verzeichnis erstellen und die Aktuelle ntfs3g Version aus dem Portage kopieren. Der Unterordner files lege ich schon mal für den Patch später an.

mkdir -p /usr/portage/local/local-overlay/sys-fs/ntfs3g/files/

cp /usr/portage/sys-fs/ntfs3g/ntfs3g-1.1120.ebuild /usr/portage/local/local-overlay/sys-fs/ntfs3g/
cp /usr/portage/sys-fs/ntfs3g/metadata.xml /usr/portage/local/local-overlay/sys-fs/ntfs3g/

Anschließend die Datei /usr/portage/local/local-overlay/sys-fs/ntfs3g/ntfs3g-1.1120.ebuild Editieren und oben bei inherit multilib toolchain-funcs noch eutils hinzufügen. Außerdem weiter Unten noch folgenden Block, der das Auspacken und Patchen erledigt, einfügen:

src_unpack() {
      unpack ${A}
      cd "${S}"
      epatch "${FILESDIR}"/Makefile.am.patch
      epatch "${FILESDIR}"/Makefile.in.patch
}

Das war's so weit jetzt müssen wir noch die beiden gepatchen Makefiles erstellen. Dazu einfach das bestehende ebuild auspacken in /tmp/ verschieben und die beiden benötigten Dateien mit der Endung *.change kopieren

ebuild /usr/portage/local/local-overlay/sys-fs/ntfs3g/ntfs3g-1.1120.ebuild unpack

cp -r /var/tmp/portage/sys-fs/ntfs3g-1.1120/work/ntfs-3g-1.1120 /tmp/

cp /tmp/ntfs-3g-1.1120/src/Makefile.am /tmp/ntfs-3g-1.1120/src/Makefile.am.change
cp /tmp/ntfs-3g-1.1120/src/Makefile.in /tmp/ntfs-3g-1.1120/src/Makefile.in.change

Diese Dateien ändern wir nun. Als erstes Kommentieren wir die Zeile aus die den Link von ntfs-3g auf mount.ntfs-3g anlegt. Dann Fügen wir über echo Zwei Zeilen in die neue /sbin/mount.ntfs-3g Datei ein die ntfs-3g mit dem gewünschten Parameter aufrufen. Wer sich über die Maskierung wundert einfach mal ausführen und Anschauen. Ich hab ewig gebraucht bis ich das raus gefunden habe. Zu Letzt geben wir der Datei noch Ausführungsrechte und erstellen einen Link auf mount.ntfs. Das ganze muss in beiden Dateien (Makefile.in und Makefile.am) jeweils unter install-data-local: und install-exec-local: eingefügt werden. Die beiden Dateien sollen unter uninstall-local: auch wieder gelöscht werden.

-- vim -O /tmp/ntfs-3g-1.1120/src/Makefile.*.change
(install-data-local:|install-exec-local:)
#$(LN_S) -f $(bindir)/ntfs-3g $(DESTDIR)/sbin/mount.ntfs-3g
echo -e '#!/bin/bash\nntfs-3g "$$@" -o locale=de_DE.utf8' > $(DESTDIR)/sbin/mount.ntfs-3g
chmod +x $(DESTDIR)/sbin/mount.ntfs-3g
$(LN_S) -f $(DESTDIR)/sbin/mount.ntfs-3g $(DESTDIR)/sbin/mount.ntfs

uninstall-local:
$(RM) -f $(DESTDIR)/sbin/mount.ntfs
$(RM) -f $(DESTDIR)/sbin/mount.ntfs-3g
-- :wqa

Nun erstellen wir ein Patch zwischen der geänderten und der original Version. Das bash -c hilft mehrere Befehle auf einmal auszuführen. Das ist besonders hilfreich wenn man wie ich mit sudo arbeitet. Da man sonst evtl. keine Berechtigungen hat in die Datei zu schreiben. Die geänderten Dateien nun in unser lokales Overlay kopieren und wieder ein Manifest erstellen.

bash -c "cd /tmp/; diff -uN ntfs-3g-1.1120/src/Makefile.in ntfs-3g-1.1120/src/Makefile.in.change >  ntfs-3g-1.1120/src/Makefile.in.patch"
bash -c "cd /tmp/; diff -uN ntfs-3g-1.1120/src/Makefile.am ntfs-3g-1.1120/src/Makefile.am.change >  ntfs-3g-1.1120/src/Makefile.am.patch"

cp -v /tmp/ntfs-3g-1.1120/src/Makefile.*.patch /usr/portage/local/local-overlay/sys-fs/ntfs3g/files/

ebuild ntfs3g-1.1120.ebuild digest

Wer noch nicht die Variable für das lokale Overlay in die Datei /etc/make.conf eingefügt hat sollte das jetzt tun. Ansonsten wieder mit eix-sync synchronisieren. Hier sieht man dann das ein Update zwischen dem Originalen Portage und unserem Overlay statt gefunden hat. Installiert man nun wie gewohnt die Datei sieht man auch, dass das Portage gewechselt hat. Wenn man schnell genug ist, und ich die Ausgabe von emerge anschaut, sieht man sogar wie unsere beiden Patchs ausgeführt werden.

-- eix-sync
[ebuild   R   ] sys-fs/ntfs3g-1.1120  USE="-debug -suid" 0 kB [0=>1]
[0] /usr/portage
[1] /usr/portage/local/local-overlay
--

-- emerge -vat ntfs3g
[ebuild   R   ] sys-fs/ntfs3g-1.1120  USE="-debug -suid" 0 kB [1]

Total: 1 package (1 reinstall), Size of downloads: 0 kB
Portage tree and overlays:
 [0] /usr/portage
 [1] /usr/portage/local/local-overlay
--
--
>>> Unpacking ntfs-3g-1.1120.tgz to /var/tmp/portage/sys-fs/ntfs3g-1.1120/work
 * Applying Makefile.am.patch ...                                                                                                                                [ ok ]
 * Applying Makefile.in.patch ...                                                                                                                                [ ok ]
>>> Source unpacked.
--

So nun sollte alles Funktionieren. Man kann nochmal über eix nach unserem Paket suchen. So sieht dann dass die Version unseres Overlays installiert ist. Außerdem sollte man nochmal checken ob die Datei richtig erstellt worden ist und auch die Rechte und der Link so passen.

-- eix ntfs3g
[I] sys-fs/ntfs3g
     Available versions:  1.810 ~1.1030 ~1.1104 1.1120 1.1120[1] ~1.2129 ~1.2216 {debug suid}
     Installed versions:  1.1120(16:14:30 03/08/08)(-debug -suid)
     Homepage:            http://www.ntfs-3g.org
     Description:         Open source read-write NTFS driver that runs under FUSE

[1] /usr/portage/local/local-overlay
--

-- cat /sbin/mount.ntfs-3g
#!/bin/bash
ntfs-3g "$@" -o locale=de_DE.utf8
--

-- ls -l /sbin/mount.ntfs-3g
-rwxr-xr-x 1 root root 46  8. Mär 20:13 /sbin/mount.ntfs-3g
--

-- ls -l /sbin/mount.ntfs
lrwxrwxrwx 1 root root 19  8. Mär 20:13 /sbin/mount.ntfs -> /sbin/mount.ntfs-3g
--

Ich finde diese Möglichkeit absolut praktisch. Beachten sollte man allerdings, dass das lokale Overlay vor dem offiziellen Portage Vorrang hat, aber wenn jetzt z.B. die Version 1.2216 in unserem Portagetree stable wird dann hat diese vor dem lokalen Overlay Vorrang da sie aktueller ist. In diesem Sinne, fröhliches Merging!

Sonntag, 9. März 2008

Eine Woche Gentoo...

Nun ist es schon eine ganze Woche her seit dem ich kurz entschlossen angefangen habe Gentoo zu installieren. Alles in allem war die Installation bisher einfacher als erwartet. Allerdings dauerte es auch länger als ich dachte. Ich kann noch lange nicht sagen das alles fertig installiert und eingerichtet ist.

Mein altes Kubuntu 7.04 ist langsam doch in die Jahre gekommen. Außerdem ärgerte ich mich immer wieder über die Paketverwaltung da teilweise unschöne Abhängigkeiten, veraltete Pakete und wenig Anpassungsmöglichkeiten einem das Leben schwer machen. Allgemein bin ich warscheinlich aus der Zielgruppe von *buntu raus gewachsen, da zwar die Oberfläche schön und Sinnvoll eingerichtet ist (was mir jetzt nach dem Umstieg besonders auf fällt), allerdings dahinter absolutes Chaos herrscht. Wer wie ich gerne auf CLI-Basis arbeitet fällt dies sicher besonders auf. Bestes Beispiel ist der Networkmanager der nie tut was er soll. Jetzt habe ich einfach ein paar Konfigurationsdateien geschrieben und Netzwerk läuft ohne Probleme. Ebenso automatisches Einbinden von Wechseldatenträger etc. Ich glaub da kann man noch genug Beispiele finden. Und zu guter Letzt ärgerte es mich das Kubuntu, welches ich als KDE-Fan verwendet habe, von den *buntu Entwicklern eher vernachlässigt wurde.

So habe ich viel Hoffnung in Gentoo gesteckt und wurde auch im Großen und Ganzen nicht enttäuscht. Hier mal meine ersten Eindrücke von der Installation und einer Woche im Gebrauch. Außerdem vielleicht ein paar Tipps am Rande die dem ein oder anderen Umsteiger das Leben etwas einfacher machen sollte.

Installation

Wer auf einen Installer, wie man ihn in den meisten anderen Linux Distributionen kennt, hofft wird enttäuscht. Statt dessen startet man mit einer Live-CD und partitioniert so mit den gewohnten Programmen seine Festplatte und kopiert einige wichtige Programme. Anschließend wechselt man mit chroot auf die so erstellte Minimalumgebung und beginnt Programme wie den Bootmanager grub oder ein DHCP-Client zu installieren. Das erste mal wo ich wirklich geschockt wurde, war die Kernel Konfiguration. Man (darf|muss) jede Kerneleinstellung selbst setzten. Ich war damit erstmal völlig überfordert. Bisher habe ich allerdings bestimmt 30 Mal mein Kernel neu kompiliert und mittlerweile ist das Konfigurieren nichts mehr besonderes. Man sollte sich nur von Anfang an klar machen das man nicht alles gleich richtig einstellen kann. Einfach mal rum Probieren. Ganz wichtig für die komplette Installation ist das Handbuch. Ich rate jedem danach vor zu gehen.

Paketverwaltung

Man muss sich hier am meisten umgewöhnen. Binärpakete, wie unter den meisten anderen Distributionen, gibt es unter Gentoo nicht mehr. Statt dessen lädt man sich den Sourcecode herunter und kompiliert diesen selbst. Das hört sich schwerer an als es ist. Es gibt trotzdem eine Paketverwaltung. So das ein einfaches emerge PAKETNAME ausreicht um ein Paket mit allen Abhängigkeiten zu installieren. Es wird der Sourcecode heruntergeladen und wie man das auch von manuellen Kompilieren kennt configure und make aufgerufen. Wer öfters selbst kompiliert wird die Flags bei configure kennen. Man kann hier entscheiden ob einzelne Module kompiliert werden sollen oder eben nicht. Dies ist bei Gentoo sehr cool über so genannte USE-Flags gelöst die man zentral oder für einzelne Pakete angeben kann.

Man kann sich mit Use-Flags aber auch viel kaputt machen. Hier ein Tipp von mir: Am Anfang wenig USE-Flags nutzen und lieber später erneutes kompilieren mit veränderten Flags in kauf nehmen. Sonst passiert es euch wie mir, dass man eigentlich nur wpasupplicant für WPA Support installieren will aber gleichzeitig noch der Druckserver Cups, ein X-Server und die QT-Libraries als Abhängigkeiten mit kommen. Außerdem bei jedem Kompilieren bei emerge die Parameter für --verbose, --ask und --tree mitgeben um alle USE-Flags und Abhängigkeiten zu prüfen. Bestes Beispiel, bei dem man aufpassen muss, ist Eclipse. Will man dies in der Version 3.3 installieren und man passt mit den USE-Flags nicht auf so hat man danach Java 1.4, Java 1.5 und Java 6 installiert. Richtig freuen kann man sich aber auf der anderen Seite wenn man Psi mit dem USE-Flag "extra" kompiliert da Psi dann einige richtig coole neue Features hat. Oder wenn man Firefox mit "iceweasel" merged. Damit wird das Iceweasel Branding aktiviert. Leider ist nicht immer klar was ein USE-Flag jetzt genau bewirkt.

Einige sehr coole Features sind ccache und distcc. Distcc ist für verteiltes Kompilieren der Pakete was ich leider nicht ausprobieren konnte da es mir dazu an Computern fehlt. Ccache ist ein schneller Compiler Cache der Zwischenresultate speichert. So ist es möglich ein Programm viel schneller zu kompilieren wenn man es schon einmal übersetzt hat. Ich rate jedem ccache als eines der ersten Dinge auf dem System einzurichten. Mittlerweile schaffe ich es damit mein Kernel mit recht vielen Modulen in ca. sieben Minuten zu kompilieren. Ohne ccache dauert es bei mir fast 25 Minuten.

Insgesamt muss man beim installieren und vor allem beim deinstallieren sehr aufpassen da eventuelle Abhängigkeiten beim Deinstallieren nicht berücksichtigt werden. Außerdem kann es passieren das Programme nicht mehr laufen wenn man von Abhängigkeiten die USE-Flags ändert. Dafür hat man aber auch wahnsinnige Möglichkeiten (die ich evtl. die nächsten Tage näher beschreiben werde). Das einzige was ich wirklich vermisse ist mein geliebtes aptitude. Mit der Zeit kommt man aber auch ganz gut so zurecht. Nur weiter empfehlen kann ich eix auf das mich Klaus gebracht hat. Damit kann man sehr komfortabel sein Portage durchsuchen. Ansonsten helfen die drei Portage Seiten sehr weiter.

Man gewöhnt sich ans kompilieren allerdings freut man sich doch wenn zwischendurch mal ein Binärpaket wie z.B. den Grafikkartentreiber oder Flash erwischt da dann die Kompilierzeit auf 0 gedrückt wird.

GUI

Hier blickt man gerne auf *buntu zurück. Gentoo installiert zwar die Pakete, allerdings konfigurieren muss man das selbst. So ist es nicht so einfach unter KDE die Schriftgröße von Firefox anzupassen. Auch muss man zum Teil erst manuell definieren welche Dateien mit welchem Programm geöffnet werden sollen. Besonders beim Firefox ist das nervig. Aber da ich sowieso mit dem Gedanken spiele mich von dem kompletten KDE-Environment etwas weg zu bewegen und lieber mit anpassbaren und schnelleren Window-Managern zu arbeiten, komme ich so oder so nicht um die Konfiguration rum.

Was mir hier überhaupt nicht gefällt sind die "Metapakete". Metapakete sind Pakete die andere Pakete enthalten. So installiert man zum Beispiel nur kdepim und das gesamte KDE-PIM-Environment wird installiert. Leider aber nicht die einzelnen Komponenten als Abhängigkeit. So ist z.B. KMail in KDE-PIM enthalten und noch einmal als extra Paket. Will ich jetzt KMail deinstallieren geht das nicht weil das Paket KMail ist nicht installiert. Sondern nur kdepim was halt zufällig KMail enthält. Das ganze ist etwas unschön aufgebaut und ich bin noch nicht hinter den Grund gekommen. Ich hatte unter *buntu schon wenig für Metapakete übrig aber so ist das noch schlimmer.

Leider verfolgt mich auch das leidige nvidia-Treiber Thema welches ich im Zusammenhang mit Framebuffer und nvidia Treiber habe. Ich kann unter Konsole normal arbeiten aber sobald ich X mit nvidia Treiber starte komme ich nicht mehr zurück auf Konsole. Abhilfe schafft nur der langsamere xf86-video-nv Treiber der auch keine 3D Unterstützung anbietet. Allerdings habe ich jetzt schon andere Leute gefunden die das selbe Problem haben. Liegt also nicht an mir ;-)

Fazit

Der Umstieg hat sich auf jeden Fall gelohnt. Auch wenn ich noch ein bisschen Arbeit vor mir habe. Die Paketverwaltung ist echt cool und auch sonst glänzt es mit Anpassungsmöglichkeiten. Ich sag nur drei System-Logger und drei Cron-Daemons die allein im Handbuch beschrieben werden. Auf der anderen Seite muss ich mich über Details wie so manche Abhängigkeit oder eben der Metapackete wundern. Auch das Bash die Standard Shell ist hat mich als zsh Fan sehr überrascht. Ich bin allerdings froh das ich umgestiegen bin auch wenn ich noch einiges an Zeit reinstecken muss. Die sehr gute Community und die vielen Wikis und Foren helfen mir dabei sehr. In Sachen Dokumentation ist Gentoo auf jeden Fall vorne mit dabei!

Mittwoch, 13. Februar 2008

Mono Funktional

Obwohl ich absolut kein Plan von C# und .Net habe und auch sonst Microsoft ... hasse, konnte ich doch der Werbung zu dem F#-Tutorial von Andreas nicht widerstehen. Da es für mich auf keinen Fall in Frage kommt Windows zu installieren habe ich die freie, .Net kompatible Laufzeitumgebung Mono installiert. Da dies nicht so einfach ging hier ein kurzes HowTo. Anmerkung: Ich weiß nicht ob alle diese Schritte genau so notwendig sind, da ich wie schon erwähnt mich auf dem Gebiet nicht auskenne, aber so läuft alles.

Zuerst einmal die Laufzeitumgebung inklusive Libraries und C#-Compiler installieren. Da ich (noch) Kubuntu nutze hier erläutere ich hier mal nur den Ubuntu-Weg. In allen anderen Distributionen sollte es allerdings ähnlich ablaufen. Anmerkung: Installiert braucht Mono gut 100MB, also mal kurz installieren und testen lohnt fast nicht.

sudo apt-get install mono-devel

Da dies soweit ich das beurteilen kann allerdings nur den C# 1.0 Compiler installiert installieren wir noch den 2.0 Compiler inklusive Libraries nach. Außerdem werden noch für C# zwei zusätzliche Libraries benötigt:

sudo apt-get install mono-gmcs libmono-winforms1.0-cil libmono-system-runtime2.0-cil

Jetzt sollte Mono so weit laufen. Testen kann man dies indem man ein Beispiel von der Student Homepage herunter lädt (Wenn das mal kein Werbebonus gibt) und mit gmcs Program.cs kompiliert. Ausführen lässt sich das Ergebnis einfach mittels mono Program.exe. Das einzige was noch zu klären bleibt: Warum zum Henker machen Windowsanhänger bei Konsolenprogrammen immer ein Console.ReadLine(); am Ende? ;-)

Soweit zu Mono. Jetzt kommt der F# Teil. Erst einmal F# downloaden. Am besten wählt man hier Download F# 1.9.3.14 als Zip aus. Das Paket entpacken und als Administrator installieren. (Gefällt mir ja überhaupt nicht ein Microsoft Produkt als Administrator auf meinem Rechner auszuführen.) Hierzu einfach das mitgelieferte Bashscript ausführen:

sudo bash install-mono.sh

Dieses Script installiert F# und kompiliert das ganze in das bin-Verzeichnis. Hat alles so weit geklappt ist man nun (mehr oder weniger) stolzer Besitzer von F# und kann sich gleich an der ersten Aufgabe von Andreas versuchen.

Als Beispiel gleich mal meine Lösung:

#light
open System
let rec (!) (a : int) =
  if (a = 1) then
    a
  else
    let a2 = a - 1
    a * !a2

printfn "Zahl eingeben:"
let a = read_line ()
let endresult = !Convert.ToInt32(a)
printfn "Die fakultaet von %s ist %i" a endresult

Das wird nun mit folgendem Befehl erst kompiliert und anschließend ausgeführt:

downloads/FSharp-1.9.3.14/bin/fsc.exe fakultaet.fs
mono fakultaet.exe

Wenn man dem Binary Ausführungsrechte gibt kann man es auch einfach mittels ./fakultaet.exe ausführen. Das einzige was jetzt noch schön wäre, ist ein vim Syntax-Style für F#...

Bleibt abzuwarten wann Tutorial Teil 3 folgt. Ich bin gespannt!

Samstag, 9. Februar 2008

Willkommen zurück

Nachdem ich gestern die letzte Prüfung hinter mich gebracht habe. Bin ich heute offiziell in meine Ferien gestartet. Jetzt heißt es erst einmal Aufarbeiten was sich so angesammelt hat. Die nächsten 5 Wochen sind eigentlich schon relativ verplant mit Gentoo installieren, zwei Server einrichten, Python anschauen, und vor allem Bücher lesen.

Das bringt mich auch gleich zu dem absolut völlig sinnlosen Stöckchen das mir Aaron zugeworfen hat. Die Bücher die gerade vor mir liegen:

Das Stöckchen gibt es allerdings nur für das letzte Buch:

  1. Nimm das nächste Buch in deiner Nähe mit mindestens 123 Seiten.
  2. Schlage Seite 123 auf.
  3. Suche den fünften Satz auf der Seite.
  4. Poste die nächste drei Sätze.
Er würde den Stich von St. Clement's Dane kaufen, ihn aus dem Rahmen nehmen und unter seinem Overall nach Hause tragen. Er würde Mr. Charrington den Rest dieses Gedichtes aus dem Gedächtnis reißen. Sogar sein Irrsinnsplan, das Zimmer oben zu mieten, schoß ihm erneut durch den Kopf.

Eigentlich ein super Buch, ich sollte es nur endlich mal fertig lesen.

Da ich Stöckchen total fürn Arsch finde und dann noch so Sinnlose, bleibt dieses wohl bei mir liegen und wird ich weiter geworfen!