28.03.2014 Aufrufe

PC Games Hardware Sonderheft: Raspberry Pi. Das erweiterte Handbuch Raspberry Pi. Das erweiterte Handbuch (Vorschau)

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

www.pcgameshardware.de • www.pcghx.de<br />

DAS HARDWARE-MAGAZIN FÜR <strong>PC</strong>-SPIELER<br />

<strong>PC</strong> <strong>Games</strong> <strong>Hardware</strong> Guide präsentiert:<br />

<strong>Raspberry</strong> <strong>Pi</strong><br />

<strong>Das</strong> <strong>erweiterte</strong> <strong>Handbuch</strong><br />

Der Mini-Computer für unter 40 Euro!<br />

Alles zur Hard- und Software des <strong>Raspberry</strong> <strong>Pi</strong>!<br />

Einstieg<br />

Projekte<br />

Coding<br />

Lernen<br />

Linux für Einsteiger<br />

mit Praxis-<br />

Beispielen<br />

So wählen Sie das<br />

ideale<br />

Betriebssystem<br />

Erste Schritte für<br />

eigene<br />

Programme<br />

Klassische und<br />

moderne<br />

Programmiersprachen<br />

Expertenwissen für Einsteiger und Fortgeschrittene<br />

<strong>PC</strong>GH GUIDE 02/14<br />

€ 9,99<br />

Österreich 11,- Euro<br />

Schweiz 17,- sfr<br />

Benelux 11,50 Euro


ALLE PREMIUM-BOOKAZINES IM ÜBERBLIcK<br />

NEU<br />

NEU<br />

NEU<br />

Bequem online bestellen:<br />

shop.computec.de/edition<br />

Jetzt auch für<br />

das iPad in der<br />

Computec-Kiosk-App


www.pcgameshardware.de • www.pcghx.de<br />

Intro<br />

DAS HARDWARE-MAGAZIN FÜR <strong>PC</strong>-SPIELER<br />

Guide <strong>Raspberry</strong> <strong>Pi</strong><br />

<strong>Das</strong> <strong>erweiterte</strong> <strong>Handbuch</strong><br />

Willkommen!<br />

Ein Unternehmen der MARQUARD MEDIA INTERNATIONAL AG<br />

Verleger Jürg Marquard<br />

Verlag<br />

Geschäftsführer<br />

Chefredakteur <strong>PC</strong>GH GUIDE (V.i.S.d.P.)<br />

Redakteur für besondere Aufgaben <strong>PC</strong>GH GUIDE<br />

Layoutkoordination <strong>PC</strong>GH GUIDE<br />

Übersetzung, Layout, Lektorat<br />

Chefredakteur <strong>PC</strong> <strong>Games</strong> <strong>Hardware</strong><br />

Product Manager<br />

Computec Media GmbH<br />

Dr.-Mack-Straße 83, 90762 Fürth<br />

Telefon: +49 911 2872-100<br />

Telefax: +49 911 2872-200<br />

redaktion@pcgameshardware.de<br />

www.pcgameshardware.de | www.pcghx.de<br />

Rainer Rosenbusch, Ingo Griebl, Hans Ippisch<br />

Christian Müller, verantwortlich für den redaktionellen Inhalt,<br />

Adresse siehe Verlagsanschrift<br />

Lars Craemer<br />

Albert Kraus<br />

MDV Textdienste, Harald Wagner, Christiane Scholz, Ina Hulm<br />

Thilo Bayer (tb)<br />

Daniel Waadt (dw)<br />

Vertrieb, Abonnement<br />

Marketing<br />

Produktion<br />

www.pcgameshardware.de<br />

Werner Spachmüller (Ltg.),<br />

Jeanette Haag<br />

Martin Closmann (Ltg.), Jörg Gleichmar<br />

Chefredakteur Online Thilo Bayer<br />

Redaktion Andreas Link, Marco Albert, Frank Stöwer,<br />

Carsten Spille, Marc Sauter,Raffael Vötter,<br />

Stephan Wilke<br />

Entwicklung Markus Wollny (Ltg.), René Giering, Aykut Arik, Tobias Hartlehnert<br />

Webdesign Tony von Biedenfeld, Emanuel Popa<br />

Anzeigen<br />

CMS Media Services GmbH, Dr.-Mack-Straße 83, 90762 Fürth<br />

Anzeigenleiter<br />

Gunnar Obermeier, verantwortlich für den Anzeigenteil. Adresse siehe Verlagsanschrift<br />

Anzeigenberatung Print:<br />

Bernhard Nusser: Tel.: 0911-2872-254; bernhard.nusser@computec.de<br />

René Behme: Tel.: 0911-2872-152; rene.behme@computec.de<br />

Alto Mair: Tel.: 0911-2872-144; alto.mair@computec.de<br />

Anne Müller: Tel.: 0911-2872-251; anne.mueller@computec.de<br />

Anzeigenberatung Online:<br />

freeXmedia GmbH<br />

Ein Unternehmen der freenet Group<br />

Deelbögenkamp 4c, 22297 Hamburg<br />

Tel.: +49 (0) 40-513 06-650<br />

Fax. +49 (0) 40-513 06-960<br />

Mail: werbung@freeXmedia.de<br />

www.freeXmedia.de<br />

Anzeigendisposition: anzeigen@computec.de<br />

Datenübertragung: via E-Mail: anzeigen@computec.de<br />

Es gelten die Mediadaten Nr. 27 vom 01.01.2014<br />

Abonnement – http://abo.pcgameshardware.de<br />

Die Abwicklung (Rechnungsstellung, Zahlungsabwicklung und Versand) erfolgt über unser Partner unternehmen DPV Direct GmbH:<br />

Post-Adresse: Leserservice Computec, 20080 Hamburg, Deutschland<br />

Ansprechpartner für Reklamationen ist Ihr Computec-Team unter:<br />

Deutschland: E-Mail: computec@dpv.de, Tel.: 0911-99399098, Fax: 01805-8618002*<br />

Support: Montag 07:00–20:00 Uhr, Dienstag–Freitag 07:30–20:00 Uhr, Samstag 09:00–14:00 Uhr<br />

* (14 Cent/Min. aus dem dt. Festnetz, max. 42 Cent/Min. aus dem dt. Mobilfunk)<br />

Österreich, Schweiz und weitere Länder: E-Mail: computec@dpv.de,<br />

Tel: +49-911-99399098, Fax: +49-1805-8618002<br />

Support: Montag 07:00–20:00 Uhr, Dienstag–Freitag 07:30–20:00 Uhr, Samstag 09:00–14:00 Uhr<br />

Abonnementpreis für 12 Ausgaben: <strong>PC</strong>GH Magazin € 47,88 (€ 51,60 Österreich, € 59,88 Ausland), <strong>PC</strong>GH DVD € 60,- (€ 67,20<br />

Österreich, € 72,- Ausland)<br />

Einzelversand/Nachbestellung<br />

Online: www.pcgh.de/go/shop, E-Mail: computec@dpv.de, Tel.: 0911-99399098 , Fax: 01805-8618002*<br />

* (0,14 €/Min. aus dem dt. Festnetz, max. 0,42 €/Min. aus dem dt. Mobilfunk)<br />

Druck: RR Donnelley Europe, ul. Obroncow Modlina 11, 30-733 Krakau, Polen<br />

COMPUTEC MEDIA ist nicht verantwortlich für die inhaltliche Richtigkeit der Anzeigen und übernimmt keinerlei Verantwortung für in<br />

Anzeigen dargestellte Produkte und Dienstleistungen. Die Veröffentlichung von Anzeigen setzt nicht die Billigung der angebotenen<br />

Produkte und Service-Leistungen durch COMPUTEC MEDIA voraus. Sollten Sie Beschwerden zu einem unserer Anzeigenkunden, seinen<br />

Produkten oder Dienstleistungen haben, möchten wir Sie bitten, uns dies schriftlich mitzuteilen. Schreiben Sie unter Angabe des<br />

Magazins, in dem die Anzeige erschienen ist, inkl. der Ausgabe und der Seitennummer an: CMS MEDIA SERVICES GmbH, Annett<br />

Heinze, Anschrift siehe oben.<br />

Einsendungen, Manuskripte und Programme:<br />

Mit der Einsendung von Manuskripten jeder Art gibt der Verfasser die Zustimmung zur Veröffentlichung in den von der Verlagsgruppe<br />

herausgegebenen Publikationen. Urheberrecht: Alle in <strong>PC</strong> <strong>Games</strong> <strong>Hardware</strong> veröffentlichten Beiträge bzw. Datenträger sind<br />

urheberrechtlich geschützt. Jegliche Reproduktion oder Nutzung bedarf der vorherigen, ausdrücklichen und schriftlichen<br />

Genehmigung des Verlags.<br />

Lizenz<br />

Artikel in dieser Ausgabe sind übersetzt oder reproduziert aus „<strong>Raspberry</strong> <strong>Pi</strong>: Beyond the Manual“ und<br />

unterliegen dem Copyright von Future plc, UK 2012. Inhalte wurden als Lizenz erworben. Alle Rechte vorbehalten.<br />

„Bookazines and Masterclass series“ ist ein eingetragenes Warenzeichen von Future Publishing Limited. Weitere<br />

Informationen über diese und andere Zeitschriften der Future plc Gruppe:<br />

http://www.futureplc.com<br />

Licence<br />

Articles in this issue are translated or reproduced from „<strong>Raspberry</strong> <strong>Pi</strong>: The Essential Manual“ and are the<br />

copyright of or licensed to Future Publishing Limited, a Future plc group company, UK 2012. Used under licence.<br />

All rights reserved. „Bookazines and Masterclass series“ is the trademark of or licensed to Future Publishing<br />

Limited, a Future plc group company. Used under licence.<br />

http://www.futureplc.com<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> ist ein kompletter Mini-Computer und<br />

darüber hinaus auch noch sehr günstig. Wer sich nicht<br />

von dem Betriebssystem auf Linux-Basis und der<br />

scheinbaren Basteloptik abschrecken lässt, wird mit<br />

dem <strong>Raspberry</strong> <strong>Pi</strong> viel Spaß haben. Der <strong>Raspberry</strong> <strong>Pi</strong> ist nämlich<br />

nicht nur ein mächtiges Werkzeug für versierte Schrauber,<br />

sondern dank der einfachen Struktur des Betriebssystems und<br />

den unzähligen Foren mit projektbezogenen Hilfestellungen auch<br />

für Anfänger perfekt geeignet. Wer also ein neues und zudem<br />

auch günstiges Hobby sucht, kann mit dem <strong>Raspberry</strong> <strong>Pi</strong> für sich<br />

eine völlig neue Technik-Welt entdecken.<br />

In unserem <strong>Handbuch</strong> gehen wir auf die Geschichte des<br />

<strong>Raspberry</strong> <strong>Pi</strong> ein und erklären Ihnen Schritt für Schritt, wie Sie den<br />

kleinen Computer an Ihre Bedürfnisse anpassen. Auch<br />

Programmierer (und solche die es werden wollen) finden bei uns<br />

praktische Tipps und viele Ansätze, auf deren Basis Sie zukünftig<br />

sogar eigene Projekte entwickeln können.<br />

Wussten Sie übrigens, dass der <strong>Raspberry</strong> <strong>Pi</strong> bereits über die<br />

Weltmeere schippert, sogar auf den Spuren von Captain Kirk<br />

wandert und den Weltall erobert hat? Dies sind nur zwei Beispiele,<br />

für die praktisch unbegrenzten Einsatzmöglichkeiten des<br />

Rechenzwergs.<br />

MARQUARD MEDIA INTERNATIONAL AG<br />

Deutschsprachige Titel: SFT, WIDESCREEN, <strong>PC</strong> GAMES, <strong>PC</strong> GAMES MMORE, <strong>PC</strong> GAMES HARDWARE, N-ZONE,<br />

GAMES & MORE, BUFFED, GAMES AKTUELL, PLAY 3, PLAYBLU, XBG GAMES<br />

Internationale Zeitschriften: Ungarn: JOY, SHAPE, ÉVA, IN STYLE, PLAYBOY, CKM, MEN’S HEALTH<br />

Polen: COSMOPOLITAN, JOY, SHAPE, HOT, PLAYBOY, CKM, VOYAGE, HARPER’S BAZAAR<br />

3


Inhalt<br />

Grundlagen<br />

Was ist Linux?.......................................................................................8<br />

E wie Eben.........................................................................................................16<br />

Ursprünge: Wie der <strong>Pi</strong> entstand........................................................20<br />

Richtig verbinden: Peripherie...............................................................22<br />

Fehlerbehebung: Booten........................................................................26<br />

Befehlszeile: Erste Schritte...................................................................28<br />

<strong>Das</strong> Dateisystem: Speichergeräte..................................................32<br />

Pakete: Software sicher im Griff......................................................34<br />

Add-ons für den <strong>Raspberry</strong> <strong>Pi</strong>.............................................................36<br />

Projekte<br />

Betriebssysteme für den <strong>Raspberry</strong> <strong>Pi</strong>.......................................42<br />

Betriebssystem: Raspbian....................................................................48<br />

Zünde den <strong>Raspberry</strong>-Booster...........................................................54<br />

Arch Linux...........................................................................................................62<br />

System: Eigene Distribution.................................................................66<br />

XBMC enthüllt.................................................................................................70<br />

Auto-Backups per Bash-Skript............................................................74<br />

dnsmasq: DNS servers...........................................................................78<br />

Syslog: Loggen per E-Mail.....................................................................80<br />

Desktop: Eigene Schreibtische.........................................................82<br />

4


Inhalt<br />

Coding<br />

Generation CODE........................................................................................88<br />

<strong>Raspberry</strong> Jams...........................................................................................92<br />

Geany: Editor de luxe...............................................................................96<br />

Code-Konzepte: Datentypen...........................................................100<br />

Designkonzepte: Komplexe Typen.............................................102<br />

Designkonzepte: Abstraktion.........................................................104<br />

Designkonzepte: Dateien und Module...................................106<br />

Python: So fangen Sie an.................................................................108<br />

Designkonzepte: Eine IDE nutzen...............................................112<br />

Designkonzepte: Ein Unix-Tool.......................................................114<br />

Designkonzepte: Ein echter Klon................................................116<br />

Designkonzepte: Klassenobjekte.............................................. 118<br />

Designkonzepte: Module...................................................................120<br />

Designkonzepte: Massenspeicher.............................................122<br />

Designkonzepte: Datenorganisation........................................124<br />

GUI-Code: Mit Clutter hantieren...................................................126<br />

Python: Clutter-Animationen...........................................................130<br />

Programmiersprachen<br />

Andere Sprachen...........................................................................................136<br />

Begeisterung für OpenEuphoria...................................................138<br />

Ein kurzer Lehrgang in Go.................................................................142<br />

Listig mit Lisp..............................................................................................146<br />

C++: So geht’s...........................................................................................150<br />

Fortan Fortran.............................................................................................154<br />

Lua: Erste Schritte..................................................................................158<br />

5


Grundlagen<br />

6


Grundlagen<br />

Grundlagen<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> setzt an sich eine gewisse<br />

Kenntnis von Linux voraus, die Sie zum Teil<br />

sicherlich nicht vorweisen können. Lesen Sie<br />

sich daher in die Grundlagen rund um den Mini-<br />

Computer ein und machen Sie sich mit dem<br />

Betriebssystem vertraut.<br />

Was ist Linux?....................................................................................................8<br />

E wie Eben.........................................................................................................16<br />

Ursprünge: Wie der <strong>Pi</strong> entstand........................................................20<br />

Richtig verbinden: Peripherie...............................................................22<br />

Fehlerbehebung: Booten........................................................................26<br />

Befehlszeile: Erste Schritte...................................................................28<br />

<strong>Das</strong> Dateisystem: Speichergeräte..................................................32<br />

Pakete: Software sicher im Griff......................................................34<br />

Add-ons für den <strong>Raspberry</strong> <strong>Pi</strong>.............................................................36<br />

7


Grundlagen<br />

Was ist<br />

Linux?<br />

Hier bekommen Sie eine erste Einführung<br />

in das – wie seine Fans sagen –<br />

beste Betriebssystem der Welt.<br />

Was ist eigentlich Linux? Auf diese Frage bekommt man<br />

unterschiedliche Antworten, je nachdem, wem man<br />

sie stellt: Der Purist sagt, dass der Begriff einzig für<br />

den Kernel steht, für den GNU-Verfechter ist Linux nur ein Teil von<br />

GNU/Linux, und der Einsteiger denkt womöglich, es wäre lediglich<br />

ein anderer Name für Ubuntu.<br />

Je nachdem, aus welchem Blickwinkel man die Sache betrachtet,<br />

trifft all das mehr oder minder zu. Ganz streng genommen<br />

bezieht sich der Begriff Linux nur auf den Kernel<br />

des Betriebssystems, während GNU/Linux das gesamte Betriebssystem<br />

bezeichnet, das den Linux-Kernel zusammen<br />

mit den GNU-Werkzeugen enthält – das Eine wäre nutzlos<br />

ohne das Andere (oder eine der Alternativen).<br />

Fügt man dem Betriebssystem noch eine Sammlung<br />

von Anwendungsprogrammen hinzu sowie ein paar<br />

Tools, um das Ganze zu verwalten, so hat man eine sogenannte<br />

Distribution. Ubuntu ist beispielsweise eine<br />

Distribution, ebenso wie das speziell für den <strong>Raspberry</strong><br />

<strong>Pi</strong> entwickelte Raspbian. Aber beide Programmpakete<br />

sind ebenfalls immer noch Linux.<br />

Die Einzelteile, aus denen das Betriebssystem zusammengesetzt<br />

ist, sind sehr zahlreich, aber sie passen doch<br />

alle zusammen und sind aufeinander abgestimmt. Auf den<br />

folgenden Seiten erklären wir Ihnen die Funktion der wichtigsten<br />

dieser Einzelteile. Die Informationen sind sowohl für<br />

alle Desktop-Varianten von Linux als auch für die <strong>Raspberry</strong>-<strong>Pi</strong>-Distributionen<br />

gültig.<br />

Betriebssystem und Distribution<br />

Man kann ein Betriebssystem als<br />

diejenige Software definieren, die<br />

es Anwendungen ermöglicht, auf<br />

einer bestimmten <strong>Hardware</strong> zu<br />

laufen. Betriebssysteme bestehen<br />

aus mehreren überlappenden<br />

Schichten. In der untersten Ebene<br />

haben wir den Kernel, der mithilfe<br />

von Treibern direkt mit der <strong>Hardware</strong><br />

interagiert. Andere Schichten<br />

setzen auf dieser Basis auf – zum<br />

Beispiel solche, die Eingabegeräte,<br />

Audio- und Video-Ausgabe oder<br />

Netzwerkverbindungen verwalten.<br />

Sie brauchen nicht zwangsläufig<br />

etwas über diese Dinge zu wissen.<br />

Da Sie jedoch gerade dieses <strong>Handbuch</strong><br />

lesen, stehen die Chancen<br />

gut, dass Sie sich auch für die Vorgänge<br />

„da unten“ interessieren.<br />

Darum versuchen wir, Ihnen einen<br />

kleinen Überblick zu geben.<br />

Eine Linux-Distribution ist<br />

genau das, was der englische<br />

Begriff „to distribute“ bedeutet:<br />

das Verteilen eines linuxbasierten<br />

Betriebssystems zusammen mit<br />

weiterer Software. Anfangs handelte<br />

es sich lediglich um die<br />

Dateien, die das Betriebssystem<br />

benötigt, zusammen mit einer<br />

Methode, das Ganze auf einem<br />

Computer zu installieren. Mit der<br />

Zeit wurden die Distributionen um<br />

Paketmanager, Update-Tools,<br />

Oberflächen zur Konfiguration<br />

und etliche andere Annehmlichkeiten<br />

erweitert. Unter der Haube<br />

sind jedoch alle Distributionen<br />

nach wie vor Linux.<br />

8


Grundlagen<br />

Der Kernel<br />

<strong>Das</strong> Kontrollzentrum des Linux-Betriebssystems.<br />

Der Kernel ist das Herz des Systems. Er kommuniziert im<br />

Namen der gesamten auf dem Computer installierten<br />

Software mit dem Prozessor, dem Speicher und allen<br />

anderen Geräten. In dieser Rolle ist der Kernel die am tiefsten<br />

gelegene und gleichzeitig wichtigste Software-Schicht. Falls der<br />

Kernel ein Problem hat, überträgt sich dieses auf die gesamte<br />

Software auf dem Rechner.<br />

Der Linux-Kernel ist monolithisch aufgebaut. <strong>Das</strong> bedeutet,<br />

dass alle Kerndienste des Betriebssystems im Kernel<br />

laufen. Die Alternative ist ein Micro-Kernel, der einen Großteil<br />

der Arbeit auf externe Dienste auslagert und selber kaum<br />

mehr macht, als die Aufgaben zu koordinieren.<br />

Während ein reinrassiger monolithischer Kernel in den<br />

Anfangstagen der Betriebssysteme gut funktionierte, ist das<br />

Prinzip in Reinform heute nicht mehr praktikabel: Aufgrund<br />

der riesigen <strong>Hardware</strong>vielfalt wäre ein Kernel, der alle denkbaren<br />

Kombinationen komplett abdeckt, viel zu groß. Deswegen<br />

ist der Linux-Kernel von heute modular aufgebaut. Die<br />

Kernfunktionen befinden sich in der Kernel-Datei (zu finden<br />

in /boot als vmlinuz-version), während sich die optionalen<br />

Treiber als separate Module im Verzeichnis /lib/modules<br />

befinden.<br />

Ziehen wir als Beispiel für den Speicherbedarf die Distribution<br />

Ubuntu 12.10 heran: Während deren 64-Bit-Kernel nur<br />

5 MB groß ist, belegen die zusätzlichen 3.700 Moduldateien<br />

100 MB. Da auf jedem Computer nur ein Bruchteil dieser<br />

Dateien benötigt wird, wäre es unsinnig, sie alle zusammen<br />

mit dem Kernel zu laden. Stattdessen ermittelt der Kernel,<br />

welche Module er benötigt. Diese werden geladen<br />

und bilden daraufhin im Hauptspeicher einen Teil<br />

des Kernels. Im Betrieb ist der Kernel somit noch<br />

immer monolithisch, auch wenn er über Tausende Dateien<br />

verteilt ist. So ist es dem System möglich, auf eine sich<br />

verändernde <strong>Hardware</strong> zu reagieren. Wenn Sie beispielsweise<br />

einen USB-Stick einstöpseln, lädt das usb-storage-Modul<br />

zusammen mit dem Dateisystem-Modul, das Sie benötigen,<br />

Beim Eigenbau eines Kernels steht Ihnen eine überwältigende Anzahl von<br />

Optionen zur Verfügung, wobei die meisten mit der <strong>Hardware</strong>unterstützung zu tun<br />

haben. Zum Glück nehmen uns die Distributoren diese Arbeit ab, wenn wir möchten.<br />

um den Stick mounten zu können. Wenn Sie einen 3G-Dongle<br />

einstecken, werden die Treiber für das serielle Modem<br />

geladen. <strong>Das</strong> ist der Grund, warum Sie so selten neue Treiber<br />

installieren müssen, wenn Sie neue <strong>Hardware</strong> mit dem Computer<br />

verbinden: Die meisten Treiber sind bereits vorhanden<br />

und warten nur darauf, dass Sie ein passendes Gerät<br />

an schließen. Computer, die auf einer spezifischen, sich nicht<br />

verändernden <strong>Hardware</strong> laufen – wie etwa Server – nutzen<br />

meist einen Kernel, der mit allen nötigen Treibern kompiliert<br />

wurde. So kann das Nachladen von Modulen deaktiviert werden,<br />

was die Sicherheit ein wenig erhöht.<br />

Falls Sie Ihren eigenen Kernel kompilieren, gilt die Faustregel,<br />

dass Sie alle Treiber für jene <strong>Hardware</strong> integrieren sollten,<br />

die ständig im Gebrauch sein wird, wie etwa für Netzwerkschnittstellen<br />

und Dateisysteme. Für alles andere greifen<br />

Sie besser auf Module zurück.<br />

Obwohl Linux eine extrem gute <strong>Hardware</strong>unterstützung<br />

bietet, fehlt mitunter ein passendes Kernel-Modul für ein<br />

Gerät, insbesondere wenn der Code sehr neu ist oder aus<br />

lizenzrechtlichen Gründen. Die darum fehlenden Treiber werden<br />

meist als Drittanbieter-Module (bei Ubuntu als „restricted<br />

drivers“) bezeichnet. Falls diese von Ihrer Distribution<br />

unterstützt werden, lassen sie sich oft per Paketmanager installieren.<br />

Andernfalls müssen sie ausgehend vom Quellcode<br />

kompiliert werden, und zwar jedes Mal, wenn Sie Ihren Kernel<br />

aktualisieren, denn die Treiber sind hierbei an den Kernel<br />

gebunden, für den sie kompiliert wurden. Um den Aufwand<br />

zu verringern, gibt es automatisierte Lösungen wie DKMS<br />

(Dynamic Kernel Module Support), das bei einer Neuinstallation<br />

des Kernels alle Drittanbieter-Module neu kompiliert.<br />

Damit wird das Aktualisieren des Kernels fast genauso einfach<br />

wie ein Update eines Anwendungsprogramms.<br />

Kernel-Space und User-Space<br />

Im Zusammenhang mit Kernels werden häufig die Begriffe<br />

„Kernel-Space“ und „User-Space“ verwendet.<br />

Beim Kernel-Space handelt es sich<br />

um einen für den Kernel reservierten<br />

Speicherbereich. Auf diesen haben<br />

nur der Kernel selbst sowie seine<br />

Module Zugriff, nicht aber Anwendungsprogramme.<br />

Damit soll verhindert<br />

werden, dass Amok laufende<br />

Programme die Arbeit des Kernels<br />

stören.<br />

Dem gegenüber steht der User-<br />

Space, der von jedem Programm<br />

angesprochen werden kann, sofern es<br />

die entsprechenden Berechtigungen<br />

dazu besitzt. Diese Aufteilung trägt<br />

viel zur Stabilität von Linux bei, da<br />

dadurch kein Programm die Arbeit<br />

des Kernels direkt beeinflussen und<br />

dadurch Schaden anrichten kann,<br />

selbst wenn es mit Root-Privilegien<br />

ausgestattet ist.<br />

9


Grundlagen<br />

Die Startreihenfolge<br />

<strong>Das</strong> mysteriöse <strong>Pi</strong>epsen und Flackern beim Bootvorgang.<br />

Wenn Sie den<br />

Splash-Screen<br />

wie im Text beschrieben<br />

deaktivieren,<br />

können<br />

Sie die Abläufe<br />

beim Booten des<br />

Computers in<br />

Gänze zusammen<br />

mit dem<br />

Status der startenden<br />

Dienste<br />

verfolgen.<br />

Beim Systemstart springen die meisten Distributionen<br />

direkt zu einem Splash-Screen, sodass nicht zu sehen ist,<br />

was im Hintergrund abläuft. Dabei passiert schon eine<br />

ganze Menge, bevor der Splash-Screen überhaupt auftaucht, und<br />

dann im Hintergrund des Splash-Screens.<br />

Zuerst startet das BIOS in der <strong>Hardware</strong> des Motherboards.<br />

Es sieht sich nach einem bootbaren Gerät um, von<br />

dem es Code laden kann.<br />

Dieser befindet sich im Falle<br />

eines Festplattenlaufwerks<br />

mit klassischem DOS-Partitionssystem<br />

im nur 512 Byte<br />

großen Master Boot Record<br />

(MBR). Davon sind 64 Byte<br />

zur Speicherung der Partitionstabelle vorgesehen (diese kleine<br />

Datenmenge ist der Grund, warum nur maximal vier primäre<br />

Partitionen möglich sind). Die restlichen 448 Byte beinhalten<br />

den Code für den Bootloader, im Falle von Linux meist<br />

GRUB. 448 Byte erlauben natürlich keinen überbordenden<br />

Funktionsumfang, weshalb dieser Code nichts weiter tut, als<br />

den Bootloader von irgendwo anders auf der Festplatte zu<br />

laden. Von wo genau, wird festgelegt, wenn der MBR auf die<br />

Festplatte geschrieben wird.<br />

Der Bootloader liest anschließend seine Konfigurationsdatei<br />

ein, im Falle von GRUB /boot/grub2/grub.cfg. Darin ist<br />

eine Liste von Boot-Optionen gespeichert. Diese wird je nach<br />

Konfiguration entweder dem Nutzer angezeigt, oder es wird<br />

„Falls Sie sehen möchten,<br />

was passiert, können Sie den<br />

Splash-Screen deaktivieren.“<br />

sofort der als Standard markierte Eintrag gestartet. Zu diesem<br />

Zeitpunkt ist Linux noch in keiner Weise in den Betrieb<br />

des Rechners involviert, bis jetzt wurde nur Code des Bootloaders<br />

ausgeführt. Der genannten Konfigurationsdatei entnimmt<br />

der Bootloader nun die Informationen zu den Speicherorten<br />

des Linux-Kernels und gegebenenfalls der<br />

initramfs-Archivdatei (siehe unten) sowie bestimmte Einstellungen<br />

wie etwa die Root-<br />

Partition. Außerdem informiert<br />

er sich, ob das Ganze<br />

hinter einem Splash-Screen<br />

versteckt werden soll. Falls<br />

Sie sehen möchten, was von<br />

jetzt an passiert, können Sie<br />

den Splash-Screen bei den meisten Distributionen deaktivieren.<br />

Drücken Sie hierzu die Taste E, um im GRUB-Menüeintrag<br />

alle Quiet- und Splash-Parameter zu entfernen. Ein<br />

Druck auf die Taste F10 führt zur Fortsetzung des Bootvorgangs.<br />

<strong>Das</strong> initramfs-Archiv<br />

Die meisten Distributionen benutzen eine initramfs-Datei.<br />

Der Hauptgrund dafür ist, dass bestimmte Treiber zusammen<br />

mit dem Kernel geladen werden müssen (etwa SATA-<br />

Controller oder Dateisystem-Code). Würde man alle denkbaren<br />

Optionen direkt in den Kernel integrieren, wäre dieser für<br />

eine gewöhnliche Distribution unhandlich groß. Deshalb ist<br />

alles in Form von Modulen hinterlegt, und diejenigen, die zum<br />

Booten benötigt werden, sind in der initramfs integriert. Dies<br />

ist eine Art von RAM-Disk, die vom Bootloader (mithilfe der<br />

BIOS-Funktionen zum Lesen der Festplatte) geladen wird<br />

und alle Dateien beinhaltet, die zum Mounten der Root-Partition<br />

notwendig sind. Die Geräteerkennung des Kernels entscheidet<br />

dabei, welche Dateien gebraucht werden. Anschließend<br />

wird die Kontrolle an die eigentliche Festplatte über -<br />

geben. Die initramfs lädt auch potentielle Splash-Screens,<br />

sodass sie am Beginn des Startvorganges richtig dargestellt<br />

werden.<br />

Sobald die Root-Partition gemountet ist, beginnt erst die<br />

<strong>Das</strong> GNU in GNU/Linux<br />

<strong>Das</strong> GNU-Projekt ist knapp ein<br />

Jahrzehnt älter als Linux. Im<br />

Rahmen dieses Projekts wurden<br />

die meisten der grundlegenden<br />

Werkzeuge und Programme<br />

geschaffen, die für einen Computer<br />

der frühen 1980er Jahre<br />

benötigt wurden: Compiler, Text-<br />

Editoren, Kommandos zum Bearbeiten<br />

von Dateien und Verzeichnissen<br />

und vieles mehr. Doch<br />

leider fehlte dem Projekt ein<br />

benutzbarer Kernel. Nachdem<br />

Linus Torvalds 1991 an seinem<br />

kleinen Projekt herumzubasteln<br />

begann, hatte er bald einen<br />

Kernel, allerdings fehlten ihm die<br />

Werkzeuge, um diesen laufen zu<br />

lassen. GNU und Linux wurden<br />

schließlich zusammengefügt,<br />

und GNU/Linux war geboren<br />

– ein Betriebssystem, das den<br />

Linux-Kernel und die GNU-<br />

Werkzeugsammlung vereint.<br />

Es sind nicht nur die Programme<br />

in /bin und /usr/bin,<br />

die von GNU stammen – auch<br />

glibc, die C-Kernbibliothek in<br />

Linux, rührt von GNU her. Jedes<br />

Mal, wenn Sie etwas an Ihrem<br />

Computer machen, immer wenn<br />

Sie ein Icon anklicken oder ein<br />

Kommando eintippen, hilft GNU-<br />

Software an irgendeiner Stelle<br />

der Befehlskette. Kein Wunder<br />

also, dass es die GNU-Verfechter<br />

immer auf die Palme treibt, wenn<br />

das Betriebssystem nur Linux<br />

und nicht GNU/Linux genannt<br />

wird. Aus Gründen der Bequemlichkeit<br />

und Lesefreundlichkeit<br />

wird dies dennoch häufig getan,<br />

auch in diesem <strong>Handbuch</strong> (wofür<br />

wir die GNU/Linux-Verfechter<br />

um Entschuldigung bitten).<br />

Richard Stallman hat das GNU-<br />

Projekt 1983 ins Leben gerufen.<br />

10


Grundlagen<br />

richtige Startsequenz, entweder direkt oder über die initramfs.<br />

Im Normalfall wird /sbin/init ausgeführt, was wiederum<br />

die in /etc/inittab festgelegten Prozesse startet. Auch<br />

alle Startmeldungen der Dienste werden von Ersterem kontrolliert.<br />

Diese Ausgaben ermöglichen es Ihnen auch zu erkennen,<br />

wo der Startvorgang hängt, falls er einmal scheitern<br />

oder unverhältnismäßig viel Zeit in Anspruch nehmen sollte.<br />

Alternativen<br />

Im Laufe der Zeit sind die Komponenten stetig modernisiert<br />

worden. Auf aktueller <strong>Hardware</strong> wurde das BIOS durch UEFI<br />

ersetzt. Sobald aber der Bootloader installiert wurde, werden<br />

Sie keine Unterschiede zwischen<br />

beiden Systemen bemerken. Es gibt auch Bestrebungen, das<br />

klassische SysVinit-System zu ersetzen, woran schon lange<br />

gearbeitet wird. So hat Ubuntu Upstart eingeführt, während<br />

Fedora und Red Hat zu systemd greifen. Der größte Unterschied<br />

ist, dass SysVinit sequenziell vorgeht: Ein Dienst muss<br />

starten, bevor der nächste auf der Liste angestoßen wird. Ist<br />

ein langsam startender Dienst dabei, hält dieser alle anderen<br />

auf. Upstart und systemd starten die Dienste hingegen parallel<br />

und vermeiden so diesen Flaschenhals. Natürlich gibt es<br />

Leute, die behaupten, dass Linux so stabil sei, dass die Startzeiten<br />

eh nicht ins Gewicht fielen – wenn Sie den Ruhezustand<br />

statt Herunterfahren nutzen, wird ein Reboot in der Tat<br />

zu einem seltenen Ereignis.<br />

Bibliotheken<br />

Warum Programme sich Funktionen teilen.<br />

Mithilfe sogenannter Bibliotheken wird bei Linux Code<br />

zwischen mehreren Programmen geteilt. Falls beispielsweise<br />

ein Programm namens foo bestimmte<br />

Funktionen beinhaltet, die auch anderswo von Nutzen sein könnten,<br />

werden diese in libfoo abgelegt. Wenn nun ein anderes Programm<br />

– hier bar genannt – diese Funktionen nutzen möchte,<br />

braucht es nur auf libfoo zu verweisen, anstatt das Rad neu zu<br />

erfinden.<br />

Im Idealfall befindet sich ein bestimmter Programmcode<br />

also nur einmal auf Ihrem Rechner, und falls in dem Code ein<br />

Fehler auftritt, genügt es, diesen in einer Bibliothek enthaltenen<br />

Code-Abschnitt auszubessern, um den Fehler in allen darauf<br />

verweisenden Programmen<br />

zu korrigieren.<br />

Dies führt auch das Konzept<br />

der Abhängigkeiten ein: In unserem<br />

Fall sind sowohl foo als auch<br />

bar von libfoo abhängig und<br />

wären ohne diese Bibliothek<br />

nutzlos. Genau diese Abhängigkeiten sind auch für das Phänomen<br />

der „Hölle der Abhängigkeiten“ verantwortlich, wo die<br />

Installation eines Programmes durch nicht erfüllte Abhängigkeiten<br />

verhindert wird und beim Nachin stallieren dieser Abhängigkeiten<br />

sich sofort neue auftun. Heute ist das aber<br />

meist nur noch eine unangenehme Erinnerung, weil Distributions-Repositorys<br />

immer umfangreicher und Paketmanager<br />

immer zuverlässiger werden.<br />

Wenn Sie mit dem Paketmanager Ihrer Distribution arbeiten,<br />

wird sich dieser um alle Abhängigkeiten kümmern, ohne<br />

dass Sie einen Gedanken daran verschwenden müssen.<br />

Paketmanager<br />

„Mithilfe von Bibliotheken<br />

wird Code zwischen<br />

Programmen geteilt.“<br />

Versuchen Sie mal, irgendwas.deb oder irgendwas.<br />

rpm von www.irgendwas.com zu installieren, und Sie werden<br />

früher oder später feststellen, warum es besser ist, so<br />

etwas in Zukunft dem Paketmanager zu überlassen. Eine<br />

mögliche Lösung für das Ganze ist es, die Programme statisch<br />

zu kompilieren. <strong>Das</strong> bedeutet, dass beim Kompilieren<br />

nicht auf den Code in libfoo verwiesen und während der Laufzeit<br />

des abhängigen Programmes dynamisch darauf zugegriffen<br />

wird, sondern dass der Compiler den Code von libfoo direkt<br />

in die abhängigen Programme integriert. Im Falle von foo<br />

und bar wären nach einem statischen Kompilierungsvorgang<br />

zwei von libfoo unabhängige Programme das Ergebnis – mit<br />

dem Nachteil, dass wenn in libfoo<br />

ein Fehler gefunden würde, beide<br />

Programme neu kompiliert und für<br />

Ihre Distribution neu bereitgestellt<br />

werden müssten. Generell ist es die<br />

bevorzugte Methode, dynamisch<br />

auf eine Bibliothek zu verlinken, sofern<br />

nicht für ein Embedded-System programmiert wird.<br />

Doch es gibt eine Situation, wo statisch verlinkte Programme<br />

nützlich sind: in der initramfs, die beim Systemstart<br />

geladen wird. So vermeiden Sie es, Bibliotheken in<br />

das RAM-Disk-Abbild integrieren müssen. Falls es Sie interessiert,<br />

welche Programme welche Abhängigkeiten aufweisen,<br />

erfahren sie das mit dem ldd-Kommando.<br />

ldd /usr/bin/irgendeinprogramm<br />

zeigt alle von einem Programm benötigten Bibliotheken<br />

sowie auch deren Abhängigkeiten an. Fast immer endet die<br />

Aufzählung bei libc, dem Großvater aller Linux-Bibliotheken.<br />

Dank der Flexibilität von Linux-Distributionen können die<br />

meisten Elemente ausgetauscht werden, darunter Standardanwendungen,<br />

Desktops und sogar der Kernel. Die einzige<br />

Komponente, die nicht ausgetauscht werden kann, ist der<br />

Paketmanager. Sollten Sie also einen anderen Paketmanager<br />

ausprobieren wollen, müssen Sie die komplette Distribution<br />

auswechseln. Wenn Sie etwa Yast von SUSE mit Synaptic von<br />

Debian vergleichen, werden Sie feststellen, wie fundamental<br />

sich der Paketmanager auf die Benutzererfahrung einer<br />

Distri bution auswirken kann.<br />

Bibliotheken machen ein System effizienter, indem sie Code anderen<br />

Anwendungen zugänglich machen. Hier sehen Sie nur einige<br />

von den Bibliotheken, auf die das Brennprogramm K3b verlinkt.<br />

11


Grundlagen<br />

Grafik<br />

Darum sieht Ihr Linux-Betriebssystem so gut aus.<br />

Werkzeuge wie<br />

die Anzeigeeinstellungen<br />

von<br />

KDE helfen beim<br />

Einrichten von<br />

Multi-Monitor-<br />

Systemen. Für<br />

ein System mit<br />

einem einzigen<br />

Bildschirm muss<br />

X jedoch in der<br />

Regel nicht<br />

konfiguriert zu<br />

werden.<br />

<strong>Das</strong> X Window System ist die Standardbasis, um unter<br />

Linux eine grafische Benutzeroberfläche (GUI) zu ermöglichen.<br />

Während Gnome und KDE die Benutzerschnittstelle<br />

und die Optik zur Verfügung stellen, wird mithilfe von X die<br />

Kommunikation mit der <strong>Hardware</strong> realisiert.<br />

Etliche Jahre war das System eine Ansammlung kryptischer<br />

Einstellungen und benötigte eine ellenlange Konfigurationsdatei,<br />

in der <strong>Pi</strong>xeltaktraten und Synchronisationsfrequenzen<br />

festgelegt wurden. Heute braucht man hingegen<br />

kaum noch Konfigurationsdateien. Dies verdanken wir vor<br />

allem einer stark verbesserten <strong>Hardware</strong>erkennung, sodass<br />

Systeme mit einer einzelnen Grafikkarte und einem Monitor<br />

ohne Konfiguration sofort funktionieren. Für die 3D-Beschleunigung<br />

könnte ein zusätzlicher Treiber notwendig sein,<br />

beispielsweise wenn Sie eine Grafikkarte von Nvidia nutzen.<br />

Andernfalls starten Sie Ihren Rechner und können sofort mit<br />

der Arbeit loslegen. X nutzt eine Client/Server-Architektur. X<br />

selbst läuft als Server, der die Anzeige verwaltet, auf dem<br />

System, während Client-Programme mit dem X-Server kommunizieren<br />

und ihm mitteilen, was wo und wann dargestellt<br />

werden soll.<br />

<strong>Das</strong> mag ziemlich komplex erscheinen, aber das System<br />

nutzt lokale Sockets zur Kommunikation zwischen Client und<br />

Server, sodass es sich kaum negativ auf die Geschwindigkeit<br />

auswirkt. Ein klarer Vorteil dieser Methode ist es, dass der<br />

Client und der Server nicht auf demselben System laufen<br />

müssen. Sie können sich mit einem anderen Computer via<br />

SSH verbinden und – das Vorhandensein entsprechender<br />

Berechtigungen voraus gesetzt – am entfernten Computer<br />

ein Programm starten, dessen GUI auf dem lokalen Computer<br />

angezeigt wird. <strong>Das</strong> ist ein großer Unterschied zu VNC,<br />

weil nur ein Anwendungsfenster lokal angezeigt wird und dieses<br />

auch nur lokal auf diesem Computer existiert. Eine VNC-<br />

Verbindung spiegelt hingegen den gesamten Desktop auf<br />

beiden Computern.<br />

Wayland<br />

Einige Leute empfinden die Client/Server-Architektur als zu<br />

kompliziert, weshalb es Bestrebungen gibt, ein einfacheres<br />

Grafiksystem zu entwickeln. <strong>Das</strong> am meisten fortgeschrittene<br />

Projekt ist Wayland. Bei Wayland ist die Herangehensweise<br />

eine andere als bei X: Nicht nur der Client/Server-Aufbau<br />

fehlt, sondern Wayland überlässt auch das Rendern der<br />

Fenster und anderer Elemente auf dem Bildschirm Programmen<br />

wie OpenGL oder Cairo. <strong>Das</strong> macht Wayland wesentlich<br />

einfacher. X beinhaltet eine große Menge Code, der der Kompatibilität<br />

dient und von der X-Spezifikation zwar gefordert,<br />

aber letztlich nicht genutzt wird. Indem die Kontrolle an die<br />

Clients übergeben wird, kann Wayland viel schlanker, effizienter<br />

und zukunftssicherer sein. <strong>Das</strong> bedeutet auch, dass die<br />

grafische Software viel mehr Einfluss auf die Darstellung der<br />

GUI hat.<br />

Dämonenprozesse<br />

Wenn Sie den Splash-Screen aktueller Distributionen<br />

deaktivieren, werden Sie meistens<br />

einen Bildschirm voller Informationen darüber<br />

sehen, welche Dienste gerade starten.<br />

Dienste sind Programme, die im Hintergrund<br />

laufen. Einige von ihnen kümmern sich um das<br />

Netzwerk, andere managen die <strong>Hardware</strong>erkennung<br />

und -konfiguration. Bei den meisten<br />

Diensten handelt es sich jedoch um traditionelle<br />

Software, die anderen Programmen Funktionen<br />

zur Verfügung stellt. Diese Hintergrunddienste<br />

heißen Daemons oder Dämonen.<br />

Während einige davon auf fast allen Systemen<br />

gebraucht werden – wie etwa der syslog-Dämon,<br />

der die Log-Informationen des Systems in die<br />

entsprechenden Dateien schreibt –, werden<br />

viele Dienste auf dem jeweiligen System de<br />

facto gar nicht benötigt. So gibt es beispielswiese<br />

keinen Grund dafür, CUPS zu starten,<br />

wenn sie keinen Drucker verwenden. Ebenso<br />

dürfte der MySQL-Datenbankserver meist<br />

nicht gebraucht werden, genauso wenig wie der<br />

SSH-Dämon, wenn Ihr Computer der einzige<br />

in einem Netzwerk ist. Eine halbe Stunde des<br />

Herumexperimentierens könnte das Hochfahren<br />

des <strong>PC</strong>s also eine Sekunde schneller machen.<br />

Sie sollten allerdings nur solche Dienste<br />

deaktivieren, die Sie sicher niemals benötigen<br />

werden. Es ist sinnvoll, Dienste aktiviert und<br />

sie geduldig ihren Netzwerk-Port oder -Socket<br />

abhören zu lassen, da das die Arbeit der Client-<br />

Software etwas effizienter macht. So müssen<br />

Programme beispielsweise keinen eigenen Code<br />

besitzen, um Log-Dateien öffnen, beschreiben<br />

und wieder schließen zu können: Sie rufen einfach<br />

die syslog()-Funktion mit dem Log-Eintrag als<br />

Parameter auf, und der Dämon kümmert sich<br />

um den Rest. Syslog ist ein wichtiger Dienst –<br />

wenn irgendwas auf dem System schief läuft,<br />

ist das oft der erste Ort, um nachzusehen, da<br />

Die Startzeit des Computers kann durch<br />

das Ausschalten unnötiger Prozesse verkürzt<br />

werden.<br />

die meisten Programme ihre Fehlerinformationen<br />

zum System-Log senden (normalerweise<br />

unter /var/log/messages zu finden).<br />

Warum aber werden Hintergrunddienste<br />

als Dämonen bezeichnet? In der griechischen<br />

Mythologie waren Dämonen Geschöpfe, die sich<br />

um Belange kümmerten, mit denen man Götter<br />

nicht behelligt. Vielleicht ist das die Antwort.<br />

12


Grundlagen<br />

Netzwerke<br />

Wie Ihr Computer mit anderen spricht.<br />

Eine der Kernfähigkeiten von Linux ist die Vernetzung.<br />

Sogar auf einem Einzel-Computer ohne Verbindung zu<br />

einem lokalen Netzwerk werden die Netzwerkfähigkeiten<br />

verwendet. Viele Dienste nutzen ein Client/Server-Modell, bei dem<br />

der Server im Hintergrund läuft und auf die Anweisungen anderer<br />

Programme wartet.<br />

Sogar etwas so Grundlegendes wie der System-Logger<br />

läuft als Netzwerkdienst und ermöglicht es dadurch anderen<br />

Programmen, Log-Dateien zu schreiben. <strong>Das</strong> X-Grafiksystem<br />

ist ebenfalls so aufgebaut: Der X-Server arbeitet im Hintergrund,<br />

während ihm die Programme mitteilen, was er anzeigen<br />

soll. Darum ist es so einfach, X-Programme auf einem<br />

entfernten <strong>PC</strong> darzustellen – soweit es das System angeht,<br />

gibt es keinen wirklichen Unterschied zwischen diesem Fall<br />

und einem Fenster, das nur lokal angezeigt werden soll.<br />

Wenn sie ifconfig ausführen, wird zumindest eine Netzwerkschnittstelle<br />

mit dem Namen lo angezeigt. Diese besitzt die<br />

Adresse 127.0.0.1 – sie wird vom Computer verwendet, um<br />

mit sich selbst zu kommunizieren. Fast alle anderen Vorgänge<br />

rund um das Netzwerk basieren auf TCP/IP, entweder<br />

über verkabeltes Ethernet oder drahtlos. Aber es gibt noch<br />

eine ganze Reihe andere Netzwerktypen, die genutzt werden.<br />

Alle Distributionen und Desktops beinhalten gute<br />

Werkzeuge, um TCP/IP-basierte Netzwerke zu konfigurieren<br />

und zu verwalten, vom allgegenwärtigen NetworkManager<br />

bis hin zu individuellen Tools wie das Netzwerk-<br />

Konfigurationswerkzeug von Gnome oder Yast von<br />

OpenSUSE.<br />

Bluetooth<br />

Neuere Entwicklungen im Netzwerkbereich<br />

umfassen die drahtlose 3G-Kommunikation<br />

und PAN-Technologien (Personal Area Network)<br />

wie etwa Bluetooth. <strong>Das</strong> Verwenden<br />

eines Breitband-Dongles für das 3G-Netz ist<br />

recht einfach, meist genügt der NetworkManager oder die<br />

PPP-Software Ihres Desktops.<br />

Bluetooth wird mit der wachsenden Anzahl von Mobilgeräten<br />

immer wichtiger, und auch die Liste der Eingabegeräte,<br />

die das Protokoll benutzen, wird immer länger. Es sind nicht<br />

nur die Smartphone- und Tablet-Benutzer, die davon profitieren<br />

– eine Bluetooth-Maus und Funk-Lautsprecher können<br />

auch den Umgang mit einem Notebook komfortabler machen.<br />

Mit PulseAudio geht das sehr einfach, da dieses zwischen<br />

den Ausgabegeräten umschalten kann, sobald sie erkannt<br />

wurden.<br />

Speicher<br />

<strong>Das</strong> Speichern von Daten auf einer Festplatte hat mehrere<br />

Aspekte. Alle physikalischen Speicher drehen sich bei Linux<br />

um blockbasierte Geräte. Ein blockbasiertes Gerät wie<br />

/dev/sda1 verweist wirklich auf Blöcke, bestimmte physisch<br />

vorhandene Bereiche auf der Festplatte, die zu einer Partition<br />

zusammengefasst werden. Darauf setzt das Dateisystem<br />

auf, das bestimmt, wie die gespeicherten Daten in Strukturen<br />

bestehend aus Dateien und Verzeichnissen organisiert werden.<br />

Diese bestehen wiederum jeweils aus Daten und Metadaten.<br />

Wo liegt der Unterschied zwischen Daten und Metadaten?<br />

Angenommen, wir haben eine Datei, die etwas Text<br />

enthält. Die Daten in dieser Datei entsprechen dem Text,<br />

aber die Datei hat auch Attribute. Dazu gehören der Besitzer,<br />

die Zeit der Erstellung, die Zeit, zu der die Datei zuletzt<br />

geändert wurde, die Zeit des letzten Zugriffs sowie Informationen<br />

darüber, wer die Datei lesen und bearbeiten darf.<br />

<strong>Das</strong> sind die Informationen, die angezeigt werden, wenn Sie<br />

den Befehl ls -l auf eine Datei anwenden oder sich deren<br />

Eigenschaften im Dateimanager ansehen. <strong>Das</strong> Standard-<br />

Dateisystem, das heute verwendet wird, ist ext4, aber es gibt<br />

auch alternative Dateisysteme wie ext3, ReiserFS, XFS, JFS<br />

und natürlich auch FAT und NTFS aus der Windows-Welt.<br />

<strong>Das</strong> Netzwerk ist unerlässlich für den Betrieb eines Linux-Systems. <strong>Das</strong> Localhost-Interface<br />

wird automatisch eingerichtet, für den Rest haben wir Programme<br />

wie den NetworkManager.<br />

Andere Linux-Betriebssysteme<br />

Linux ist nicht nur ein Betriebssystem, das<br />

auf „klassischer <strong>Hardware</strong>“ (Desktops, Notebooks,<br />

Server) läuft, sondern es wird noch<br />

in ganz anderen Umgebungen eingesetzt,<br />

darunter viele Embedded-Geräte wie Router,<br />

Videorecorder oder Set-Top-Boxen.<br />

Falls etwa Ihr Router den Zugriff über SSH<br />

erlaubt, werden Sie sich womöglich schnell zwar auf dem gleichen Source-Code basieren,<br />

zu Hause fühlen, wenn Sie sich einloggen. aber alles, was darüber läuft, ist anders. Die Funktionsprinzipien<br />

sind sich in gewisser Weise ähn-<br />

Es gibt aber noch eine andere Klasse von Geräten,<br />

wo Linux genutzt wird: Smartphones und lich, aber deren Ausführung unterscheidet sich<br />

Tablets, die Android verwenden. Auch Android ist stark – auch wenn Sie ähnliche Kommandozeilenwerkzeuge<br />

finden werden, falls Sie ein Terminal-<br />

nämlich eigentlich Linux, es nutzt den Linux-Kernel.<br />

Aber es ist nicht GNU/Linux. Der Kernel mag Fenster auf Ihrem Smartphone aufbekommen.<br />

13


Grundlagen<br />

Desktops<br />

Gnome, KDE, Cinnamon, Unity – die Benutzerschnittstelle.<br />

Betrachtet man den Kernel als die unterste Ebene des Systems,<br />

stellt das Benutzerinterface die oberste dar. Der Kernel,<br />

die Treiber, die <strong>Hardware</strong>schnittstellen – all das wäre<br />

nutzlos, wenn man den Computer nicht bedienen könnte.<br />

Im Allgemeinen meint man mit dem Benutzerinterface<br />

einen grafischen Desktop. Hier begegnen wir dann weiteren<br />

Schichten. X (oder zukünftig vielleicht Wayland) bietet lediglich<br />

eine blanke Fläche. Sie brauchen noch etwas, um Ihnen<br />

die Vorzüge einer fensterbasierten Oberfläche zu bieten. Und<br />

dieses Etwas ist der Fenstermanager.<br />

In der Vergangenheit waren Fenstermanager Standalone-<br />

Systeme. Von diesen gibt es immer noch eine ansehnliche<br />

Anzahl, so wie etwa OpenBox oder Enlightenment. Heutzutage<br />

sind die Fenstermanager jedoch oft ein Teil einer großen<br />

Desktop-Umgebung. Ein Fenstermanager ist ein Programm,<br />

das das Öffnen, Schließen, die Positionierung und andere<br />

Steuerungen rund um ein Fenster verwaltet. Nach und nach<br />

übernahmen die Fenstermanager noch weitere Funktionen<br />

wie etwa Taskleisten oder Menüs zum Starten von Programmen,<br />

bis schließlich daraus die heute bekannten<br />

Desktop-Umgebungen wurden.<br />

Softwaresammlungen<br />

Eine Desktop-Umgebung ist im Großen und Ganzen<br />

eine Sammlung von Werkzeugen, die nötig<br />

sind, um einen kompletten Desktop zu betreiben.<br />

Es laufen Programme darauf, sie steuern deren<br />

Fenster und verfolgen, was sich auf dem System<br />

abspielt. Im Hintergrund läuft aber<br />

immer noch ein Fenstermanager: etwa KWin<br />

bei KDE und Metacity bei Gnome, um nur zwei zu<br />

nennen. Es ist die Stufe der Integration, die eine Desktop-Umgebung<br />

von einem Fenstermanager unterscheidet.<br />

Bei KDE, wo alles rund um einen gemeinsamen Kern arbeitet<br />

Es gibt auch eine große Anzahl von sehr schlanken Fenstermanagern.<br />

OpenBox, das hier gerade auf CrunchBang<br />

läuft, ist einer davon.<br />

und Programme nicht nur untereinander kommunizieren,<br />

sondern eines auch in das Fenster eines anderen eingebunden<br />

werden kann, ist das klar zu erkennen.<br />

Während es nicht viel Sinn ergeben mag, KWin mit Gnome<br />

zu benutzen, möchten Sie vielleicht einen der besseren Fenstermanager<br />

ausprobieren. Oder vielleicht möchten Sie auch<br />

eine andere Art zum Anzeigen von Fenstern verwenden. Beispielsweise<br />

gibt es Fenstermanager, die auf das sogenannte<br />

Tiling setzen, wie etwa awesome und xmonad. Diese skalieren<br />

die Fenster automatisch so, dass sie alle auf den Desktop<br />

passen. KDE hat eine eigene Option, um dieses Verhalten zu<br />

erreichen. Es gibt Fenstermanager, die darauf ausgelegt sind,<br />

mit der Tastatur steuerbar zu sein, genauso wie solche Exemplare,<br />

die auf sehr spezialisierten Systemen von Nutzen<br />

sind. Diese führen Programme im Vollbildmodus aus und<br />

wollen nicht, dass irgendein Widget Platz verschwendet.<br />

Gnome, KDE,<br />

Unity, Cinnamon,<br />

Mate – die Auswahl<br />

ist nicht gerade<br />

klein, wenn<br />

es um die passende<br />

Desktop-<br />

Umgebung geht.<br />

14


Grundlagen<br />

Sound<br />

Ein (früher) kniffliges Thema.<br />

<strong>Das</strong> Soundausgabesystem unter Linux hat bereits einige<br />

Anpassungen hinter sich. Über Jahre war OSS (Open<br />

Sound System) der Standard, bevor es von ALSA<br />

(Advanced Linux Sound Architecture) abgelöst wurde. ALSA gibt<br />

es immer noch, inzwischen haben sich aber auch PulseAudio und<br />

Jack hinzugesellt.<br />

ALSA unterstützt mehrere Soundkarten, wovon jede mehrere<br />

Ein- und Ausgänge haben kann. Sofern die <strong>Hardware</strong><br />

dies unterstützt, beherrscht es auch <strong>Hardware</strong>-Mixing, andernfalls<br />

nutzt es Software-Mixing. Damit entfällt die Notwendigkeit<br />

eines Soundmanagers, wie er in der Vergangenheit<br />

von KDE und Gnome zur Verfügung gestellt wurde. Ein<br />

Soundmanager wurde gebraucht, um mehr als ein Programm<br />

gleichzeitig Sound abspielen zu lassen. ALSA arbeitet<br />

sehr hardwarenah, um die Latenz möglichst gering zu halten.<br />

Inzwischen wird fast jede <strong>Hardware</strong> direkt unterstützt. Die<br />

Musikwiedergabe sollte also sofort nach der Installation der<br />

Distribution funktionieren. ALSA ist eine Kombination aus<br />

Kernel-Code und User-Space-Anwendungen. Es stellt auch<br />

eine API zur Verfügung, sodass es von anderen Anwendungen<br />

direkt kontrolliert werden kann. Dazu gehören etwa die<br />

Lautstärkeregler, die in den meisten Desktop-Umgebungen<br />

integriert sind.<br />

PulseAudio<br />

PulseAudio ist ein neueres Audio-Framework, aber kein Ersatz<br />

für ALSA. Stattdessen setzt es auf dem Kernel-Audio-<br />

System auf und erlaubt so eine <strong>erweiterte</strong> Kontrolle darüber.<br />

PulseAudio arbeitet als Server, der Eingaben von den Quellen<br />

annimmt und sie an die Ausgabe (<strong>Hardware</strong> oder eine Aufzeichnungssoftware)<br />

weiterleitet. In vielen Fällen befindet<br />

sich ALSA auf der Ausgangsseite, aber auch am Eingang<br />

kann ein ALSA-Treiber aktiv sein. <strong>Das</strong> kommt beispielsweise<br />

dann vor, wenn eine Anwendung PulseAudio nicht direkt unterstützt.<br />

<strong>Das</strong> Funktionsprinzip lässt sich so weit treiben,<br />

dass ein Ausgangssignal, das von einer Anwendung an ALSA<br />

gesendet wurde, von eben jenem abgefangen und an Pulse-<br />

Audio geleitet werden kann, welches es wieder zurück zu<br />

ALSA sendet. Deshalb ist es keine Überraschung, dass viele<br />

Anwender PulseAudio für zu kompliziert halten. Ein gutes Interface<br />

sollte eine solche Verkettung aber transparent machen.<br />

Die meisten Distributionen erfüllen diese Anforderung<br />

auch und bieten so zusammen mit ALSA eine funktionierende<br />

Soundlösung, die auch mit mehreren Soundausgabegeräten<br />

zusammenarbeitet. ALSA unterstützt zwar mehrere Ausgabegeräte,<br />

das Standardgerät ist aber systemweit als<br />

solches festgelegt. Mit PulseAudio ist es dagegen möglich,<br />

die Musik direkt zu den Lautsprechern zu leiten, während Sie<br />

mit dem ebenfalls mit dem <strong>PC</strong> verbundenen Bluetooth-Headset<br />

gerade einen VoIP-Anruf verwenden. Des Weiteren ist es<br />

möglich, die Lautstärke einzelner Programme separat zu regeln.<br />

PulseAudio ist außerdem netzwerkfähig. Es kann dazu<br />

verwendet werden, andere PulseAudio-Server zu finden und<br />

über deren Lautsprecher Sound abzuspielen.<br />

JACK (Jack Audio Connection Kit) ist ein Sound-Server,<br />

der für professionelle Audio-Anwendungen entworfen wurde.<br />

Seine Stärke ist eine latenzarme Echtzeitverbindung zwischen<br />

Anwendungen speziell für Sound- und MIDI-Daten. Die<br />

Software ist für den täglichen Computergebrauch unnötig,<br />

aber sehr nützlich für Nachwuchsmusiker.<br />

Drucken<br />

CUPS und Treiber.<br />

Während Open Source die Wahlfreiheit fördert<br />

und deshalb oft auch mehrere Programme die<br />

gleiche Aufgabe auf leicht unterschiedliche<br />

Art und Weise erledigen, gibt es einige Bereiche, wo<br />

bestimmte Programme im Prinzip konkurrenzlos dastehen.<br />

Was X.org für die universelle Grafikdarstellung darstellt,<br />

ist CUPS für den Bereich des Druckens.<br />

Wenn Sie einen Drucker an Ihrem Linux-Rechner angeschlossen<br />

haben, brauchen Sie zwei Dinge: CUPS sowie<br />

einen Treiber für Ihren Drucker. In vielen Fällen erhalten Sie<br />

beides gemeinsam. CUPS ist ein Server, der im Hintergrund<br />

auf Druckanfragen wartet. So gut wie jede Anwendung, die<br />

das Drucken beherrscht, kennt auch das Internet Printing<br />

Protocol (IPP), dessen Sprache auch die von CUPS ist. Wenn<br />

Sie in Ihrer Textverarbeitung oder im Browser den Drucken-<br />

Button betätigen, erscheint ein Fenster, das Ihre installierten<br />

Drucker zeigt. Die Anwendung braucht nur die Druckdaten zu<br />

senden, was normalerweise in PostScript geschieht, und<br />

CUPS kümmert sich um alles Weitere. Es muss dabei nicht<br />

einmal auf dem lokalen Computer laufen, denn CUPS ist ein<br />

netzwerkbasierter Dienst und macht so den Drucker am lokalen<br />

<strong>PC</strong> auch für jeden anderen Rechner im Netzwerk verfügbar.<br />

Ohne Treiber, der CUPS sagt, wie mit dem Drucker<br />

gesprochen wird, ist es aber nutzlos. Deshalb bringt CUPS<br />

eine große Anzahl Treiber mit. Viele weitere gibt es, wenn Sie<br />

das gutenprint-Treiberpaket installieren, und von HP gibt es<br />

ein Treiberpaket namens hplib, das sowohl die Drucker als<br />

auch die Scanner des Herstellers abdeckt.<br />

Manche Hersteller bestehen aber darauf, ihre eigenen Treiber<br />

anzubieten, anstatt sie mit CUPS zu bündeln. Meist geht<br />

es dabei um Lizenzfragen. In diesem Fall haben Sie die Alternative,<br />

die Internetseite des Druckerherstellers auf einen passenden<br />

Treiber hin zu durchsuchen und diesen separat zu installieren.<br />

Der Drucker sollte anschließend unter CUPS und<br />

im Konfigurationsfenster ihrer Distribution auftauchen. Sie<br />

können auch vor dem Kauf eines Druckers auf linuxprinting.<br />

org vorbeischauen, damit Sie zu einem Modell eines kooperativeren<br />

Druckerherstellers greifen können.<br />

Die Verwaltung<br />

von Druckern<br />

über CUPS ist<br />

so leicht wie das<br />

Anklicken von<br />

ein paar Links<br />

im Browser.<br />

Dies liegt am<br />

eingebauten<br />

Web-Interface.<br />

15


Grundlagen<br />

16


Grundlagen<br />

Eben Upton<br />

E wie Eben<br />

Wir haben der <strong>Raspberry</strong> <strong>Pi</strong> Foundation einen<br />

Besuch abgestattet und mit ihrem Gründer<br />

über Themen wie geistiges Eigentum und<br />

<strong>Hardware</strong>-Upgrades gesprochen.<br />

Vermutlich gibt es wenige Menschen, die<br />

ein so volles Programm haben wie Eben<br />

Upton. Mit seinem Namen verbindet sich<br />

zuallererst die Tatsache, dass er den Rasp berry <strong>Pi</strong><br />

entscheidend mit auf den Weg gebracht hat: Von<br />

Beginn an stand er im Zentrum der Realisierung<br />

des Mini-Computers, überwachte das Gerätedesign<br />

bis ins Detail, organisierte die Herstellung und<br />

war maßgeblich dafür verantwortlich, dass der <strong>Pi</strong><br />

in so unglaublicher Weise ins Zentrum des Interesses<br />

gerückt ist. Mittlerweile hat die von Upton mitgegründete<br />

Stiftung die Produktion des Geräts<br />

nach Großbritannien verlagert, ein zusätzliches<br />

Kameramodul verwirklicht und den <strong>Pi</strong> für vielfältige<br />

neue Anwendungsbereiche fit gemacht.<br />

Zwischen der Beantwortung von Anfragen<br />

potenzieller Kooperationspartner und von Medien<br />

aus aller Welt fand Eben Upton dennoch etwas Zeit<br />

für ein Interview.<br />

Frage: War es sehr schwierig, den großen Ansturm<br />

auf den <strong>Raspberry</strong> <strong>Pi</strong> zu bewältigen?<br />

Upton: Zum Glück haben uns die <strong>Pi</strong>-Hersteller<br />

RS und element14 einen Großteil der Sorgen<br />

über die Logistik und die hohen Stückzahlen<br />

abgenommen.<br />

Frage: Hatten Sie die Zusammenarbeit mit den<br />

Dienstleistern von Anfang an geplant?<br />

Upton: Ja, das war bereits die ursprüngliche<br />

Idee, denn uns wurde noch vor der ersten Auslieferung<br />

klar, dass die Nachfrage unsere eigenen<br />

Kapazitäten höchstwahrscheinlich weit<br />

übersteigen würde. Unsere finanziellen Mittel –<br />

eine Viertelmillion Dollar – reichten für die Produktion<br />

von 10.000 Exemplaren aus. Als wir<br />

das erste SD-Karten-Image für den <strong>Raspberry</strong><br />

<strong>Pi</strong> veröffentlichten und plötzlich 50.000 Downloads<br />

hatten, wussten wir, dass wir ein Problem<br />

hatten [lacht]. <strong>Das</strong> Team, das die erste,<br />

noch sehr fehlerhafte Version des Betriebssystems<br />

entwickelte, wusste zu Beginn seiner<br />

Arbeit ja nicht einmal, ob der <strong>Pi</strong> überhaupt je<br />

gebaut werden würde, doch nun mussten wir<br />

uns schnell etwas über legen.<br />

Frage: <strong>Das</strong> war Ende 2011?<br />

Upton: Richtig. Hätten wir zu diesem Zeitpunkt<br />

das ursprüngliche Gerätedesign beibehalten,<br />

wären die Bestellungen allein des ersten Tages<br />

vermutlich erst nach einem Jahr abgearbeitet<br />

gewesen. Tatsächlich hat dies nur drei oder<br />

vier Monate gedauert, auch wenn es uns länger<br />

vorkam. Aus eigener Kraft hätten wir selbst<br />

im besten Fall wohl nur 100.000 Stück im ersten<br />

Jahr verkaufen können, doch niemals eine<br />

Million oder mehr. <strong>Das</strong> Zauberwort war daher<br />

die Auslagerung der Massenherstellung des<br />

<strong>Raspberry</strong> <strong>Pi</strong> an externe Dienstleister. Unsere<br />

Partner können es in puncto Stückzahlen mit<br />

Amazon aufnehmen. Allein RS verschickt nach<br />

eigenen Angaben täglich 44.000 Warenpakete<br />

– da macht der <strong>Raspberry</strong> <strong>Pi</strong> zwar einiges an<br />

Volumen aus, doch letztlich stellt die Auslieferung<br />

für RS kein Problem dar.<br />

Frage: Der Startschuss für die Auslieferung war<br />

ein denkwürdiges Ereignis, oder?<br />

Upton: Allerdings! Wir, die Entwickler, hatten<br />

neun Monate oder so darauf warten müssen,<br />

die Hersteller RS und element14 nur ein, zwei<br />

Monate.<br />

Frage: Ihre Ehefrau Liz Upton hat als PR-Chefin der<br />

<strong>Raspberry</strong> <strong>Pi</strong> Foundation sehr geschickt die Spannung<br />

angeheizt.<br />

Upton: <strong>Das</strong> hat sie in der Tat. Für unsere Produktionspartner<br />

war die riesige Nachfrage<br />

sicherlich eine Überraschung. Der <strong>Raspberry</strong><br />

<strong>Pi</strong> sichert bei beiden Herstellern einen<br />

ansehnlichen Teil des Geschäfts und hat<br />

ihnen deutliches Wachstum beschert. Und<br />

für das Team bedeutete der große Erfolg eine<br />

Veränderung der Sichtweise auf unsere Ziele<br />

und Herausforderungen.<br />

Frage: Auch auf einer persönlichen Ebene?<br />

Upton: Ja. Zwar wurde der Spaß an der Sache<br />

nicht weniger, aber das ganze Projekt wurde<br />

dennoch auch ernsthafter, denn nun hingen<br />

auf einmal die Jobs von Menschen davon ab.<br />

Derzeit sichert der <strong>Raspberry</strong> <strong>Pi</strong> die Arbeitsplätze<br />

von etwa einhundert Leuten. <strong>Das</strong> verändert<br />

den Blick auf die Dinge. Würden wir lediglich<br />

100 Platinen pro Woche herstellen, könnten<br />

wir ohne großes Risiko einzelne Bauelemente<br />

austauschen und im schlimmsten Fall<br />

würden wir in dieser Woche einen Ausschuss<br />

von 100 Stück produzieren. De facto sind es<br />

aber zwischen 30.000 und 50.000 Einheiten,<br />

die wöchentlich hergestellt werden, sodass ein<br />

Fehler beträchtlichen Einfluss auf das Geschäft<br />

hätte und Menschen dadurch ihren Job verlieren<br />

könnten. Wie gesagt, es macht nach wie<br />

vor Spaß, aber man wird etwas vorsichtiger.<br />

Frage: Interessanterweise haben Sie das <strong>Raspberry</strong>-<strong>Pi</strong>-Projekt<br />

sowohl als Stiftung als auch als<br />

Geschäftstätigkeit konzipiert. <strong>Das</strong> ist eine ungewöhnliche<br />

Kombination, nicht wahr?<br />

Upton: Nun, gemeinhin geht man davon aus,<br />

dass gemeinnützige Organisationen keine großen<br />

Stückzahlen realisieren können – allerdings<br />

ist gerade dies sehr wichtig, wenn man<br />

nachhaltig arbeiten möchte. Wir wollten trotzdem<br />

ge mein nützig bleiben, als Nonprofit-<br />

Organisation. Darum stecken wir das verdiente<br />

Geld wieder in das Projekt. Ich selbst bekomme<br />

von der Stiftung kein Gehalt bezahlt, was<br />

ich glücklicher weise auch nicht benötige.<br />

Frage: Könnte sich das irgendwann ändern?<br />

Upton: Vermutlich könnte es das eines Tages,<br />

denn ich arbeite mehr als Vollzeit für die Stiftung,<br />

wenn Sie so wollen, bin jedoch nach wie<br />

vor ein Angestellter der Broadcom<br />

17


Grundlagen<br />

jedoch das Layout der Leiterplatte. Eine<br />

interessante Frage. Ob wir das Layout<br />

veröffent lichen werden? Eigentlich war das<br />

immer so geplant und ist es noch. Allerdings<br />

kann man die verbauten Chips in dieser<br />

Form ja gar nicht kaufen. <strong>Das</strong> ist also ein<br />

weiteres Problem, um das wir uns kümmern<br />

müssen.<br />

Corporation. Broadcom ist extrem großzügig<br />

mir gegenüber. Ich nehme an, das Unternehmen<br />

betrachtet das Ganze unter dem Marketingaspekt.<br />

Wir brauchten allerdings einige<br />

Zeit, bis wir Broadcom von der Idee überzeugt<br />

hatten.<br />

Frage: Lässt sich das damit vergleichen, als<br />

Linus Torvalds bei Transmeta angestellt war?<br />

Upton: Ja, man kann es vergleichen. Allerdings<br />

war Torvalds anscheinend sehr stark<br />

bei Transmeta involviert, während ich etwa<br />

90 % meiner Arbeitszeit nicht für Broadcom,<br />

sondern für <strong>Raspberry</strong>-<strong>Pi</strong>-Aktivitäten<br />

aufwende.<br />

Ob ich irgendwann direkt für meine <strong>Raspberry</strong>-<strong>Pi</strong>-Arbeit<br />

ein Gehalt bekommen<br />

werde? Möglicherweise wird der Tag kommen,<br />

an dem Broadcom das jetzige Arrangement<br />

nicht mehr vorteilhaft erscheint, das<br />

wäre dann der richtige Zeitpunkt für einen<br />

Wechsel. Allerdings ist es nicht so, dass<br />

irgendwer eine Dividende aus dem <strong>Raspberry</strong>-<strong>Pi</strong>-Geschäft<br />

erhalten würde – alle<br />

Gewinne, die nach Abzug der Gehälter in der<br />

Organisation verbleiben, werden wieder in<br />

die Entwicklung des <strong>Raspberry</strong> <strong>Pi</strong> investiert.<br />

<strong>Das</strong> ist sehr schön, denn es gibt uns die<br />

„Wir sollten nicht unser<br />

gesamtes geistiges Eigentum<br />

zur Verfügung stellen, denn<br />

es sichert die Nachhaltigkeit<br />

des <strong>Raspberry</strong> <strong>Pi</strong>.“<br />

Möglichkeit, nachhaltig zu arbeiten und<br />

auch strategische Entscheidungen finanziell<br />

zu unterfüttern. Beispielsweise können wir<br />

uns dadurch interessante neue Projekte wie<br />

die Entwicklung der Kamera leisten. Der <strong>Pi</strong><br />

ist von Pete Lomas von Norcott Technologies<br />

entwickelt worden, wobei diese Arbeit<br />

eine Zuwendung an die Stiftung war, zu<br />

deren Treuhändern Lomas gehört. Die<br />

Kameraplatine wurde als kommerzielles<br />

Produkt entwickelt, daher haben wir in dem<br />

Fall Leute für das Gerätedesign bezahlt.<br />

Frage: Hat dies einen Einfluss darauf, ob die<br />

Schaltpläne der <strong>Hardware</strong> der Öffentlichkeit<br />

zugänglich gemacht werden?<br />

Upton: Die Schaltpläne sind öffentlich, nicht<br />

Frage: Ist das der Grund dafür, dass das Layout<br />

der Leiterplatte bisher nicht öffentlicht ist?<br />

Upton: Wenn wir das Layout des <strong>Raspberry</strong><br />

<strong>Pi</strong> veröffentlichen, können Sie dennoch keinen<br />

selber bauen, denn die Chips sind nicht<br />

als Einzelkomponenten auf dem Markt<br />

erhältlich. Es gibt aber noch einen weiteren<br />

Grund: Einige Leute – nicht viele – waren<br />

sehr erbost darüber, dass wir unser geistiges<br />

Eigentum nicht vollständig der Allgemeinheit<br />

zur Verfügung gestellt haben. Der<br />

Zorn dieser Leute ist bislang auf die Stiftung<br />

gerichtet. Wenn wir nun das Layout der Leiterplatte<br />

herausgeben würden, weiß ich, wer<br />

stattdessen den Ärger abbekommen würde<br />

– nämlich Broadcom, die die Chips herstellen,<br />

und das hätten sie nicht verdient. <strong>Das</strong><br />

Unternehmen hat uns äußerst viel Unterstützung<br />

gegeben, darum lasse ich einstweilen<br />

die Kritik gerne über mich ergehen.<br />

Ich vertrete nicht die Ideologie, dass wir<br />

unser gesamtes geistiges Eigentum zur Verfügung<br />

stellen sollten, denn das Geld, das<br />

wir damit verdienen, sichert die Nachhaltigkeit<br />

des <strong>Raspberry</strong> <strong>Pi</strong>. Ein ziemlich wichtiger<br />

Aspekt des <strong>Pi</strong> ist es, dass es ihn wahrscheinlich<br />

auch in fünf Jahren noch geben wird –<br />

ein gutes Verkaufsargument. So können Sie<br />

nämlich ein industrielles Produkt<br />

auf Basis des <strong>Pi</strong> herstellen<br />

oder einen Lehrplan entwickeln,<br />

der sich auf das Gerät<br />

stützt.<br />

Frage: Und Sie möchten all das<br />

nicht dadurch verwässert sehen,<br />

dass ein anderer Hersteller einen<br />

eigenen <strong>Raspberry</strong> <strong>Pi</strong> anbietet?<br />

Upton: So ist es. Würden wir das<br />

Gerätede sign herausgeben und dadurch<br />

anderen Produzenten die Herstellung von<br />

<strong>Raspberry</strong>-<strong>Pi</strong>-Klonen ermöglichen, würden<br />

wir die finanzielle Grundlage unserer Arbeit<br />

unterminieren. Es ist ja nicht so, dass wir 10<br />

Dollar an jedem <strong>Pi</strong> verdienen würden! Unsere<br />

Marge ist klein genug, und darum können wir<br />

das Gerät auch so günstig anbieten. Bei Klongeräten<br />

würde das Geld vermutlich in Form<br />

von Dividenden in die privaten Taschen anderer<br />

Leute fließen. Letztendlich würden wir die<br />

Stiftung destabilisieren – ihre Möglichkeiten,<br />

in Bildung oder Open-Source-Projekte zu<br />

investieren, würden beschnitten.<br />

Frage: Wird es ein Upgrade des <strong>Raspberry</strong> <strong>Pi</strong><br />

geben? Haben Sie die Möglichkeit eines modu-<br />

18


Grundlagen<br />

beeinflussen kann. Und das funktioniert<br />

ganz gut. Der ARM bewegt <strong>Pi</strong>xel für <strong>Pi</strong>xel,<br />

aber nun da wir die Sachen mit <strong>Pi</strong>xmap<br />

gemacht haben, ist es ein ARM, der die<br />

<strong>Pi</strong>xel bang!, bang!, bang! transportiert. In<br />

dem Maße, wie ein ziemlich langsamer<br />

ARM <strong>Pi</strong>xel schnell bewegen kann, bewegen<br />

wir jetzt die <strong>Pi</strong>xel schnell. Im End effekt<br />

haben wir uns entschieden, das mit der<br />

X-Beschleunigung sein zu lassen. Stattdessen<br />

sollten wir uns in die schöne neue Welt<br />

von Wayland begeben.<br />

Frage: Weil das einfacher ist?<br />

Upton: Ja, ich glaube schon, dass es einfacher<br />

ist. Wenn wir jede der Alternativen<br />

„Es wäre traurig und fatal,<br />

wenn wir 2016 noch immer<br />

den gleichen <strong>Pi</strong> vertreiben<br />

würden.“<br />

lar aufgebauten Geräts in Erwägung gezogen?<br />

Upton: Bislang haben wir keinen Platz auf<br />

der Platine, um zusätzlichen RAM-Speicher<br />

unterzubringen. Wir können das RAM nicht<br />

erweitern, denn der SoC-Prozessor kann nur<br />

den vorhandenen Speicher ansprechen. Und<br />

den Prozessor können wir wiederum nicht<br />

mit einer höheren Leistung ausstatten, da<br />

diese vom SoC vorgegeben ist. Wir haben<br />

im Grunde keinen Fahrplan für eine <strong>Hardware</strong>-Erweiterung.<br />

Frage: Haben Sie denn noch keinen <strong>Raspberry</strong><br />

<strong>Pi</strong> 2 im Hinterkopf?<br />

Upton: Es wäre traurig – und wohl auch fatal<br />

für uns –, wenn wir im Jahr 2016 oder so<br />

noch immer den gleichen <strong>Raspberry</strong> <strong>Pi</strong> vertreiben<br />

würden. Wir müssen etwas tun, aber<br />

eine konkrete Idee habe ich noch nicht. <strong>Das</strong><br />

Problem ist, dass ich mir zwar eine Platine<br />

zu einem beliebigen Preis zwischen 25 und<br />

85 Dollar ausdenken könnte, dass es jedoch<br />

ex trem schwierig ist, etwas wirklich Attraktives<br />

zu kreieren. Der <strong>Raspberry</strong> <strong>Pi</strong> ist so<br />

attraktiv, weil er ein tolles Preis-Leistungs-<br />

Verhältnis besitzt. Zu einem vergleichbaren<br />

Preis, also etwa zwischen 25 und 35 Dollar,<br />

könnte ich auf Grundlage der aktuell verfügbaren<br />

<strong>Hardware</strong> keine Platine bauen, die<br />

dem <strong>Pi</strong> das Wasser reichen würde.<br />

Sogar in einer Preisklasse von 45 Dollar<br />

wäre es noch schwierig, den <strong>Raspberry</strong> <strong>Pi</strong> zu<br />

übertreffen. Mit einem 55-Dollar-Gerät wäre<br />

das vermutlich machbar, doch ich frage<br />

mich, warum es dann kein entsprechendes<br />

Teil auf dem Markt gibt.<br />

Frage: Wie halten Sie denn dann die Dynamik<br />

aufrecht?<br />

Upton: Mit einer Menge Softwarearbeit.<br />

Frage: Auf der Softwareseite liegt also momentan<br />

der gesamte Fokus?<br />

Upton: Mit seinen 700 MHz ist der Chip des<br />

<strong>Raspberry</strong> <strong>Pi</strong> ein extrem leistungsfähiger<br />

Grafikprozessor. 97 % der Leistung werden<br />

für die Grafik aufgewandt.<br />

Frage: Was benötigt eine Standardinstallation<br />

des Betriebssystems Raspbian?<br />

Upton: Derzeit benutzt sie den Video-Output,<br />

den USB-Controller – Dinge, die vor dem<br />

ARM da waren. Der ARM hat den Chip 3 %<br />

größer gemacht. Hauptsächlich ist der ARM<br />

gefordert, ein bisschen von der Systeminfrastruktur,<br />

ein SDRAM-Controller und einige<br />

kleine Peripheriebausteine. Ein großer Teil<br />

des Systems ist die meiste Zeit über inaktiv.<br />

Der 700-MHz-ARM-Prozessor besitzt eine<br />

Menge Power, aber im historischen Kontext<br />

ist er auch ein wenig voluminös. Da wir auf<br />

der <strong>Hardware</strong>seite mehr oder weniger festgelegt<br />

sind, investieren wir mehr Arbeit in<br />

die Software, um möglichst viel von der<br />

Leistung herauszukitzeln. Wir haben Elemente<br />

auf der Systemebene optimiert –<br />

Dinge wie <strong>Pi</strong>xmap, memcpy und memset.<br />

Wir hatten eine Diskussion über X-Beschleunigung.<br />

Wir haben keine X-Beschleunigung,<br />

wir haben keinen Beschleunigungstreiber.<br />

Wir haben viele Komponenten auf<br />

dem Chip, eine Menge Subsysteme, mit<br />

denen man den X-Server-Beschleuniger<br />

finanzieren können, würde ich das Geld<br />

doch lieber auf die schöne neue Welt verwenden.<br />

Der Trend geht hin zu Wayland,<br />

daher sollten wir dort mit von der Partie<br />

sein, und das möglichst bald. Wir haben mit<br />

etwas herumprobiert, wo bei Ausreizung der<br />

Speicherbandbreite eine Off-Screen-Erstellung<br />

als Ausweichlösung fungiert. <strong>Das</strong> ist<br />

ziemlich cool und gibt einem das reine<br />

60-Hz-Window-Dragging. In einer Welt, wo<br />

jedes Fenster ein <strong>Hardware</strong>-Sprite ist, werden<br />

beim Ziehen von Fenstern keinerlei <strong>Pi</strong>xel<br />

bewegt.<br />

Wir haben dieses Video-Scaler-Bauteil, das<br />

größer ist als der ARM, da es eine Menge Pufferspeicher<br />

benötigt, um die Sprites zu steuern.<br />

Da wir also etwas haben, das sich um<br />

Render-Hierarchien kümmert, sowie einen<br />

Window-Manager, sollten wir die Software<br />

entwickeln, um beides zu verbinden. Dies ist<br />

ein gutes Beispiel dafür, wie wir mithilfe der<br />

Software einen Mehrwert für den Benutzer<br />

schaffen, ohne einen neuen Chip zu bauen.<br />

Und es gibt uns Zugang zu dem wunderbaren<br />

Wayland.<br />

Frage: <strong>Das</strong> klingt nach der ersten hochkarätigen<br />

Anwendung von Wayland!<br />

Upton: Ich glaube, wir haben das erste Wayland-Backend<br />

ohne GL. Normalerweise wird<br />

auf GL aufgesetzt, aber GL ist lausig, wenn<br />

der Bildaufbau darauf aufsetzt, denn die Skalierungsfilter<br />

sind primitiv – sogar beim<br />

Herunter skalieren muss man eine Reihe Mipmaps<br />

generieren. Unser Backend funktioniert<br />

jedoch anders. Wenn man beispielsweise im<br />

Verhältnis 3:1 herunterskalieren möchte,<br />

baut es jeden <strong>Pi</strong>xel dadurch auf, dass es<br />

Durchschnittswerte eines 3x3-Gitters von<br />

<strong>Pi</strong>xeln aus dem Originalbild verwendet.<br />

19


Grundlagen<br />

Ursprünge: Wie<br />

Hier erfahren Sie etwas über die Entstehungsgeschichte des <strong>Raspberry</strong> <strong>Pi</strong><br />

sowie über dessen einzelne Bauteile.<br />

Doch nicht nur die Bequemlichkeit hält die Menschen davon<br />

ab, einen Blick unter die Haube ihrer Rechenmaschinen zu werfen,<br />

um herauszufinden, wie sie genau funktionieren. Ein weiterer<br />

Grund sind diverse Klauseln in den Endbenutzerverträgen<br />

von Windows und Mac OS X, die das Modifizieren des Programmcodes<br />

verbieten. Obwohl Sie eine ansehnliche Summe<br />

für das Betriebssystem bezahlt haben, ist es Ihnen nicht erlaubt,<br />

es zu „zerlegen“ und wieder „zusammenzusetzen“. Diese<br />

beiden Faktoren sorgen in Kombination dafür, dass die Anwender<br />

wenig Ahnung von den Funktionsabläufen innerhalb ihrer<br />

Computern haben.<br />

Heutzutage hält ein Computer seine Funktionsweise versteckt.<br />

Sie öffnen ein Dropdown-Menü, klicken mit der<br />

Maus auf ein Icon, und das Programm, das Sie gerade<br />

benutzen, macht das, was Sie wollen. Oder zumindest das, was<br />

es laut dem Ersteller der Software machen soll. Leider ist die<br />

Benutzung eines Computers für die meisten Menschen nur<br />

noch gleichbedeutend mit der Benutzung einer Software, die<br />

jemand anders für sie geschrieben hat, und nicht mehr mit der<br />

Entwicklung eigener Lösungen für eine Aufgabenstellung. Es<br />

stimmt natürlich, dass grafische Benutzeroberflächen den Computer<br />

einem weit größeren Kreis von Anwendern zugänglich<br />

gemacht haben, als dies ohne solche Programme je möglich<br />

gewesen wäre. Aber es stimmt genauso, dass die meisten<br />

Anwender nur noch eine grobe Ahnung davon haben, wozu ihr<br />

Computer eigentlich in der Lage wäre.<br />

Die Stunde des <strong>Raspberry</strong> <strong>Pi</strong><br />

Hier kommt nun Eben Upton ins Spiel, Studienleiter für Informatik<br />

am St. John’s College in Cambridge. Im Rahmen seiner Tätigkeit<br />

ist er unter anderem am Zulassungsprozess für neue Studenten<br />

beteiligt. Dabei stellte er über die Jahre hinweg einen<br />

kontinuierlichen Verfall der Fähigkeiten bei den Bewerbern fest.<br />

Je mehr Zeit Universitäten aufwenden müssen, um Bewerber<br />

mit unterdurchschnittlichem Vorwissen auf das Standardniveau<br />

zu heben, desto weniger Zeit bleibt, um den Studenten die wirklich<br />

interessanten Dinge beizubringen. Dies hat natürlich zur<br />

Folge, dass auch das Kenntnisniveau der Berufseinsteiger in<br />

der Informatikbranche sich mit der Zeit verschlechtert und Personalchefs<br />

es zunehmend schwerer haben, einen Bewerber mit<br />

ausreichender Qualifikation zu finden.<br />

Um dem entgegenzuwirken, haben Eben Upton und einige<br />

Mitstreiter den Plan geschmiedet, ein Gerät zu entwickeln, das<br />

„hackbar“, billig und frei von Schutzansprüchen ist sowie zu<br />

einem Bruchteil der Kosten prinzipiell zu allem in der Lage ist,<br />

was auch ein normaler <strong>PC</strong> kann. <strong>Das</strong> Produkt, das die Gruppe<br />

aus dem Hut zauberte, war – na klar! – der <strong>Raspberry</strong> <strong>Pi</strong>.<br />

Der BBC Micro<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> war nicht der erste Computer, der mit der Absicht<br />

entwickelt wurde, das IT-Wissen der britischen Bevölkerung zu verbessern.<br />

1981 brachte Acorn Computers in Zusammenarbeit<br />

mit dem Computer-Kompetenz-Projekt der BBC den BBC Micro<br />

auf den Markt. <strong>Das</strong> Gerät war in zwei Versionen – Modell A<br />

und Modell B – erhältlich und wurde mit dem Zweck entworfen,<br />

darauf Programme laufen zu lassen, die Jugendliche im Umgang<br />

mit Computern trainieren sollten. Eine Fernsehsendung der BBC<br />

begleitete das Projekt. Der größte Unterschied zwischen den beiden<br />

Versionen war der Preis: 1981 kostete das Modell A 235 Pfund und das<br />

schnellere Modell B stolze 335 Pfund. Der BBC Micro wurde zu einem<br />

riesigen Erfolg und trug nicht wenig dazu bei, dass eine ganze Generation<br />

britischer Kinder mit einem soliden Wissen darüber aufwuchs, wie man<br />

einen Computer programmiert. <strong>Das</strong>s der Chip im Herzen des <strong>Raspberry</strong><br />

<strong>Pi</strong> auf dem Design einer Firma – ARM – basiert, die aus Acorn Computers<br />

ausgegründet wurde, stellt dabei eine nette historische Fußnote dar.<br />

Zu heutigen Preisen würde das<br />

Modell B des BBC Micro umgerechnet<br />

1.300 Euro kosten – der <strong>Pi</strong><br />

ist dagegen für 35 Dollar zu haben.<br />

20


Grundlagen<br />

der <strong>Pi</strong> entstand<br />

Ein Blick auf den <strong>Raspberry</strong> <strong>Pi</strong><br />

Slot für die SD-Karte<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> hat keinen Speicher mit an Bord,<br />

weshalb Sie diesen mit einer SD-Karte nachrüsten<br />

müssen, um darauf das Betriebssystem und Ihre<br />

Dateien zu speichern. Die Idee dahinter ist, dass<br />

Sie nur das bezahlen müssen, was Sie brauchen:<br />

<strong>Das</strong> kann eine 4-GB-Karte für wenige Euro oder<br />

eine 128-GB-Karte für ein kleines Vermögen sein.<br />

System-on-a-Chip<br />

Dieses kleine Element ist<br />

das Herz des <strong>Raspberry</strong><br />

<strong>Pi</strong>: Es besteht aus einem<br />

700 MHz schnellen<br />

ARM11-Prozessor<br />

und einer Videocore-<br />

4-Grafikeinheit. Der<br />

Arbeitsspeicher sitzt<br />

im System-on-a-Chip:<br />

Modell A ist mit 256 MB<br />

RAM, Modell B mit 512<br />

MB RAM ausgerüstet.<br />

RCA-Video-Ausgang<br />

Für ältere Fernseher gibt es auch einen RCI-<br />

Video-Anschluss. Falls Ihr Bildschirm keine<br />

Anschlüsse für RCA oder HDMI besitzt, gibt es<br />

Adapter auf den gängigen DVI-Anschluss.<br />

3,5-mm-Audio-Klinke<br />

Mit diesem Anschluss verwandeln<br />

Sie den <strong>Raspberry</strong> <strong>Pi</strong> schnell in<br />

ein günstiges HiFi-System.<br />

USB-Anschlüsse<br />

<strong>Das</strong> Modell B hat zwei USB-<br />

Anschlüsse, die zum Betrieb<br />

einer Maus und einer Tastatur<br />

ausreichen. Um zusätzliche Geräte<br />

am <strong>Raspberry</strong> <strong>Pi</strong> zu betreiben,<br />

müssen Sie sich nach der Einrichtung<br />

entweder über das Netzwerk<br />

mit dem <strong>Raspberry</strong> <strong>Pi</strong> verbinden<br />

oder einen USB-Hub anschließen.<br />

Stromanschluss<br />

<strong>Das</strong> <strong>Raspberry</strong> <strong>Pi</strong> erhält seinen Strom über einen<br />

5-V-Micro-USB-Stecker. So können Sie die Platine<br />

günstig mit Energie versorgen. Falls Sie ein<br />

Android-Smartphone besitzen, haben Sie das<br />

passende Netzteil wahrscheinlich schon zu Hause.<br />

HDMI-Ausgang<br />

Die Entwickler des <strong>Raspberry</strong> <strong>Pi</strong> gingen davon aus,<br />

dass die meisten Nutzer das Gerät an einem Fernseher<br />

oder einem Bildschirm verwenden würden: Deshalb<br />

gibt es einen HDMI-Anschluss, der den <strong>Raspberry</strong> <strong>Pi</strong><br />

mit modernen TV-Geräten und Bildschirmen verbindet.<br />

Ethernet<br />

Stecker rein, und Sie sind mit dem Internet verbunden<br />

– es sei denn, Sie haben zum Modell A<br />

gegriffen, das keinen Ethernet-Anschluss besitzt.<br />

In diesem Fall verwenden Sie einen WLAN-Adapter,<br />

den Sie in einen USB-Anschluss einstöpseln.<br />

Modell A oder Modell B?<br />

Es gibt zwei Typen des <strong>Raspberry</strong> <strong>Pi</strong>, das Modell<br />

A und das Modell B. Bei beiden handelt es sich<br />

im Prinzip um den gleichen Computer. Die einzigen<br />

Unterschiede liegen im Preis, in der Größe<br />

des RAMs und in den vorhandenen Anschlüssen.<br />

Während das Modell B 512 MB aufweist, hat<br />

das Modell A nur 256 MB. <strong>Das</strong> Modell A verfügt<br />

außerdem nur über einen USB-Anschluss,<br />

während das Modell B derer zwei hat. Außerdem<br />

kommt das Modell B mit Ethernet-Anschluss,<br />

der dem Modell A komplett fehlt. Deshalb kostet<br />

das Modell B auch 35 Dollar, das Modell A<br />

ist dagegen schon für 25 Dollar zu haben. <strong>Das</strong><br />

Modell B ist aufgrund dieser Unterschiede die<br />

vielseitigere Version der beiden und deshalb auch<br />

die Variante, die wir empfehlen sowie für dieses<br />

Heft verwendet haben. Falls Sie keinen Internetanschluss<br />

brauchen – vielleicht, weil es Ihnen um<br />

eine Möglichkeit geht, ein Embedded-System zu<br />

betreiben – ist das Modell A immer noch eine gute<br />

Wahl, die Ihnen hilft, die Kosten gering zu halten.<br />

<strong>Das</strong> gilt vor allem, wenn Sie viele davon brauchen.<br />

Trotzdem bevorzugen wir die Flexibilität des Modell<br />

B, die für wenige Euro zusätzlich zu haben ist.<br />

21


Grundlagen<br />

Richtig verbinden:<br />

Unser detaillierter Guide, wie Sie das richtige Zubehör wählen und welche<br />

Verbindungen Sie für eine optimale Performance brauchen.<br />

Der <strong>Raspberry</strong> <strong>Pi</strong><br />

kann wählerisch<br />

sein, wenn es um<br />

die Kompatibilität<br />

der Speicherkarte<br />

geht. Versichern<br />

Sie sich daher,<br />

dass Sie eine<br />

Karte kaufen, die<br />

funktioniert und<br />

passt. Achtung:<br />

Die Karte ganz<br />

oben hat die<br />

richtigen Maße!<br />

Bevor Sie mit dem <strong>Raspberry</strong> <strong>Pi</strong> loslegen können, müssen<br />

Sie einiges an Zubehör anschließen. Es lohnt sich, hier<br />

mit Sorgfalt vorzugehen, denn Probleme aufgrund falscher<br />

Verbindungen oder inkompatibler Peripherie sind im Nachhinein<br />

oft schwer aufzuspüren. Deswegen lohnt es sich nachzuschauen,<br />

welche <strong>Hardware</strong> am besten funktioniert – vor allem,<br />

wenn Sie den Kauf eines neuen <strong>Raspberry</strong> <strong>Pi</strong> planen.<br />

Am besten fangen Sie mit der SD-Karte an, denn dies ist das<br />

vermutlich wichtigste Zubehör, das Sie für Ihren <strong>Raspberry</strong> <strong>Pi</strong><br />

brauchen. Die kleinen Plättchen mit der abgeschnittenen Ecke<br />

dienen dazu, das Betriebssystem darauf zu speichern, und sind<br />

die einzigen Einheiten, von denen Ihr <strong>Raspberry</strong> <strong>Pi</strong> booten kann.<br />

Gerade zu Beginn müssen Speicherkarten einiges einstecken:<br />

Ihre SD-Karte muss willkürliche Neustarts sowie ständiges Entfernen<br />

und Einsetzen aushalten und ist ständig dem Risiko<br />

ausgesetzt, an eine unebene Platine angeschlossen zu werden.<br />

Aus diesen Gründen ist es ein bisschen knifflig, die richtige<br />

SD-Karte auszusuchen. So ist es nicht empfehlenswert, eine<br />

Karte mit zu hoher Kapazität zu kaufen: Dabei bezahlen Sie<br />

einen hohen Preis für ein Stück <strong>Hardware</strong>, das schnell kaputtgehen<br />

kann. Andererseits ist eine bestimmte Menge an Speicher<br />

schon erforderlich, da Sie mindestens 2 GB benötigen, um<br />

das Standard-Betriebssystem Raspbian zu installieren. Dafür<br />

nicht genutzter Speicher kann dazu verwendet werden, Ihre eigenen<br />

Dateien oder Zusatzeinheiten zu speichern, darum sollten<br />

Sie auch wiederum nicht zu knapp kalkulieren.<br />

Wir empfehlen Ihnen, für den Anfang eine Karte mit 4 GB<br />

Speicher zu kaufen und bei Bedarf ein zusätzliches USB-Gerät –<br />

etwa eine externe Festplatte – zu benutzen. Solche Geräte bieten<br />

Ihnen erstens mehr Speicher zu einem niedrigeren Preis,<br />

und zweitens bleiben so Ihre darauf gespeicherten Medienoder<br />

Konfigurationsdaten erhalten, auch wenn Sie das Betriebssystem<br />

auf der SD-Karte überschreiben. Außerdem lohnt es<br />

sich, die Karte noch vor dem Kauf auf Kompatibilität zu überprüfen,<br />

da es mehrere SD-Karten gibt, die mit dem <strong>Raspberry</strong><br />

<strong>Pi</strong> nicht funktionieren. Achten Sie des Weiteren darauf, eine SD-<br />

HC-Karte zu kaufen („HC“ steht für „high capacity“, hohe Kapazität),<br />

da SDSC-, SDXC- sowie SDIO-Karten dafür bekannt sind,<br />

Probleme zu verursachen. Auf http://elinux.org/R<strong>Pi</strong>_SD_cards<br />

werden sowohl die funktionierenden als auch die fehlerhaften<br />

Karten aufgelistet, basierend auf den Erfahrungen der<br />

<strong>Raspberry</strong>-Benutzer. Sogar Karten von großen Herstellern wie<br />

SanDisk oder Kingston versagen manchmal beim <strong>Pi</strong> ihren<br />

Dienst, daher lohnt es sich auf jeden Fall, vor dem Kauf die<br />

Kompatibilität zu überprüfen.<br />

Falls Sie ein völliger Neuling sind, sollten Sie erwägen, sich<br />

eine SD-Karte mit vorinstalliertem Raspbian zu besorgen. Dadurch<br />

umgehen Sie sowohl das mögliche Problem der Inkompatibilität<br />

als auch die Schwierigkeiten beim Installieren<br />

des Systems auf der Karte. In der Praxis hatten wir<br />

bei unseren Versuchen selten Probleme mit Speicherkarten<br />

aus dem Fachhandel. Was Sie ebenfalls probieren<br />

können, ist die Verwendung einer alten SD-Karte von einer<br />

Kamera.<br />

Energieversorgung<br />

Man könnte annehmen, die Energiezufuhr für den <strong>Raspberry</strong> <strong>Pi</strong><br />

wäre kein größeres Thema, aber das würde täuschen. Haben<br />

Sie nämlich nicht die richtige Versorgung für Ihre <strong>Pi</strong>-Konfiguration,<br />

dann können Sie nur schwer bestimmen, ob eventuell<br />

22


Grundlagen<br />

Peripherie<br />

Gehäuse für den <strong>Raspberry</strong> <strong>Pi</strong><br />

Obwohl dies nicht direkt die Leistung Ihres<br />

<strong>Raspberry</strong> <strong>Pi</strong> beeinflussen wird, lohnt sich die<br />

Anschaffung eines Gehäuses für die Platine. Standardmäßig<br />

ist der <strong>Pi</strong> sehr anfällig für Einwirkungen<br />

von außen, da die schützende Schicht sehr dünn<br />

ist und Metallflächen einen Kurzschluss verursachen<br />

und den <strong>Raspberry</strong> <strong>Pi</strong> beschädigen können.<br />

Dank der „Do it yourself“-Idee des Projekts gibt<br />

es für jedes Budget das passende Gehäuse. Wer<br />

sich die Ausgabe ganz sparen möchte, kann einen<br />

Gegenstand des täglichen Gebrauchs umfunktionieren,<br />

wie etwa die Hülle einer Audiokassette,<br />

oder sogar ein Gehäuse aus Lego-Steinen bauen<br />

– wenn Sie dabei durchsichtige Steine verwenden,<br />

können Sie weiterhin die Anzeigen die Status-<br />

LEDs sehen. Wenn Sie bereit sind, ein wenig Geld<br />

auszugeben, gibt es verschiedene bunte Acrylgehäuse<br />

für etwa 6 Euro. Viele dieser Gehäuse<br />

haben einen weiteren Vorteil: Sie können anmontiert<br />

werden. Nachdem Ihr <strong>Pi</strong> also einmal eingepackt<br />

ist, können Sie ihn überall anbringen – ob<br />

im Inneren eines Spieleautomaten oder an einem<br />

Regalbrett. Bedenken Sie dabei nur, dass der <strong>Pi</strong><br />

bei hoher Belastung viel Wärme abgeben kann.<br />

auftretende Probleme das Resultat der Energiezufuhr oder aber<br />

eines Softwarefehlers sind. Als wir beispielsweise am Tutorial<br />

zum Thema Fernsehaufzeichnung mit dem <strong>Pi</strong> gearbeitet haben,<br />

konnten wir mit unserer USB-<strong>Hardware</strong> stundenlang keinen einzigen<br />

TV-Kanal finden, obwohl alles vollkommen fehlerfrei aussah.<br />

Letztendlich war der von uns benutzte USB-Hub einfach<br />

nicht leistungsfähig genug. Um ausreichend Energie für Ihren <strong>Pi</strong><br />

bereitzustellen, empfehlen wir Ihnen die ausschließliche Verwendung<br />

von Micro-USB-Ladegeräten mit mindestens 1,2 A.<br />

Mehr als 1,2 A verursachen keine Probleme, weniger kann zu<br />

unvorhersehbarem Verhalten führen. Solche Adapter liegen einerseits<br />

vielen modernen Mobiltelefonen bei, andererseits finden<br />

Sie sie in den meisten Elektrofachgeschäften. Jeder Adapter<br />

mit weniger als 1,2 A kann zu Problemen führen, wenn Ihr <strong>Pi</strong><br />

stärker beansprucht wird.<br />

Für externe USB-Verbindungen empfehlen wir dringend, einen<br />

guten USB-2.0-Hub (HiSpeed) zu verwenden. Diesen verbinden<br />

Sie mit Ihrem <strong>Raspberry</strong> <strong>Pi</strong> über einen Standard-B-Stecker und<br />

ein Standard-A-Kabel. Ältere 1.0-Hubs scheinen zwar zu funktionieren,<br />

doch hatten wir Probleme bei der <strong>Hardware</strong>-Kompatibilität<br />

– dieses Risiko sollte man lieber vermeiden. Außerdem<br />

müssen Sie sicherstellen, dass der Hub separat und nicht nur<br />

über den <strong>Raspberry</strong> <strong>Pi</strong> mit Strom versorgt wird. Bei vielen preisgünstigen<br />

Hubs gehört ein Netzteil nicht zum Lieferumfang,<br />

kann jedoch angeschlossen werden – achten Sie hierbei auf die<br />

jeweiligen Spezifikationen. Die Hubs müssen 5 V liefern und<br />

möglichst auch 3,5 A, damit Sie mehrere Geräte an den <strong>Pi</strong> anschließen<br />

können. Einfacher ist es, für ein wenig mehr Geld<br />

gleich einen Hub mit eigenem Netzteil zu erwerben. Achten Sie<br />

darauf, sämtliches Zubehör über den Hub und nicht direkt an<br />

den <strong>Pi</strong> anzuschließen, denn nur so profitieren Sie von der externen<br />

Stromversorgung.<br />

Vernetzen<br />

Für die Installation und Konfiguration müssen Sie den <strong>Raspberry</strong><br />

<strong>Pi</strong> mit Ihrem Heimnetzwerk verbinden. <strong>Das</strong> erledigen Sie am<br />

besten über den Ethernet-Port auf der Platine, den großen<br />

RJ45-Anschluss an der Seite. Die meisten Internetverbindungen<br />

zu Hause finden über einen Wireless-Hub statt, der außerdem<br />

über einige RJ45-Anschlüsse verfügen sollte – falls Sie Geräte<br />

wie Spielkonsolen oder TV-Receiver per Kabel anschließen<br />

möchten. Der <strong>Raspberry</strong> <strong>Pi</strong> lässt sich auf die gleiche Art und<br />

Weise verbinden: Solange Ihr Hub in Betrieb ist, müssen Sie<br />

einfach beide Geräte per Ethernet-Kabel miteinander verbinden.<br />

Sollte das nicht möglich sein, können Sie eine andere Option<br />

nutzen, nämlich eine Verbindung via „Ethernet über Strom“-Adapter,<br />

auch als Powerline-Adapter bekannt. Einen der zwei Adapter<br />

verbinden Sie dabei mit einem freien Ethernet-Port Ihres<br />

Sie müssen sich überlegen, wie Sie<br />

sowohl das <strong>Raspberry</strong> <strong>Pi</strong> als auch die<br />

daran angeschlossenen USB-Geräte mit<br />

Strom versorgen möchten.<br />

Ethernet-<br />

Verbindungen sind<br />

einfach, aber viele<br />

USB-Geräte werden<br />

auch dann funktionieren,<br />

wenn Sie<br />

einfach das Desktop-WiFi-Programm<br />

benutzen.<br />

23


Grundlagen<br />

Hubs und einer Steckdose, während der andere in eine Steckdose<br />

in der Nähe Ihres <strong>Pi</strong> gesteckt wird und über ein<br />

Ethernet-Kabel den <strong>Raspberry</strong> <strong>Pi</strong> mit dem Netzwerk<br />

verbindet.<br />

Wenn Sie ein Modell A ohne<br />

Ethernet-Schnittstelle besitzen oder<br />

lieber eine kabellose Verbindung<br />

nutzen möchten, dann ist der Vorgang<br />

komplexer. Zuerst müssen<br />

Sie sich ein kabelloses USB-Gerät<br />

besorgen, das mit dem <strong>Raspberry</strong> <strong>Pi</strong><br />

kompatibel ist. Wir empfehlen Ihnen,<br />

zuerst einen Blick auf das überprüfte<br />

Zubehör unter elinux.org zu werfen<br />

(http://elinux.org/R<strong>Pi</strong>_VerifiedPeripherals)<br />

und ein Gerät zu wählen, das sicher funktioniert.<br />

Dadurch müssen Sie keine Treiber ohne Internet verbindung<br />

installieren. Außerdem sollten Sie das Gerät über einen USB-<br />

Hub mit eigener Stromversorgung verbinden und nicht direkt an<br />

den <strong>Pi</strong> anschließen, da kabellose Verbindungen beträchtliche<br />

Mengen Strom verbrauchen können. <strong>Das</strong> Einzige, das Sie danach<br />

noch zur Herstellung einer kabellosen Verbindung tun<br />

müssen, ist es, auf die Schaltfläche zur WiFi-Konfiguration auf<br />

dem Raspbian-Desktop zu klicken. Falls Ihr WiFi-Gerät richtig erkannt<br />

wird, sehen Sie „wlan0“ als Adapternamen und müssen<br />

nur noch auf die Scan-Schaltfläche klicken. Mit etwas Glück<br />

wird Ihr Heimnetzwerk erkannt und Sie müssen es nur noch<br />

doppelklicken, um das Konfigurationsfenster zu öffnen. Geben<br />

Sie das Netzwerk-Passwort ein und klicken Sie auf „Hinzufügen“.<br />

Schließen Sie das Fenster mit den Scan-Ergebnissen; die<br />

Statusseite sollte Ihnen anzeigen, dass Ihr <strong>Pi</strong> mit dem Netzwerk<br />

verbunden ist. Sie können die Netzwerk-Einstellungen jederzeit<br />

über die Netzwerkverwaltung ändern. Vor dem Schließen des<br />

Programms oder dem Neustart Ihres <strong>Raspberry</strong> <strong>Pi</strong> sollten Sie<br />

immer Ihre Konfiguration speichern.<br />

HDMI lässt sich einfach in DVI konvertieren, um das <strong>Pi</strong><br />

zusammen mit den meisten Flachbildschirmen zu benutzen.<br />

USB-Tastatur und -Maus<br />

Wenn Sie über eine funktionierende Netzwerk-Verbindung verfügen,<br />

brauchen Sie nicht unbedingt eine Tastatur oder eine<br />

Maus. Ist das Raspbian-System installiert, können Sie sich per<br />

Fernsteuerung mithilfe eines Protokolls namens SSH mit Ihrem<br />

<strong>Pi</strong> verbinden. Installieren Sie über einen Windows-Rechner den<br />

kostenlosen Putty-Client. OS-X- und Linux-Nutzer verfügen über<br />

einen eingebauten SSH-Client: Tippen Sie ssh, gefolgt von pi@<br />

und der IP-Adresse Ihres <strong>Pi</strong> in die Kommandozeile (Ihr Router<br />

oder Hub hat eine Konfigurationsseite mit den IP-Adressen aller<br />

angeschlossenen Geräte). <strong>Das</strong> Passwort für den Standard-Account<br />

(„pi“) ist „raspberry“. Wenn Sie verbunden sind, können<br />

Sie tippen und Ihren <strong>Raspberry</strong> <strong>Pi</strong> direkt konfigurieren, ohne<br />

eine Maus, Tastatur oder einen Bildschirm anschließen<br />

Per Fernsteuerung<br />

können Sie<br />

Maus, Tastatur<br />

und Bildschirm<br />

eines anderen<br />

Geräts mit Ihrem<br />

<strong>Pi</strong> verwenden.<br />

24


Grundlagen<br />

Programmierbare Schnittstelle<br />

Eine Anschlussart des <strong>Raspberry</strong> <strong>Pi</strong> unterscheidet<br />

sich deutlich von den anderen: Es handelt sich<br />

dabei um die <strong>Pi</strong>ns auf der Oberseite der Platine.<br />

<strong>Das</strong> sind die Allzweckeingabe- und Allzweckausgabe-Anschlüsse<br />

oder programmierbaren<br />

Schnittstellen (engl.: General Purpose Input Output<br />

Connectors, kurz GPIO), die etwa für spezielle<br />

<strong>Hardware</strong>projekte oder zur Verbindung mit Zubehör<br />

niedriger Stufe gedacht sind. Jeder <strong>Pi</strong>n hat eine<br />

eigene Funktion und kann über die Entwicklungsumgebung<br />

oder mittels Programmiersprache<br />

gesteuert werden. Sie können die <strong>Pi</strong>ns etwa dafür<br />

benutzen, LEDs zu steuern oder Motoren, wenn<br />

der <strong>Pi</strong> die Steuereinheit eines Roboters bildet.<br />

Auf der Platine befinden sich 26 <strong>Pi</strong>ns (mit „P1“<br />

gekennzeichnet), deren Funktion sich einhergehend<br />

mit der Überarbeitung des <strong>Pi</strong> leicht verändert<br />

hat. Daher müssen Sie wissen, welche <strong>Raspberry</strong>-<br />

Revision Sie haben – falls Sie etwa vorhaben,<br />

eine Tochterplatine zu kaufen, die direkt über die<br />

GPIO-<strong>Pi</strong>ns angeschlossen wird. Jeder <strong>Raspberry</strong><br />

<strong>Pi</strong>, der Ende 2012 oder später hergestellt wurde,<br />

gehört zur Revision 2. Die bekannteste Erweiterungsplatine<br />

ist das Gertboard, das<br />

dem <strong>Pi</strong> alle möglichen Arten von<br />

programmierbarer Funktionalität<br />

einbringt – etwa Motorsteuerung,<br />

Digital-/Analog-Umwandler, zwölf<br />

LED-Leuchten oder auch neue<br />

Brücken und Anschlüsse. Allerdings<br />

benötigen Sie zu Beginn<br />

keine zusätzliche Platine, da die<br />

<strong>Pi</strong>ns auch ohne Modifikationen zu<br />

verschiedenen Zwecken genutzt<br />

werden können. <strong>Das</strong> neueste<br />

Update fügt der Platine eine<br />

P5-Stiftleiste direkt neben den<br />

P1-GPIO-<strong>Pi</strong>ns hinzu. Die acht<br />

<strong>Pi</strong>ns sorgen für mehr Energie<br />

sowie für vier zusätzliche<br />

GPIO-Funktionen, die vor allem für die Bereitstellung<br />

eines sekundären I 2 C-Kanals genutzt<br />

werden können; I 2 C ist ein serieller Datenbus.<br />

Sie können Platinen wie das Gertboard benutzen, die sich<br />

über die GPIO-<strong>Pi</strong>ns mit dem <strong>Raspberry</strong> <strong>Pi</strong> verbinden lassen.<br />

zu müssen. Wenn Sie ein grafisches Interface haben wollen,<br />

können Sie auch ein Paket namens tightvncserver installieren<br />

und den Befehl vncserver :1 ausführen, um einen ferngesteuerten<br />

Desktop zu starten. Benutzen Sie einfach einen beliebigen<br />

kostenlosen VNC-Client auf einem anderen Gerät, um sich mittels<br />

der IP-Adresse und des Ports 5901 Ihres <strong>Raspberry</strong> <strong>Pi</strong> zu<br />

verbinden. Danach können Sie Ihre Tastatur und Maus per Fernsteuerung<br />

nutzen.<br />

Falls Sie jedoch eine Maus und eine Tastatur direkt an den <strong>Pi</strong><br />

anschließen möchten,<br />

„Falls Sie eine Tastatur anschließen<br />

möchten, dürften Sie keine<br />

großen Schwierigkeiten haben.“<br />

dürften Sie keine allzu<br />

großen Schwierigkeiten<br />

haben. Die meisten<br />

Modelle benutzen einen<br />

USB-Standard, weswegen<br />

Maus und Tastatur einfach<br />

funktionieren werden – es sei denn, Sie kaufen etwas Exotisches<br />

wie die neuesten kabellosen Microsoft- oder Logitech-<br />

Modelle. Sie müssen allerdings – wie bereits gesagt – beide<br />

Geräte über einen Hub mit externer Stromversorgung anschließen,<br />

sodass sie nicht zu viel Energie vom <strong>Raspberry</strong> ziehen.<br />

Falls Sie die Tastaturbelegung anpassen möchten, tippen Sie<br />

sudo dpkg-reconfigure keyboard-configuration in die Kommandozeile<br />

ein. Damit stellen Sie sicher, dass die Tasten Ihrer<br />

Tastatur mit denen beim <strong>Pi</strong> übereinstimmen.<br />

Display und Sound<br />

<strong>Das</strong> Modell B des <strong>Raspberry</strong> <strong>Pi</strong> verfügt über zwei Anschlüsse,<br />

über die man Videosignale zu einem Display senden kann. Der<br />

gelbe Klinkenstecker dient zur Übertragung des zusammengesetzten<br />

Videosignals (Composite Video) und kann an einer<br />

großen Anzahl an Fernsehern angeschlossen werden, die normalerweise<br />

einen gelben Anschluss für externe Kameras oder<br />

Rekorder besitzen. Der gelbe Stecker befindet sich oft in der<br />

Nähe eines roten und eines weißen Steckers, die zur Audioübertragung<br />

(links/rechts) dienen. Versichern Sie sich, dass der<br />

HDMI-Port frei ist, falls Sie den Composite-Video-Anschluss nutzen<br />

wollen: Der <strong>Raspberry</strong> <strong>Pi</strong> stellt immer bevorzugt eine HDMI-<br />

Verbindung her, wenn er eine entdeckt, und schaltet erst auf<br />

Composite-Übertragung um, wenn er keine HDMI-Verbindung<br />

findet.<br />

Allerdings ist der gelbe Stecker nicht die erste Wahl – es sei<br />

denn, Sie haben keine andere Option. Der moderne HDMI-<br />

Anschluss ist viel besser für die Übertragung geeignet, und Sie<br />

brauchen noch nicht einmal einen HDMI-Port an Ihrem Display,<br />

um ihn zu benutzen. Der Videoteil des Signals, der über HDMI<br />

übertragen wird, ist genau der gleiche wie das Videosignal, das<br />

etwa über das übliche DVI-Kabel eines <strong>PC</strong>-Monitors übertragen<br />

wird. Daher können Sie<br />

einfach ein Kabel mit<br />

einem männlichen DVI-<br />

Anschluss der Variante<br />

24+1 auf der einen Seite<br />

und einem männlichen<br />

19-<strong>Pi</strong>n-HDMI-Stecker auf<br />

der anderen nutzen. Oder Sie wählen einen Adapter mit einem<br />

männlichen 19-<strong>Pi</strong>n-HDMI-Stecker für den <strong>Raspberry</strong> <strong>Pi</strong> und<br />

einem weiblichen DVI-Anschluss für die Verbindung über ein übliches<br />

DVI-Kabel. <strong>Das</strong> alles mag jetzt sehr technisch und kompliziert<br />

klingen, doch handelt es sich sowohl beim DVI- als auch<br />

beim HDMI-Kabel und dem Adapter um übliche Teile, die Sie in<br />

jedem Elektronikgeschäft günstig besorgen können. Da die<br />

Kabel digitale Signale übertragen, lohnt sich die Investition in<br />

spezielle Adapter oder Umwandler nicht – es gibt kaum Anhaltspunkte<br />

dafür, dass solche Geräte die Signalstärke verbessern.<br />

Ein weiterer Vorteil des HDMI-Anschlusses: Sie können darüber<br />

auch die digitalen Audiodateien von Ihrem <strong>Raspberry</strong> <strong>Pi</strong><br />

übertragen. Ihr Fernseher oder Verstärker muss dieses Feature<br />

unterstützen, damit es funktioniert, und Sie werden ein bisschen<br />

an der <strong>Pi</strong>-Konfiguration herumspielen müssen, aber es ist<br />

eine gute Lösung, wenn Sie Ihren <strong>Raspberry</strong> als Medienhub<br />

benutzen wollen.<br />

Ein HDMI-zu-DVI-Umwandler bringt Ihnen bei der Soundübertragung<br />

nichts, da die Soundkomponente bei der Umwandlung<br />

weggelassen wird, aber Sie haben immer noch den analogen<br />

Audioanschluss zur Verfügung. Dessen Ausgabe ist zwar mit<br />

Nebengeräuschen verbunden, aber immerhin gut genug, um<br />

Videos zu einem Fernseher zu streamen.<br />

25


Grundlagen<br />

Fehlerbehebung:<br />

In den allermeisten Fällen werden Sie diese beiden Seiten gar nicht benötigen<br />

– Ihr <strong>Pi</strong> wird einfach starten. Falls es dennoch nicht klappen sollte, finden Sie<br />

hier einige Hinweise zur Fehlerbehebung.<br />

mit der richtigen Menge Strom versorgt wird. Selbst wenn Sie<br />

keine Netzwerkverbindung haben oder die SD-Karte nicht angeschlossen<br />

ist, sollte die LED während des gesamten Betriebs<br />

leuchten. Im Falle eines Flackerns oder sogar eines Verlöschens<br />

haben Sie ein Problem mit der Stromversorgung Ihres Geräts.<br />

Überprüfen Sie in diesem Fall sowohl Stromkabel als auch<br />

Netzteil. Ist Ihre SD-Karte angeschlossen, so sollte die äußerste<br />

LED auf der linken Seite aufleuchten. Mit ihr wird die<br />

Zugriffsaktivität auf der SD-Karte signalisiert.<br />

Der große Unterschied zwischen Ihrem <strong>Raspberry</strong> <strong>Pi</strong> und<br />

einem herkömmlichen <strong>PC</strong> ist die Tatsache, dass das <strong>Pi</strong><br />

kein BIOS besitzt. <strong>Das</strong> BIOS ist das Erste, was Sie beim<br />

Start Ihres <strong>PC</strong>s sehen. In einem teilweise an vergangene DOS-<br />

Zeiten erinnernden Bildschirm werden Ihnen Informationen über<br />

Speicher, CPU und angeschlossene Festplatten angezeigt, allerdings<br />

in einem kaum lesbaren Tempo. Dennoch spielt das BIOS<br />

eine große Rolle bei der Suche nach Fehlern wie etwa einer<br />

schadhaften CPU. Ein modernes BIOS meldet solche Probleme<br />

nicht nur via Bildschirmtext, sondern auch über akustische<br />

Signale und blinkende LEDs auf dem Motherboard. Ohne das<br />

BIOS fehlt Ihnen beim <strong>Raspberry</strong> <strong>Pi</strong> also ein wichtiges Werkzeug<br />

zum Erkennen von vermeintlichen Fehlern. Auch wenn Ihr <strong>Pi</strong><br />

beim ersten Mal ohne Weiteres booten wird, so steigt die Wahrscheinlichkeit<br />

eines Problems während eines Startvorgangs,<br />

je mehr Sie an der Funktionalität Ihres Geräts basteln. Und für<br />

genau solche Probleme gibt es hier einige Lösungen.<br />

Was die LEDs bedeuten<br />

Die einzigen Hinweise, wie weit der Bootvorgang vorangeschritten<br />

ist, erhalten Sie von einer Reihe LEDs neben dem Soundausgang<br />

und dem USB-Port. Während das Modell B über fünf<br />

LEDs verfügt, hat das Modell A nur zwei.<br />

LED 1: Grün, „ACT“: SD-Kartenzugriff<br />

LED 2: Rot, „PWR“: 3,3-Volt-Stromversorgung vorhanden<br />

LED 3: Grün, „FDX“: LAN-Kabel angeschlossen<br />

LED 4: Grün, „LNK“: Netzwerkaktivität<br />

LED 5: Gelb, „100“: Mit 100-Mbit-Netzwerk verbunden<br />

Da das Modell A über keine Netzwerkfunktionen verfügt, sind<br />

die letzten drei LEDs auf dessen Platine nicht vorhanden. Auch<br />

ist es möglich, dass bei älteren Modellen der B-Reihe die Bezeichnungen<br />

der LEDs ein wenig anders lauten. Die Funktionen,<br />

die sie beschreiben, bleiben trotzdem gleich.<br />

Wenn Sie Ihr <strong>Pi</strong> an eine Stromquelle anschließen, sollte die<br />

zweite LED rot aufleuchten. Dies zeigt Ihnen an, dass Ihr Gerät<br />

Startvorgang<br />

Beim Start Ihres Geräts wird diese LED kurz aufleuchten, verlöschen<br />

und dann wieder flackern, während das <strong>Pi</strong> den Boot-Code<br />

von der SD-Karte einliest. Passiert dies nicht, so ist es sehr<br />

wahrscheinlich, dass entweder Ihr Boot-Code nicht richtig auf<br />

die Speicherkarte geschrieben wurde oder aber die Speicherkarte<br />

nicht mit Ihrem <strong>Pi</strong> funktioniert. Überprüfen Sie, ob Ihre<br />

SD-Karte richtig angeschlossen ist und ob jeder SD-Mikroadapter,<br />

den Sie benutzen, richtig mit der Karte verbunden ist.<br />

Prüfen Sie auch, ob die Anschlüsse zwischen SD-Kartenadapter<br />

und Konnektor des <strong>Pi</strong>s identisch aussehen, da es hier in<br />

seltenen Fällen zu Kompatibilitätsproblem kommt.<br />

Weiterhin ist es auch möglich festzustellen, an welcher Stelle<br />

des Bootvorgangs das <strong>Raspberry</strong> <strong>Pi</strong> abbricht. Im Anschluss<br />

finden Sie eine Übersicht der verschiedenen Blinkmuster der<br />

„ACT“/„OK“-LED und deren Bedeutungen. Beachten Sie jedoch,<br />

dass diese Liste eine Firmware von mindestens Mitte 2012<br />

voraus setzt und wir diese Informationen den <strong>Raspberry</strong> <strong>Pi</strong>-Foren<br />

entnommen haben.<br />

3-maliges Aufleuchten: loader.bin nicht gefunden<br />

4-maliges Aufleuchten: loader.bin nicht geladen<br />

5-maliges Aufleuchten: start.elf nicht gefunden<br />

6-maliges Aufleuchten: start.elf nicht geladen<br />

Im Rahmen eines Firmware-Updates vom Oktober 2012<br />

wurden die Signale wie folgt neu zugeordnet:<br />

3-maliges Aufleuchten: start.elf nicht gefunden<br />

4-maliges Aufleuchten: start.elf nicht gestartet<br />

7-maliges Aufleuchten: kernel.img nicht gefunden<br />

Es ist möglich, diese Probleme dadurch zu beheben, dass<br />

Sie auf ihrer Speicherkarte nach den oben genannten Dateien<br />

schauen und sie auf ihre Richtigkeit überprüfen. Suchen Sie<br />

nach etwas mit dem Namen Checksum und überzeugen Sie<br />

sich davon, dass die Dateien auf der SD-Karte den gleichen<br />

Checksum-Wert haben wie die Originaldateien.<br />

Da aber solche Zugriffsfehler eher ein Hinweis darauf sind,<br />

dass entweder die SD-Karte nicht richtig ausgelesen werden<br />

kann oder aber das Betriebssystem Ihres <strong>Raspberry</strong> <strong>Pi</strong> nicht<br />

richtig auf diese geschrieben wurde, empfehlen wir Ihnen, dass<br />

Sie mit einer anderen Karte und einer anderen Methode der<br />

Image-Erstellung – unsere Installationsanleitung beschreibt<br />

Ihnen hierfür drei verschiedene Betriebssysteme – einen Versuch<br />

wagen. Während unserer Installation stießen wir jedoch<br />

26


Grundlagen<br />

Booten<br />

Die hellen LEDs<br />

des <strong>Raspberry</strong> <strong>Pi</strong><br />

sehen nicht nur<br />

schön aus, sondern<br />

können auch bei<br />

der Fehlerbehebung<br />

wichtige<br />

Hinweise liefern.<br />

Die Abbildungen<br />

zeigen eine ältere<br />

Version der Platine,<br />

auf der noch die<br />

Bezeichnungen<br />

„OK“ statt „ACT“<br />

und „10M“ statt<br />

„100“ neben den<br />

entsprechenden<br />

LEDs aufgedruckt<br />

sind.<br />

mit verschiedenen Kartenlesern auf Probleme. In vielen Fällen<br />

handelte es sich hierbei um solche, die in Laptops oder Notebooks<br />

verbaut waren. Daher empfehlen wir Ihnen, auf ein Einzelgerät<br />

umzusteigen. Sollten Sie Ihr <strong>Pi</strong> an einen Bildschirm<br />

angeschlossen haben, zeigen Ihnen aktuelle Versionen der<br />

Firmware einen kaleidoskopartigen Startbildschirm. Sollte der<br />

Startvorgang über diesen Bildschirm hinausgehen, aber nichts<br />

weiter passieren, liegt das Problem wiederum bei Ihrer<br />

Stromversorgung.<br />

Netzwerk<br />

Falls sich Ihr <strong>Raspberry</strong> <strong>Pi</strong> erfolgreich durch den initialen Startvorgang<br />

gearbeitet hat, wird nun Ihr Betriebssystem von der<br />

SD-Karte geladen. Hierbei sollte wegen des umfangreichen<br />

Datentransfers die erste LED die meiste Zeit leuchten. Die<br />

Geschwindigkeit des Bootvorgangs hängt zum größten Teil von<br />

der Geschwindigkeit der SD-Karte ab. Kurz nachdem Linux beginnt<br />

hochzufahren, blinkt zunächst die vierte LED („LNK“) und<br />

leuchten etwa eine halbe Sekunde später auch die anderen<br />

Netzwerk-LEDs. Dies zeigt an, dass die Netzwerkfunktionen<br />

aktiviert sind und sich das Gerät an Ihrem Netzwerk anmeldet.<br />

Die Netzwerk-LEDs sind vergleichbar mit denen auf der Netzwerkkarte<br />

Ihres <strong>PC</strong>s und weisen somit eher auf Probleme Ihres<br />

LAN-Netzwerks hin als auf Probleme mit der Konfiguration ihres<br />

<strong>Raspberry</strong> <strong>Pi</strong>.<br />

Die orangene LED signalisiert eine Full-Duplex-Verbindung.<br />

Ob es sich bei Ihrer Netzwerkverbindung um eine Full- oder<br />

Half-Duplex-Verbindung handelt, wird in dem Zusammenhang<br />

wichtig, ob Ihr <strong>Raspberry</strong> <strong>Pi</strong> gleichzeitig senden und empfangen<br />

kann. Auch wenn dies heutzutage in modernen Netzwerken nur<br />

noch selten ein Problem darstellt, hat dies natürlich Auswirkungen<br />

auf die Geschwindigkeit Ihres Geräts im Netzwerkverbund.<br />

Die „LNK“-LED ist in Bezug auf das Netzwerk das Äquivalent<br />

zu Ihrer „ACT“-LED für den SD-Karten-Zugriff, da diese durch<br />

Blinken den Transfer von Daten im Netzwerk signalisiert. Sollte<br />

diese LED aufleuchten, können Sie davon ausgehen, dass Ihr<br />

<strong>Raspberry</strong> <strong>Pi</strong> in der Lage war, eine Verbindung zwischen Ihrem<br />

Router und sich selber herzustellen. Allerdings nur mit einer<br />

geringen Bandbreite, daher muss Ihre Netzwerkverbindung<br />

noch keine ausreichende Funktionalität für das Surfen im Internet<br />

und das Abrufen von E-Mails haben. Es ist durchaus möglich,<br />

dass trotz offensichtlicher Aktivität Ihres <strong>Raspberry</strong> <strong>Pi</strong> das<br />

Gerät selbst kein aktiver Bestandteil des Netzwerks ist. Sollten<br />

Sie trotz blinkender LED keine wirklich funktionierende Verbindung<br />

zu Ihrem Netzwerk aufbauen können, sollten Sie sich mit<br />

der Konfiguration Ihres Netzwerks befassen. Überprüfen Sie<br />

zuerst, ob Ihr <strong>Pi</strong> eine IP-Adresse von ihrem Router zugeteilt bekommen<br />

hat und wiederholen sie den Vorgang im Betriebssystem<br />

Ihres <strong>Raspberry</strong> <strong>Pi</strong>. In vielen Fällen kann das Betriebssystem<br />

die Konfiguration selber vornehmen. In manchen<br />

komplexeren Netzwerken, mit verschiedenen Domains oder<br />

mehreren Routern, können aber durchaus Probleme auftauchen.<br />

Versuchen Sie in diesem Fall zuerst, die direkteste und<br />

einfachste Verbindung zu Ihrem Netzwerk aufzubauen, und<br />

dann, sich in die komplexeren Bereiche vorzuarbeiten, bis Sie<br />

die gewünschte Konfiguration gefunden haben.<br />

Die letzte LED zeigt Ihnen die Geschwindigkeit Ihres Netzwerks<br />

an. Sollte sie aufleuchten, erreicht Ihr <strong>Pi</strong> eine Geschwindigkeit<br />

von 100 Mbps. Anders ausgedrückt sind das<br />

100.000.000 Datenbits pro Sekunde. Dies ist natürlich bereits<br />

ein gewaltiger Unterschied zu den 10 Mbps, mit denen Ihr <strong>Pi</strong><br />

läuft, wenn diese LED nicht leuchtet, doch arbeiten moderne<br />

Netzwerke mittlerweile mit bis zu 1.000 Mbps. Der Grund,<br />

warum Ihr <strong>Raspberry</strong> <strong>Pi</strong> nicht in der Lage ist, eine solche Gigabitverbindung<br />

aufzubauen, ist die Tatsache, dass Ihr Ethernetadapter<br />

über einen USB2-Port implementiert wird, welcher<br />

die Transferrate auf 100 Mbps begrenzt. Dennoch reicht diese<br />

Verbindungsgeschwindigkeit für die gängigsten Anwendungen<br />

vollkommen aus. Ihr <strong>Raspberry</strong> <strong>Pi</strong> wird allerhöchstens an seine<br />

Grenzen im Netzwerkbereich stoßen, wenn Sie ihn als Hochleistungs-NAS<br />

oder zum gleichzeitigen Streamen mehrerer HD-<br />

Filme benutzen wollen. Andernfalls wird Ihnen der Unterschied<br />

in der Netzwerkgeschwindigkeit nicht auffallen und Sie können<br />

Ihr <strong>Raspberry</strong> <strong>Pi</strong> einfach genießen.<br />

27


Grundlagen<br />

Befehlszeile: Erste<br />

Lernen Sie die Befehlszeile Ihres <strong>Raspberry</strong> <strong>Pi</strong> kennen und entfesseln Sie<br />

seine volle Funktionalität, ohne die Maus zu benutzen.<br />

Interaktive Programme<br />

Die meisten der Befehle, die wir hier<br />

behandeln, sind nicht interaktiv. <strong>Das</strong><br />

bedeutet, man startet sie und wartet, bis<br />

sie fertig ausgeführt sind. Es funktionieren<br />

jedoch nicht alle Befehlszeilenprogramme<br />

auf diese Weise. Als Sie beispielsweise<br />

anfangs Raspbian hochgefahren haben,<br />

wurde ein Config-Tool, das im Terminal<br />

läuft, gestartet. Es gibt noch ein paar Programme,<br />

die ähnlich funktionieren, dazu<br />

zählen insbesondere die Texteditoren. Sie<br />

ermöglichen ein Bearbeiten von Dateien<br />

Wie Sie sicherlich schon festgestellt haben, hat das <strong>Pi</strong>-<br />

Betriebssystem Raspbian eine mit Windows oder Mac<br />

OS X vergleichbare Benutzeroberfläche. Die meisten<br />

alltäglichen Aufgaben kann man innerhalb dieser Benutzeroberfläche<br />

erledigen. Es gibt einen Dateimanager, Webbrowser, Texteditor<br />

und viele weitere nützliche Anwendungen. Manchmal benötigt<br />

man allerdings eine leistungsfähigere Zugriffsmöglichkeit,<br />

und hier kommt die Befehlszeile – auch Kommandozeile, Terminal<br />

oder Shell genannt – ins Spiel.<br />

Die Befehlszeile ist eine komplett textbasierte Benutzerschnittstelle,<br />

in die man Kommandos eingibt und daraufhin eine<br />

Ausgabe erhält. <strong>Das</strong> mag für den Neuling zunächst etwas verwirrend<br />

aussehen, doch so schlimm ist es gar nicht. Es lohnt<br />

sich, ein wenig Zeit in das Erlernen dieses Steuerungsprinzips<br />

zu investieren, denn dies wird sich später bezahlt machen.<br />

Als Erstes muss man ein Terminal öffnen. Hierzu klickt man<br />

auf LXTerminal auf dem Raspbian Desktop.<br />

Die folgende Zeile sollte jetzt erscheinen:<br />

pi@raspberrypi ~ $<br />

ohne grafisches Benutzerinterface. Es gibt<br />

einige recht komplizierte, die schwierig zu<br />

erlernen sind, die aber wirklich interessant<br />

werden, wenn man viel von der Befehlszeile<br />

aus arbeitet. Es gibt aber auch einen<br />

einfach zu bedienenden terminalbasierten<br />

Texteditor namens Nano. Geben Sie im Terminal<br />

nano ein, gefolgt von einem Dateinamen.<br />

Dann können Sie im ausgegebenen<br />

Text navigieren und Änderungen durchführen.<br />

Speichern Sie alles mit Ctrl+X, und<br />

kehren Sie zur Eingabeaufforderung zurück.<br />

<strong>Das</strong> ist die Eingabeaufforderung. Wenn sie erscheint, heißt<br />

das so viel wie: <strong>Das</strong> System ist startklar für Eingaben.<br />

Geben Sie das Kommando pwd ein, und drücken Sie die<br />

Enter-Taste. Folgendes sollte zu sehen sein:<br />

/home/pi<br />

Falls man seinen Benutzernamen geändert hat, sieht man<br />

eine andere Zeile. Der eher kryptisch benannte pwd-Befehl<br />

steht für „print working directory“ und gibt ganz einfach das<br />

Verzeichnis aus, in dem man sich gerade befindet. Wenn Sie<br />

das Terminal öffnen, startet es in Ihrem Home-Verzeichnis<br />

(mehr dazu auf Seite 32 in diesem Heft).<br />

Nun wissen wir also, wo wir uns befinden. Der nächste logische<br />

Schritt ist, sich durch die Verzeichnisstruktur zu bewegen.<br />

Hierzu verwendet man das Kommando cd („change directory“).<br />

Geben Sie Folgendes ein:<br />

cd ..<br />

pwd<br />

<strong>Das</strong> System sollte zu /home zurückkehren. <strong>Das</strong> kommt<br />

daher, dass wir in das „ ..“-Verzeichnis gewechselt haben. Zwei<br />

Punkte verweisen immer auf das übergeordnete Verzeichnis.<br />

Um zum Home-Verzeichnis zurückzukehren, kann man cd pi eingeben.<br />

Hierfür gibt es auch noch einen anderen Weg. Die Tilde<br />

(das Zeichen „~“) verweist immer auf Ihr Home-Verzeichnis.<br />

Wo auch immer man sich im Verzeichnisbaum befindet, gelangt<br />

man über die Eingabe von cd ~ dorthin zurück.<br />

Geben Sie nun ls ein, und drücken Sie die Enter-Taste. Dies<br />

listet alle Dateien im aktuellen Verzeichnis auf. Einer der großen<br />

Vorteile von Befehlen ist, dass wir festlegen können, wie<br />

sie ausgeführt werden. Dies geschieht mit der Hilfe von Parametern,<br />

die man nach dem Befehl setzt und die mit einem „-“<br />

beginnen. Wenn man zum Beispiel alle Dateien im aktuellen<br />

Verzeichnis auflisten möchte (einschließlich der versteckten,<br />

die bei unixbasierten Systemen mit „.“ beginnen), nutzen wir<br />

den Parameter -a. Schreiben Sie in Ihrem Terminal also ls -a.<br />

Jetzt sollten mehr Dateien erscheinen. Ein anderer Parameter<br />

für ls lautet -l. Dieser gibt uns weitere Informationen zu jeder<br />

Datei. Man kann sogar Parameter kombinieren wie zum Beispiel<br />

ls -al.<br />

Welche Befehle sollte man kennen?<br />

Sie fragen sich jetzt vielleicht, woher um alles in der Welt Sie<br />

wissen sollen, welche Befehle und Parameter Sie für eine bestimmte<br />

Aufgabe verwenden können. Es gibt eine gute und eine<br />

schlechte Nachricht. Die gute ist, dass es normalerweise nicht<br />

allzu schwierig ist, die Parameter für einen Befehl herauszufinden,<br />

in aller Regel geht dies mittels -h oder --help. Wenn man<br />

beispielsweise ls --help ausführt, erhält man eine lange Liste<br />

von Parametern und deren Bedeutung, einschließlich der<br />

folgenden:<br />

-a, --all Auch mit Punkt beginnende Dateien anzeigen<br />

…<br />

-l Alle Dateidetails anzeigen<br />

Die zweite Möglichkeit, Informationen zu einem Befehl zu<br />

28


Grundlagen<br />

Schritte<br />

bekommen, ist die Verwendung von man. Dies ist die Abkürzung<br />

für <strong>Handbuch</strong> (engl.: manual). Man gibt man gefolgt von dem jeweiligen<br />

Befehlsnamen ein und erhält die Hilfe zu diesem Befehl.<br />

Um die Hilfe für ls zu sehen, geben Sie man ls ein. Zum<br />

Navigieren auf der Seite verwendet man die Aufwärts- und Abwärts-Pfeiltasten<br />

oder – zum schnelleren Scrollen – die Bildnach-oben-<br />

und Bild-nach-unten-Tasten. Um nach einem Wort<br />

oder einer Formulierung auf der <strong>Handbuch</strong>seite zu suchen,<br />

geben Sie / und dann den jeweiligen Suchbegriff ein. Mit den<br />

Kommando /-l lassen Sie sich beispielsweise alle Stellen anzeigen,<br />

wo -l vorkommt. Mit der N-Taste und Shift+N kann man<br />

zwischen den Treffern vor und zurück navigieren.<br />

Da wir noch weitere Befehle einführen, wäre es gut, wenn Sie<br />

sich die Hilfe und die <strong>Handbuch</strong>seite ansehen und sich mit<br />

ihnen vertraut machen. Natürlich können Sie auch immer einen<br />

Befehl bei Google nachschlagen, falls Ihnen der Umgang mit<br />

der textbasierten Hilfe nicht so sehr liegt. Allerdings werden Sie<br />

schneller mit der Befehlszeile vertraut, wenn Sie mit dem Terminal<br />

arbeiten.<br />

Hilfefunktionen<br />

Nun kommt aber noch die schlechte Nachricht. Es kann nämlich<br />

manchmal knifflig sein, die richtigen Befehle zu finden,<br />

wenn man nicht weiß, wie sie heißen. Dann ist die man-Stichwortsuche<br />

eine nützliche Anwendung. Hierzu verwendet man<br />

den Parameter -k („keyword“).<br />

Um zum Beispiel nach allen Programmen zu suchen, die mit<br />

dem Browser Ihres Systems zu tun haben, führen Sie man -k<br />

browser aus. Sie werden sehen, dass dieser Befehl sowohl Programme<br />

der grafischen Oberfläche als auch Befehlszeilenkommandos<br />

auflistet. <strong>Das</strong> liegt daran, dass zwischen den beiden<br />

kein wirklicher Unterschied besteht. Sie können Fenster vom<br />

Terminal aus starten und manchmal sogar steuern.<br />

Falls Sie Iceweasel (eine spezielle Version von Firefox) auf<br />

Ihrem <strong>Pi</strong> installiert haben (dies gehört nicht zu den<br />

Man kann sich sogar Filme in der Befehlszeile ansehen. Um<br />

ein paar Klassiker zu streamen, geben Sie einfach telnet towel.<br />

blinkenlights.nl ein und holen Sie sich Popcorn.<br />

Tabulator-Vervollständigung<br />

Wenn man mit langen Dateinamen<br />

arbeitet, ist es anstrengend, sie jedesmal<br />

neu zu schreiben, wenn man einen<br />

Befehl mit Ihnen ausführen möchte.<br />

Um das zu erleichtern, gibt es im Terminal<br />

die Tabulator-Vervollständigung.<br />

Wenn man also mit der Eingabe eines<br />

Dateinamens beginnt und die Tabulator-<br />

Taste drückt, versucht das System, den<br />

restlichen Dateinamen zu ergänzen. Falls<br />

es nur einen Dateinamen gibt, der mit<br />

dem übereinstimmt, was bisher eingegeben<br />

wurde, wird der restliche Dateiname<br />

automatisch ergänzt (geben Sie cd /h<br />

ein, und drücken Sie die Tabulator-Taste).<br />

Falls es mehrere Dateinamen gibt,<br />

erfolgt die Vervollständigung nur so<br />

weit, wie diese übereinstimmen. Ein<br />

wiederholtes drücken der Tabulator-<br />

Taste zeigt die möglichen Optionen an<br />

(geben Sie cd /m ein, und drücken<br />

Sie die Tabulator-Taste zweimal).<br />

vorinstallierten Programmen), dann können Sie TuxRadar.com<br />

in einem neuen Reiter im geöffneten Iceweasel-Fenster mit dem<br />

Befehl iceweasel - -new-tab www.tuxradar.com öffnen.<br />

Hier noch in aller Kürze ein paar weitere nützliche Befehle:<br />

rm löscht eine Datei. mkdir erzeugt ein neues Verzeichnis. Mit<br />

cp kann man eine Datei an einen anderen Speicherort kopieren.<br />

Dieser Befehl benötigt zwei Parameter (für die Originaldatei<br />

und die neue Datei). cat gibt den Inhalt von einer oder mehreren<br />

Textdateien aus. Der Befehl nimmt beliebig viele Parameter<br />

und zeigt die Ausgabe direkt im Terminal an. less ist eine benutzerfreundlichere<br />

Möglichkeit, sich Texte anzusehen, man<br />

kann mit den Pfeiltasten rauf und runter scrollen. Um vom Programm<br />

zurück zur Befehlszeile zu gelangen, drücken Sie die<br />

Q-Taste. find ist ein nützliches Kommando, um Dateien auf<br />

Ihrem Computer zu suchen. Sie verwenden ihn im Format find<br />

location flags. Wenn Sie zum Beispiel alle Dateien auf Ihrem<br />

Computer finden möchten, die tags zuvor geändert wurden,<br />

führen Sie folgenden Befehl aus:<br />

find / -mtime 1<br />

Auf Seite 27 in diesem Heft finden Sie weitere Informationen<br />

zur Benutzung dieses und der anderen genannten Befehle.<br />

Mächtigere Funktionen<br />

Bis hierher hätte man die entsprechenden Funktionen auch mit<br />

der grafischen Benutzeroberfläche nutzen können, ohne sich<br />

Befehle und Parameter merken zu müssen, doch jetzt kommen<br />

wir zu den speziellen Stärken der Eingabe per Kommandozeile.<br />

Wir beginnen mit den sogenannten Wildcards. <strong>Das</strong> sind Platzhalter,<br />

die für beliebige andere Zeichen stehen können. Am besten<br />

lässt sich dies an einigen Beispielen veranschaulichen.<br />

Als Erstes erstellen wir dazu ein neues Verzeichnis und legen<br />

darin ein paar leere Dateien an (Letzteres geht ganz einfach mit<br />

dem Befehl touch, der eine leere Datei mit dem Namen eines<br />

jeden angehängten Parameters erzeugt).<br />

mkdir wildcards<br />

cd wildcards<br />

touch one two three four<br />

touch one.txt two.txt three.txt four.txt<br />

29


Grundlagen<br />

sudo<br />

Führen Sie ls aus, und schauen Sie nach, welche Dateien<br />

sich in der neuen Verzeichnisstruktur befinden. Es sollten acht<br />

sein.<br />

Die erste Wildcard, die wir verwenden, ist „*“. Dieser Platzhalter<br />

steht für eine beliebige Zeichenkette von null oder mehreren<br />

Zeichen. Verwendet man ihn alleine, zeigt er alle Dateien in<br />

der Verzeichnisstruktur auf. Probieren Sie es aus:<br />

ls *<br />

<strong>Das</strong> ist noch nicht besonders nützlich, doch wir können noch<br />

weitere Zeichen hinzunehmen. Was denken Sie? Wird *.txt<br />

funktionieren? Testen Sie, ob Sie richtig liegen:<br />

ls *.txt<br />

Was ist mit one*? Probieren Sie es auch hiermit.<br />

ls one*<br />

Die Wildcards können mit allen Befehlen der Kommandozeile<br />

verwendet werden. Sie sind besonders nützlich zum Sortieren<br />

von Dateien. Um alle .txt-Dateien in ein neues Verzeichnis zu<br />

kopieren, könnten Sie folgende Befehle ausführen:<br />

mkdir text-files<br />

cp *.txt text-files<br />

Ob alles geklappt hat, können wir folgendermaßen<br />

überprüfen:<br />

ls text-files/<br />

Der zweite Platzhalter, den wir kennenlernen ist „?“. Er steht<br />

für ein beliebiges einzelnes Zeichen. Was ergibt wohl:<br />

ls ???<br />

Raten Sie, und probieren Sie es einfach aus.<br />

Wir können auch Platzhalter für bestimmte Zeichen festlegen.<br />

[abc] steht für ein kleingeschriebenes A, B oder C. Was,<br />

denken Sie, zeigt uns der Befehl ls [ot]* an? Versuchen Sie es!<br />

ls [!ot]*<br />

Welchen Unterschied hat das Ausrufezeichen ausgemacht?<br />

Alles, was nicht mit einem kleingeschriebenem O oder T beginnt,<br />

sollte aufgelistet werden.<br />

man ist wahrscheinlich der wichtigste Befehl in jedem unixähnlichen System. Wenn man<br />

ihn versteht, versteht man auch jeden anderen Befehl. Nehmen Sie sich Zeit, um mit seinem<br />

Aufbau und seiner Sprache vertraut zu werden. <strong>Das</strong> wird Ihnen das Leben leichter machen.<br />

Verwenden Sie den sudo-Befehl, um zwischen dem normalen<br />

Benutzer „pi“ und dem Super-Anwender „root“ zu wechseln.<br />

Ausgabeumlenkung<br />

Die Befehle, die wir bisher verwendet haben, haben die entsprechenden<br />

Ergebnisse im Terminal angezeigt. Meistens ist das<br />

auch genau das, was wir beabsichtigen. Doch manchmal ist<br />

eine andere Ausgabeform hilfreicher. Unter Linux hat man noch<br />

zwei weitere Ausgabemöglichkeiten: in eine andere Datei oder<br />

ein anderes Programm.<br />

Um die Ausgabe in eine andere Datei umzulenken, verwendet<br />

man das Zeichen „>“, gefolgt von dem Dateinamen. Führen Sie<br />

folgende Befehle aus:<br />

ls > files<br />

cat files<br />

Sie werden sehen, dass eine neue Datei namens files erzeugt<br />

worden ist, die die Ergebnisse von ls enthält.<br />

Die Möglichkeit, die Ergebnisse an ein anderes Programm zu<br />

senden, ist eine weitere, wirklich nützliche Anwendung der<br />

Linux-Befehlszeile, da man hier eine Reihe von Befehlen zusammenfassen<br />

kann. Es gibt Befehle, die darauf ausgelegt sind,<br />

auf diese Art verkettet zu werden. Hier ein einfaches Beispiel<br />

dafür: Wenn Sie find / ausführen würden, würde Ihnen jede<br />

Datei Ihres Systems aufgelistet. Dies wäre eine sehr lange<br />

Liste von Dateinamen, die nicht auf eine Bildschirmseite passt.<br />

Statt uns das Ergebnis direkt auf dem Bildschirm ausgeben zu<br />

lassen, können wir jedoch die Liste an einen anderen Befehl<br />

senden, der sie lesefreundlicher darstellt. Hierzu können wir<br />

den less-Befehl verwenden, den wir weiter oben bereits kennengelernt<br />

haben. Führen Sie Folgendes aus:<br />

find / | less<br />

Weiterführende Quellen<br />

Sie kennen nun die Grundlagen der Eingabe per Befehlszeile.<br />

Dieses Rüstzeug sollte Ihnen für den Anfang genügen, und wir<br />

hoffen, dass Sie mit der Zeit die vielfältigen Möglichkeiten des<br />

Terminals für sich entdecken.<br />

Falls Sie mehr über die Benutzung der Befehlszeile erfahren<br />

möchten (was wir natürlich sehr empfehlen), gibt es hierzu eine<br />

Vielzahl von Quellen sowohl in gedruckter Form als auch online.<br />

Eine gute Einstiegsmöglichkeit bietet www.linuxcommand.org.<br />

Dort ist auch ein Link zu einer kostenlosen PDF-Version des<br />

Buches The Linux Command Line zu finden.<br />

Für die meisten Anwendungsfälle ist es für<br />

Rasperry-<strong>Pi</strong>-Nutzer ausreichend, im Home-Verzeichnis<br />

zu arbeiten (z.B. /home/pi). Man kann auch<br />

die meisten anderen Dateien ansehen, aber nicht<br />

ändern. <strong>Das</strong> Installieren von Software ist ebenfalls<br />

nicht möglich. Linux beinhaltet nämlich ein<br />

Berechtigungssystem, welches gewöhnliche<br />

Nutzer davor bewahrt, versehentlich Systemeinstellungen<br />

zu ändern. Möchte man jedoch<br />

Systemeinstellungen ändern, kann man<br />

/sudo nutzen und einen Befehl als Super-<br />

User (manchmal auch als „root“ bezeichnet)<br />

ausführen. Ein Super-User kann so ziemlich<br />

alles ausführen. Sie müssen einfach nur<br />

sudo vor den Befehl setzten. Zum Beispiel:<br />

sudo apt-get install synaptic<br />

Mit diesem Befehl wird das Paket synaptic installiert<br />

und für alle Benutzer zugänglich gemacht.<br />

30


Grundlagen<br />

Die wichtigsten Befehle im Überblick<br />

Navigation und Dateien<br />

df -h zeigt die freie Speicherkapazität des Gerätes an.<br />

pwd zeigt das Verzeichnis an, in dem man sich gerade<br />

befindet.<br />

cd Verzeichniswechsel. cd movies navigiert zum Verzeichnis<br />

movies, mit cd ~ gelangen Sie in Ihr Home-Verzeichnis, mit cd /<br />

zum Hauptverzeichnis und mit cd .. in die nächsthöhere<br />

Verzeichnisebene.<br />

ls Dateiliste für das aktuelle oder per Parameter angegebene<br />

Verzeichnis. ls movies listet die Dateien des Verzeichnisses<br />

movies auf, ls -a zeigt alle Dateien (auch die versteckten) an,<br />

und ls -l zeigt zusätzliche Informationen zu jeder Datei an.<br />

cp Kopieren. cp orig-file new-file kopiert orig-file zu new-file.<br />

wget Download von Dateien aus dem Internet. Um die<br />

Google-Homepage herunterzuladen, verwendet man<br />

wget www.google.com<br />

Dateien suchen<br />

find . Nützliche Parameter sind:<br />

-mtime zeigt alle Dateien an, die in den letzten<br />

Tagen geändert wurden. Anstelle von kann<br />

beispielsweise 2 (vor genau 2 Tagen), -2 (vor weniger als zwei<br />

Tagen) oder +2 (vor mehr als zwei Tagen) stehen.<br />

-name sucht Dateien mit dem Namen<br />

.<br />

-iname findet Dateien namens <br />

ohne Beachtung der Groß- und Kleinschreibung.<br />

-writable sucht alle Dateien, die beschreibbar sind.<br />

Es können auch Parameter kombiniert werden. Zum Beispiel<br />

listet find / -mtime -2 -writeable alle Dateien im Dateisystem<br />

auf, die vor weniger als 2 Tagen geändert wurden und für den<br />

aktuellen Benutzer beschreibbar sind.<br />

Fernzugriff<br />

ssh Loggen Sie sich auf einem entfernten Rechner über<br />

Secure Shell (SSH-Protokoll) ein. ssh pi@192.168.1.2 wird<br />

sich als Anwender „pi“ auf dem Computer mit der IP-Adresse<br />

192.168.1.2 einloggen. Beachten Sie, dass dies nur funktioniert,<br />

wenn auf dem Remote-Rechner ein SSH-Server läuft.<br />

scp Secure Copy. scp pi@192.168.1.2:/home/pi<br />

kopiert in das Verzeichnis /home/pi auf dem Rechner<br />

192.168.1.2, und scp pi@192.168.1.2:/home/pi/<br />

kopiert /home/pi/ von dem Rechner 192.168.1.2 in<br />

das aktuelle Verzeichnis. Achtung, dies ist nur möglich, wenn<br />

auf dem Remote-Rechner ein SCP-Server läuft.<br />

Wildcards<br />

* ist Platzhalter für eine beliebige Zeichenkette (auch leere).<br />

? ist Platzhalter für ein einzelnes Zeichen.<br />

[abc] ist Platzhalter für a, b oder c.<br />

[!abc] ist Platzhalter für alle Zeichen außer a, b oder c.<br />

[A-Z] ist Platzhalter für einen Buchstaben von A-Z<br />

(großgeschrieben).<br />

[A-z] ist Platzhalter für einen Buchstaben von A-z<br />

(klein- oder großgeschrieben).<br />

[eins, zwei] ist Platzhalter für die Wörter eins und zwei.<br />

Informationen über den Computer<br />

top zeigt das Programm an, das gerade die meiste CPU- und<br />

Speicherkapazität benötigt.<br />

uname zeigt Informationen zum Kernel an. uname -m zeigt<br />

Informationen zur <strong>Hardware</strong> an.<br />

lscpu gibt Informationen über die CPU aus.<br />

dmesg gibt Kernel-Meldungen über den Bildschirm aus (und<br />

kann hilfreich sein, um <strong>Hardware</strong>probleme zu identifizieren).<br />

Textdateien<br />

head gibt die ersten 10 Zeilen einer Textdatei auf dem Bildschirm<br />

aus. Mit dem Parameter -n kann man die Anzahl 10<br />

ändern Beispielsweise zeigt dmesg | head -n 15 die ersten<br />

15 Zeilen einer Kernel-Meldung an.<br />

tail zeigt die letzten 10 Zeilen einer Textdatei auf dem Bildschirm<br />

an. Der Parameter -n kann wie gehabt verwendet werden.<br />

Man kann auch Dateiänderungen mit dem Parameter -f („follow“)<br />

verfolgen. So zeigt tail -n 15 -f /var/log/syslog die letzten 15<br />

Zeilen der Log-Datei des Systems an und aktualisiert laufend die<br />

Ausgabe bei Änderungen.<br />

less ermöglicht das Scrollen innerhalb einer Textdatei.<br />

cat gibt den Inhalt einer Textdatei im Terminal aus.<br />

nano <strong>Das</strong> Programm Nano ist ein benutzerfreundlicher<br />

Befehlszeilen-Texteditor (Ctrl+X schließt das Programm<br />

und fragt ab, ob Änderungen gespeichert werden sollen).<br />

Besondere Tastenkombinationen<br />

Ctrl+C beendet jegliches Programm, das gerade im Terminal<br />

läuft.<br />

Ctrl+D sendet das Dateiendezeichen an jegliches Programm,<br />

das gerade im Terminal läuft.<br />

Ctrl+Shift+C kopiert ausgewählten Text in die Zwischenablage.<br />

Ctrl+Shift+V fügt den Text aus der Zwischenablage ein.<br />

Software installieren<br />

./configure Wenn man den Quellcode eines Programms entpackt,<br />

wird gewöhnlich ein neues Verzeichnis, das das Programm<br />

beinhaltet, erstellt. Wechseln Sie in dieses Verzeichnis und führen<br />

Sie ./configure aus, um zu kontrollieren, ob Ihr System über<br />

alles Nötige zum Kompilieren der Software verfügt.<br />

make kompiliert die Software.<br />

make install (benötigt sudo) verschiebt die gerade kompi lierte<br />

Software an einen geeigneten Ort im System, sodass man sie<br />

wie einen normalen Befehl ausführen kann.<br />

apt-get kann dazu verwendet werden, Software zu installieren<br />

oder zu deinstallieren. So wird per sudo apt-get install iceweasel<br />

das Programm Iceweasel (eine Variante von Firefox) installiert<br />

und per sudo apt-get purge iceweasel wieder entfernt.<br />

Mit apt-get update rufen Sie eine aktuelle Liste aller Datenpakete<br />

von der Repository-Datenbank ab (eine gute Idee, bevor Sie irgendetwas<br />

unternehmen), und apt-get upgrade führt ein Upgrade<br />

aller Datenpakete aus, die in der Repository-Datenbank eine neuere<br />

Version beinhalten.<br />

apt-cache search sucht in der Repository-Datenbank<br />

nach allen Paketen, die ein bestimmtes Stichwort<br />

enthalten.<br />

31


Grundlagen<br />

<strong>Das</strong> Dateisystem:<br />

Lernen Sie, wie Linux Dateien verwaltet und wie Sie zusätzliche Speichergeräte<br />

zu Ihrem <strong>Raspberry</strong> <strong>Pi</strong> hinzufügen.<br />

Mit dem nützlichen<br />

Befehl df -h<br />

kann man sich<br />

anzeigen lassen,<br />

welche Laufwerke<br />

gerade an den<br />

<strong>Raspberry</strong> <strong>Pi</strong> angeschlossen<br />

sind.<br />

<strong>Das</strong> Linux-Dateisystem ist unter dem Wurzelverzeichnis<br />

(engl. root directory) aufgehängt, welches durch einen<br />

Schrägstrich (/) symbolisiert wird. Wenn man das Dateisystem<br />

mit einem Haus vergleicht, dann entspricht / der Haustüre,<br />

durch die man ins Haus gelangt. Wir probieren das mal<br />

aus. Hierzu öffnen wir ein Terminal und geben Folgendes ein:<br />

cd /<br />

ls<br />

Uns werden daraufhin einige Dateien und Verzeichnisse ausgegeben.<br />

In unserer Metapher entsprechen die Verzeichnisse<br />

Türen zu weiteren Räumen. Der wichtigste Raum ist für die<br />

meisten Anwender ihr Home-Verzeichnis, das wir uns ansehen<br />

können, wenn wir folgende Befehle eingeben:<br />

cd /home<br />

ls<br />

Haben Sie den / vor home bemerkt? Dieser bedeutet, dass<br />

home sich im Wurzelverzeichnis (/) befindet. Dateipfade, die<br />

mit / beginnen, werden als absolute Pfade bezeichnet. Über<br />

den Befehl ls werden uns dann alle Dateien in /home angezeigt.<br />

Für jeden angelegten Benutzer auf Ihrem <strong>Raspberry</strong> <strong>Pi</strong><br />

sollte es hier ein eigenes Verzeichnis geben. Zum Verzeichnis<br />

des Benutzers pi gelangt man mit dem Befehl:<br />

cd pi<br />

Diesmal haben wir vor den Verzeichnisnamen kein / gesetzt.<br />

<strong>Das</strong> heißt, dass sich das Verzeichnis des Benutzers pi im aktuellen<br />

Verzeichnis befindet. In diesem Fall spricht man von<br />

einem relativen Pfad. Wir hätten auch den absoluten Pfad mit<br />

cd /home/pi aufrufen können.<br />

Wenn wir uns das Dateisystem als Gebäudekomplex mit vielen<br />

Zimmern vorstellen, so ist es wichtig zu wissen, dass sich<br />

nicht alle Verzeichnisse auf demselben Speichergerät befinden.<br />

Wir haben es also mit Zimmern in unterschiedlichen Gebäuden<br />

zu tun, die durch Gänge miteinander verbunden sind. Für den<br />

ungeübten Benutzer ist dies nicht zu erkennen. Im Fall eben<br />

hätte sich das Benutzerverzeichnis pi auf einem physisch anderen<br />

Laufwerk als home befinden können, und wir hätten es niemals<br />

bemerkt. Wem die Verzeichnisstruktur von Windows mit<br />

den getrennten Laufwerken vertraut ist, dem mag dies seltsam<br />

vorkommen, doch es sorgt für deutlich mehr Flexibilität.<br />

Um anzuzeigen, welche Geräte gerade an Ihr System<br />

angeschlossen sind, geben Sie Folgendes ein:<br />

df -h<br />

Es werden eine paar Zeilen ausgegeben, deren erste Spalte<br />

anzeigt, wo sich das Dateisystem befindet (dies ist nicht der<br />

Pfad, an dem das Speichergerät eingebunden wird – also die<br />

Tür in unserem Vergleich –, sondern die Datei für das interne<br />

Dateisystem). Es gibt zwei unterschiedliche Typen: diejenigen,<br />

die mit /dev/ beginnen, und welche, die anders anfangen.<br />

Die Letzteren stellen keine echten Geräte dar, sondern vom<br />

Betriebssystem erzeugte virtuelle Geräte, die virtuelle Dateien<br />

mit Systeminformationen beinhalten. Schauen Sie sich zum<br />

Beispiel einmal an, was sie unter /dev finden: für jede <strong>Hardware</strong><br />

Ihres Systems eine Datei, einschließlich aller Laufwerke.<br />

Daher haben die Ausgabezeilen, die sich auf physische Geräte<br />

beziehen, alle ein /dev/ in der ersten Spalte.<br />

Die Geräte, die mit /dev/ beginnen, werden wiederum in<br />

zwei Kategorien eingeteilt: solche, die mit /dev/mmcblk beginnen<br />

(das sind die auf einer SD-Karte), und solche, die mit<br />

/dev/sd beginnen (das sind die auf zusätzlichen Geräten).<br />

Da wir die SD-Karte belassen, wie sie von Raspbian eingestellt<br />

wurde, schauen wir uns einmal nur die mit /dev/sd Beginnenden<br />

an (Achtung, Sie finden nur Einträge, wenn Sie zusätzliche<br />

Speicher angeschlossen haben). Jedem Laufwerk wird<br />

ein Buchstabe, bei A beginnend, zugeordnet. /dev/sda ist demnach<br />

das erste Laufwerk, /dev/sdb das zweite usw. Zusätzlich<br />

wird jede Partition eines Laufwerks durchnummeriert.<br />

/dev/sda1 ist somit die erste Partition auf dem ersten Laufwerk<br />

und /dev/sdb3 ist die dritte Partition auf dem zweiten<br />

Laufwerk usw.<br />

Speicher hinzufügen<br />

Man kann seinen <strong>Raspberry</strong> <strong>Pi</strong> um zusätzlichen Speicher in so<br />

ziemlich jeder Form ergänzen, sofern der neue Speicher über<br />

einen USB-Anschluss verfügt. USB-Memory-Sticks und externe<br />

32


Grundlagen<br />

Speichergeräte<br />

Man kann alle möglichen<br />

externen Speichergeräte<br />

an den <strong>Raspberry</strong><br />

<strong>Pi</strong> anschließen, doch sie<br />

haben jeweils unterschiedliche<br />

Einschränkungen.<br />

Festplatten sind am gängigsten. Externe Festplatten sollten<br />

allerdings über eine eigene Stromversorgung verfügen, da der<br />

<strong>Raspberry</strong> <strong>Pi</strong> nicht dafür konzipiert ist, so viel Strom wie ein normaler<br />

Computer über USB zu liefern. Wenn die externe Festplatte<br />

also nur über einen USB-Anschluss und keinen externen<br />

Stromanschluss verfügt, wird sie wahrscheinlich nicht funktionieren.<br />

Mit einem USB-Hub mit externer Stromzufuhr kann man<br />

sich hier wiederum behelfen. Ein Speicherstick benötigt nicht<br />

so viel Strom und sollte über den USB-Anschluss des <strong>Pi</strong> funktionieren.<br />

Wenn Sie jedoch auch noch eine Maus und eine Tastatur<br />

verwenden möchten, benötigen Sie dennoch einen Hub, da<br />

es nur zwei USB-Anschlüsse gibt.<br />

Hier müssen wir jedoch darauf hinweisen, dass die USB-Anschlüsse<br />

des R<strong>Pi</strong> langsamer sind als bei den meisten Computern<br />

und man nicht die gleiche Übertragungsgeschwindigkeit erwarten<br />

darf. Besonders auffallen wird das bei USB 3.0-Geräten,<br />

die bei einem R<strong>Pi</strong> nur das Leistungsniveau von USB 2.0 erreichen<br />

und darum weit langsamer funktionieren. <strong>Das</strong> ist der<br />

Nachteil, der in Kauf genommen werden musste, um das Board<br />

so klein und preiswert gestalten zu können.<br />

Daten-Layout<br />

Bisher haben wir das Wort Dateisystem verwendet, um damit<br />

die Verzeichnisstruktur auf dem Computer zu benennen. Es gibt<br />

jedoch noch eine weitere Bedeutung: die Art und Weise, wie<br />

Daten physisch auf einem Speichermedium gespeichert werden.<br />

<strong>Das</strong> ist wichtig, da jedes Laufwerk mit einem bestimmten<br />

Dateisystem formatiert werden muss, bevor es funktioniert. Es<br />

gibt eine Reihe verschiedener Dateisysteme: die einen werden<br />

von Windows verwendet, die anderen von Mac OS X, und die<br />

nächsten von anderen Systemen. Die gute Nachricht ist, dass<br />

Linux mit fast allen kompatibel ist. Wenn man also ein Speichermedium<br />

sowohl mit dem <strong>Pi</strong> als auch mit einem anderen<br />

Computer, auf dem kein Linux läuft, verwenden möchte, so formatiert<br />

man den Speicher am besten auf dem anderen Computer.<br />

Wenn man es andersherum macht, muss man darauf achten,<br />

den richtigen Dateisystemtyp für den Computer zu wählen.<br />

Die meisten Speichergeräte sind mit FAT32 vorformatiert, was<br />

von fast allen Geräten gelesen werden kann. Hierbei besteht<br />

allerdings das Problem, dass sehr große Dateien nicht verwaltet<br />

werden können (die Grenze liegt bei 4 GB). Wenn Sie jedoch<br />

das Speichermedium nur mit Ihrem <strong>Raspberry</strong> <strong>Pi</strong> und anderen<br />

Linux-Geräten verwenden wollen, dann erhalten Sie die beste<br />

Leistung, wenn Sie es mit einem Linux-Dateisystem formatieren.<br />

<strong>Das</strong> bekannteste Format ist ext4.<br />

Wenn Sie das Speichergerät formatiert und angeschlossen<br />

haben, öffnen Sie ein Terminal und geben Sie folgenden Befehl<br />

ein:<br />

df -h<br />

Wurde eine Zeile ausgegeben? Wahrscheinlich nicht. <strong>Das</strong><br />

liegt daran, dass das Gerät zuerst eingebunden werden muss.<br />

Dies können wir im Terminal erledigen. Als Erstes benötigen<br />

wir einen „Mount-Point“. <strong>Das</strong> ist einfach ein Verzeichnis, das wir<br />

als „Eingangstür“ zu unserem Speichergerät benutzen. Es kann<br />

überall im Dateisystem liegen. Um die erste Partition des ersten<br />

Geräts in dem Verzeichnis data im Home-Bereich des<br />

Benutzers einzubinden, geben Sie folgende Befehle ein:<br />

cd ~<br />

mkdir data<br />

sudo mount /dev/sda1 data<br />

Natürlich wollen wir das nicht bei jedem Neustart unseres <strong>Pi</strong><br />

wiederholen, besonders dann nicht, wenn wir ihn ohne Tastatur<br />

und Monitor verwenden möchten. Daher automatisieren wir die<br />

Durchführung. Es gibt eine Datei, die Linux vorgibt, was es wo<br />

einbinden soll. Diese heißt fstab und befindet sich in /etc. Um<br />

sie in einem einfachen Befehlszeilen-Texteditor zu öffnen, geben<br />

Sie im Terminal Folgendes ein:<br />

sudo nano /etc/fstab<br />

Die Datei beinhaltet eine Zeile für jede Partition auf jedem<br />

eingebundenen Gerät. Jede Zeile besteht aus einer Serie von<br />

durch einen Tabulator getrennten Werten, die dem System vorgeben,<br />

was es ausführen soll. Damit unser Speichergerät beim<br />

Neustart automatisch eingebunden wird, geben Sie in einer<br />

neuen Zeile am Ende von fstab Folgendes ein (Achtung, das Verzeichnis<br />

data muss wie im Beispiel zuvor bereits angelegt sein):<br />

/dev/sda1 /home/pi/data<br />

33


Grundlagen<br />

Pakete: Software<br />

Erfahren Sie hier, wie der Paketmanager von Raspbian, apt-get, von Online-<br />

Repositorys Software herunterlädt und diese auf Ihrem System verwaltet.<br />

Falls Sie an das Windows-Betriebssystem gewöhnt sind, ist<br />

es für Sie vermutlich selbstverständlich, dass jede Software<br />

ihren eigenen Installer mitbringt, der die richtigen<br />

Dateien an die richtigen Orte kopiert. Linux arbeitet jedoch normalerweise<br />

nach einem anderen Prinzip. Unter Linux gibt es<br />

eine Systemkomponente, die man gemeinhin als Paketmanager<br />

bezeichnet. Der Paketmanager holt und verwaltet die Software,<br />

die Sie brauchen. Er verlinkt auf ein Repository („Lagerstätte“),<br />

von wo er alle Programme herunterlädt. Da Linux auf Open-<br />

Source-Software baut, werden Sie fast alles, was sie benötigen,<br />

kostenlos in diesen Repositorys finden. Sie müssen sich auch<br />

nicht darum kümmern, wo genau Sie die Installationsdateien<br />

finden: <strong>Das</strong> alles erledigt der Paketmanager für Sie.<br />

Es gibt mehrere Paketmanager für Linux. Raspbian benutzt<br />

apt-get, Arch hingegen einen anderen. Falls Sie also letztere<br />

Distribution auf Ihrem <strong>Raspberry</strong> <strong>Pi</strong> ausprobieren möchten,<br />

müssen Sie sich mit der Software pacman auseinandersetzen,<br />

die wir hier aber nicht behandeln.<br />

Bevor wir anfangen, weisen wir darauf hin, dass Sie Ihren<br />

<strong>Raspberry</strong> <strong>Pi</strong> mit dem Internet verbinden müssen. Da wir Software<br />

aus dem Internet herunterladen werden, ist eine Verbindung<br />

zum Internet für das Befolgen dieser Anleitung zwingend<br />

notwendig.<br />

apt-get ist ein Kommandozeilenprogramm, für das Sie ein<br />

Terminal verwenden müssen (mehr zur Kommandozeile auf<br />

Seite 24). Da die Verwaltung von Softwarepaketen das gesamte<br />

System betrifft, müssen alle Befehle mit einem vorangestellten<br />

sudo ausgeführt werden. Stellen Sie zunächst sicher, dass Sie<br />

die aktuelle Software in Ihrer Paketliste zur Verfügung haben.<br />

Führen Sie dazu folgenden Befehl aus:<br />

sudo apt-get update<br />

Da die gesamte Software über den Paketmanager verwaltet<br />

wird, kann er alle Programme auf dem Rechner aktualisieren.<br />

Sie müssen sich also nicht für jede Anwendung einzeln damit<br />

befassen. Um alle Updates für die gesamte installierte Software<br />

herunterzuladen und zu installieren, verwenden Sie den Befehl:<br />

sudo apt-get upgrade<br />

<strong>Das</strong> könnte ein Weilchen dauern, da Open-Source-Software<br />

dazu neigt, recht oft aktualisiert zu werden.<br />

Bei Linux installiert man – um in der Terminologie zu bleiben<br />

– keine Anwendungen, sondern sogenannte Pakete. Diese<br />

bestehen jeweils aus einem Satz Dateien, der zwar meistens<br />

einem Anwendungsprogramm entspricht, jedoch nicht immer.<br />

Ebenso gut kann es sich bei einem solchen Paket um Daten<br />

für ein Spiel, eine Dokumentation oder ein Plug-in handeln.<br />

Um mit apt-get Software zu installieren, müssen Sie den<br />

Namen des Pakets kennen, das Sie installieren möchten.<br />

Meist ist dieser offensichtlich, er muss aber vollständig richtig<br />

sein, damit das Paket heruntergeladen werden kann. Falls Sie<br />

sich nicht sicher sind, können Sie alle zur Verfügung stehenden<br />

Pakete mit apt-cache durchsuchen. Probieren Sie beispielsweise<br />

folgenden Befehl aus:<br />

apt-cache search iceweasel<br />

Diese Eingabe wird eine Liste von Paketen auswerfen, die mit<br />

dem gesuchten Webbrowser (Iceweasel ist eine spezielle Version<br />

von Firefox) zu tun haben. Um Iceweasel zu installieren, verwenden<br />

Sie folgendes Kommando:<br />

sudo apt-get install iceweasel<br />

Sie werden feststellen, dass apt-get Sie um die Zustimmung<br />

zur Installation einer Anzahl von Paketen fragt. Dabei handelt es<br />

sich um die sogenannten Abhängigkeiten. Iceweasel benötigt<br />

den Inhalt dieser Pakete, um zu funktionieren. Normalerweise<br />

müssen Sie sich über die angezeigten Abhängigkeiten nicht den<br />

Kopf zerbrechen – bestätigen Sie deren Installation einfach nur<br />

mit „Y“, und der Paketmanager wird alles andere für Sie erledigen.<br />

Allerdings gibt es Pakete, die eine große Anzahl von Abhängigkeiten<br />

aufweisen und somit viel Speicherplatz benötigen.<br />

Falls Ihre SD-Karte bereits relativ voll ist, sollten Sie gegebenenfalls<br />

vor der Installation Platz schaffen.<br />

Falls Sie Iceweasel und alle zugehörigen Pakete (sofern diese<br />

nicht von anderen Paketen benötigt werden) wieder deinstallieren<br />

möchten, erledigen Sie dies mit dem Befehl:<br />

sudo apt-get purge iceweasel<br />

Oft begegnen Sie Paketen, die ein -dev am Ende ihres Namens<br />

aufweisen. Diese brauchen Sie nur, wenn Sie planen,<br />

die Software selbst zu kompilieren. Normalerweise können Sie<br />

solche Pakete ignorieren. apt-get ist ein großartiges Werkzeug,<br />

lässt jedoch etwas an Benutzerfreundlichkeit zu wünschen<br />

übrig. Es gibt aber auch grafische Tools zur Paketverwaltung.<br />

Zwei davon sind Synaptic sowie der <strong>Raspberry</strong> <strong>Pi</strong> App Store<br />

(siehe auch Seite 37). Synaptic funktioniert wie apt-get, hat<br />

aber eine grafische Benutzeroberfläche. Sie können das Programm<br />

mit sudo apt-get install synaptic installieren und mit<br />

--where is synaptic starten. Im <strong>Raspberry</strong> <strong>Pi</strong> App Store finden<br />

Sie nicht nur freie Software wie mit apt-get und Synaptic, sondern<br />

auch kommerzielle Pakete, die Sie kaufen müssen. Der<br />

App Store ist auf Raspbian vorinstalliert und kann über das entsprechende<br />

Icon auf dem Desktop aufgerufen werden.<br />

34


Grundlagen<br />

sicher im Griff<br />

Weitere Informationen<br />

Synaptic<br />

Mit Synaptic können Sie alles erledigen, was Sie auch mit dem<br />

Kommando apt-get tun können, allerdings ist das grafische Interface<br />

etwas einfacher zu verwenden. <strong>Das</strong> zeigt sich vor allem<br />

beim Suchen von Paketen, da das Fenster die Ergebnisse übersichtlicher<br />

als das Terminal aufbereitet.<br />

<strong>Raspberry</strong> <strong>Pi</strong> App Store<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> App Store erlaubt es den Anwendern, die Software<br />

zu bewerten. So sehen Sie sofort, wie gut sie von anderen<br />

Nutzern eingeschätzt wird. Allerdings hat der App Store bei weitem<br />

nicht den Umfang von apt-get oder Synaptic.<br />

Software kompilieren<br />

Manchmal benötigen Sie Pakete, die Sie nicht in einem Repository<br />

finden und damit auch nicht mit apt-get installieren können.<br />

In diesem Fall müssen Sie die Software selbst kompilieren.<br />

Verschiedene Projekte verpacken ihre Software auf<br />

verschiedenen Arten, aber normalerweise funktioniert folgende<br />

Anleitung: Laden Sie sich den Quellcode von der Website des<br />

Projekts herunter und entpacken Sie ihn. Meist endet der Dateiname<br />

mit .tar.gz oder .tgz. Falls das zutrifft, entpacken Sie die<br />

Datei mit:<br />

tar zxvf <br />

Falls der Name der Datei mit .tar.bzip2 endet, ersetzen Sie<br />

zxvf durch xjf. <strong>Das</strong> sollte ein neues Verzeichnis anlegen, das<br />

Sie mit cd aufrufen. Hier hoffen wir darauf, dass eine Datei mit<br />

dem Namen INSTALL zu finden ist, die Sie mit less INSTALL<br />

lesen können. <strong>Das</strong> sollte Ihnen alles Nötige verraten, um mit<br />

der Installation fortfahren zu können. Oft (aber nicht immer) ist<br />

der Weg der folgende:<br />

./configure<br />

make<br />

sudo make install<br />

Die erste Zeile überprüft, ob auf Ihrem System alle notwendigen<br />

Abhängigkeiten vorhanden sind. Falls die Überprüfung fehlschlägt,<br />

müssen Sie sicherstellen, dass alle nötigen -dev-Pakete<br />

vorhanden sind.<br />

Falls sich alle Befehle ohne Fehler ausführen lassen, ist die<br />

Software installiert und bereit zur Verwendung. Dieser Weg ist<br />

aber wesentlich fehleranfälliger als die Benutzung eines Paketmanagers.<br />

apt-cache in<br />

einer Kommandozeile<br />

zeigt Ihnen<br />

eine Liste aller<br />

erhältlichen<br />

Pakete an.<br />

Synaptic stellt<br />

Ihnen ein einfach<br />

zu verwendendes<br />

Front-End für den<br />

apt-Paketmanager<br />

zur Verfügung.<br />

35


Grundlagen<br />

Add-ons für den<br />

<strong>Raspberry</strong> <strong>Pi</strong><br />

Entdecken Sie die Extras und Erweiterungen und werden Sie zum Bastler!<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> ist vermutlich das erfolgreichste<br />

IT-Produkt, das in den<br />

letzten zehn Jahren aus Großbritannien<br />

gekommen ist, allerdings wohl auch eines<br />

der am meisten missverstandenen. Viele Leute<br />

scheinen der Meinung zu sein, beim <strong>Raspberry</strong><br />

<strong>Pi</strong> handele es sich um nichts weiter als einen<br />

preisgünstigen Desktop-Computer. Wenn man<br />

sich allerdings die in dem Fall zusätzlich erforderliche<br />

Peripherie wie Monitor, Tastatur,<br />

Maus und SD-Karte zulegt, kommt man preislich<br />

fast an einen billigen Laptop heran – und<br />

hat dann auch noch einen Rechner mit im Vergleich<br />

dazu wesentlich weniger Leistung.<br />

Was ist es also, das den <strong>Raspberry</strong> <strong>Pi</strong> dennoch<br />

zu einem Schnäppchen werden lässt?<br />

Es ist der Formfaktor! <strong>Das</strong> Gerät ist klein, ist<br />

mit ein paar Batterien oder Solarzellen zu betreiben<br />

und besitzt überdies eine Reihe<br />

GPIO-<strong>Pi</strong>ns (Kontaktstifte mit integrierten<br />

Schaltkreisen zur Allzweckein- und -ausgabe).<br />

Diese Dreierkombination hat es im Computerbereich<br />

so noch nicht gegeben, jedenfalls nicht<br />

zu diesem ansprechenden Preis.<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> ist also nicht einfach ein<br />

neues Gerät, sondern eine vollkommen neuartige<br />

Geräteklasse, und das wird der Grund<br />

sein, dass vielen sein Zweck noch nicht so<br />

ganz klar ist. Allerdings bessert sich die Lage<br />

rapide, denn mit dem durchschlagenden Erfolg<br />

des <strong>Pi</strong> werden auch seine wahren Möglichkeiten<br />

immer mehr Menschen bewusst.<br />

Fast täglich, so kommt es einem vor, gibt es<br />

Meldungen über ein weiteres Gerät, das an<br />

den <strong>Pi</strong> angeschlossen werden kann und damit<br />

neue Funktionen und Features herauskitzelt.<br />

Viele dieser Geräte werden nicht von großen<br />

Firmen entwickelt, sondern von Bastlern und<br />

Hobbyschraubern, die eine Idee haben und sie<br />

in die Tat umsetzen.<br />

Auf den folgenden Seiten werfen wir einen<br />

Blick auf drei ganz besondere Add-ons: das<br />

Multifunktions-LED-Display <strong>Pi</strong> Lite, das <strong>Pi</strong>-Kameramodul<br />

und die GPIO-Erweiterungen von<br />

Quick2Wire.<br />

„Was ist es, das den <strong>Raspberry</strong> <strong>Pi</strong> zu<br />

einem Schnäppchen werden lässt?<br />

Es ist der Formfaktor!“<br />

36


Grundlagen<br />

<strong>Pi</strong> Lite<br />

Ein Multifunktions-LED-Display.<br />

Die Leute von Ciseco hatten einen interessanten Einfall:<br />

Was, wenn man eine Ladung LEDs auf eine Platine<br />

packen und eine simple Technik kreieren würde,<br />

diese anzusprechen? <strong>Das</strong> Ergebnis ist das <strong>Pi</strong> Lite mit 126<br />

roten Lämpchen, für die Zukunft ist auch eine Version mit<br />

weißen LEDs geplant. Damit lässt sich alles Mögliche anstellen.<br />

<strong>Das</strong> <strong>Pi</strong> Lite wird an die GPIO-<strong>Pi</strong>ns des <strong>Raspberry</strong> <strong>Pi</strong> angeschlossen<br />

und nimmt passgenau und platzsparend ein<br />

Stockwerk über der <strong>Pi</strong>-Platine Platz (siehe Abbildung).<br />

<strong>Das</strong> <strong>Pi</strong> Lite ist zwar kein Plug-and-Play-Gerät, doch es erfordert<br />

nur ein wenig Konfigurationsarbeit, bevor es bereit<br />

zum Einsatz ist. Eine Anleitung hierfür finden Sie auf<br />

http://bit.ly/1c0GOY1. Die Einrichtung dürfte eine Sache<br />

von zehn Minuten sein, allerdings benötigen Sie eine Netzwerkverbindung,<br />

um ein wenig Software herunterladen zu<br />

können. <strong>Das</strong> könnte sich bei einem <strong>Raspberry</strong> <strong>Pi</strong> Modell A<br />

als schwierig erweisen.<br />

Wenn Sie das <strong>Pi</strong> Lite eingerichtet haben, können Sie es<br />

über den seriellen Anschluss des <strong>Raspberry</strong> <strong>Pi</strong> ansteuern.<br />

Tippen Sie<br />

minicom -b9600 -o -D /dev/ttyAMA0<br />

in die Kommandozeile, und Sie erhalten eine Schnittstelle zu<br />

der LED-Platine. Alles, was Sie nun schreiben, scrollt als rote<br />

Lichtpunkte über das <strong>Pi</strong> Lite. <strong>Das</strong> ist an sich schon mal cool,<br />

aber mit dem <strong>Pi</strong> Lite lässt sich noch viel mehr machen. Statt<br />

Text können Sie auch Befehle an das Gerät senden. Die Befehle<br />

beginnen immer mit drei Dollarzeichen, so wie in diesem<br />

Beispiel:<br />

$$$ALL,ON<br />

Mit diesem Kommando werden alle <strong>Pi</strong>xel auf dem <strong>Pi</strong> Lite aktiviert.<br />

Es lassen sich außerdem vertikale und horizontale Linien<br />

darstellen und die <strong>Pi</strong>xel auch einzeln ansprechen. Letzteres<br />

könnte dann etwa so aussehen (1 = an, 0 = aus):<br />

$$$F00000000000000000000011100001111111001111111011<br />

111111111110111111110111101100011001100011000000000<br />

0000000000000000000000000000<br />

In diesem Modus lassen sich Bilder erzeugen, wobei es aber<br />

sinnvoll ist, dies mithilfe von Skripten zu automatisieren. Da<br />

die gesamte Kommunikation mit dem <strong>Pi</strong> Lite über den seriellen<br />

Anschluss des <strong>Raspberry</strong> <strong>Pi</strong> läuft, können Sie es mit jeder<br />

Sprache ansteuern, die die serielle Kommunikation<br />

unterstützt.<br />

Für den Einstieg am besten geeignet ist vermutlich die Programmiersprache<br />

Python (mit dem seriellen Modul). Auch<br />

hierzu gibt es direkt von Ciseco einige einführende Beispiele:<br />

http://bit.ly/19C3Sve.<br />

Da das <strong>Pi</strong> Lite über einen seriellen Anschluss angesteuert<br />

wird, ist es sehr portabel und lässt sich über jedes Gerät mit<br />

entsprechenden Fähigkeiten betreiben, also außer dem<br />

Rasp berry <strong>Pi</strong> auch über einen Linux-<strong>PC</strong> oder fast jeden anderen<br />

Computer (gegebenenfalls per USB-FTDI-Verbindung).<br />

Eventuell müssen Sie dafür zum Lötkolben greifen.<br />

Testmöglichkeit vor dem Kauf<br />

Falls Sie sich erst einmal anschauen möchten, wie das <strong>Pi</strong> Lite<br />

funktioniert, bevor Sie eine Kaufentscheidung treffen, können<br />

Sie den von Ciseco unter http://bit.ly/14Li3d4 zur Verfügung<br />

gestellten Emulator nutzen.<br />

<strong>Das</strong> <strong>Pi</strong> Lite hat übrigens noch ein weiteres Ass im Ärmel:<br />

Es betreibt die LEDs mit einem ATMEGA-Chip, der zur selben<br />

Familie gehört wie die Prozessoren, die in den beliebten Arduino-Boards<br />

verbaut werden, und es wird mit einem Arduino-Bootloader<br />

ausgeliefert. Mit anderen Worten, Sie können<br />

den Mikrocontroller auf dem Bord beliebig programmieren.<br />

Sie könnten das <strong>Pi</strong> Lite sogar allein für sich, ohne Anschluss<br />

an irgendeinen anderen Rechner, betreiben. Da die<br />

Platine Zugang zu den fünf Analog-Inputs des ATMEGA gewährt,<br />

können Sie diese mit ein bisschen Programmierarbeit<br />

für Ihr Projekt nutzbar machen. Dies ist etwas komplexer als<br />

die Standardverwendung des <strong>Pi</strong> Lite, aber es ist ein tolles Beispiel<br />

dafür, wie ein einzelnes Stück <strong>Hardware</strong> dabei helfen<br />

kann, eine breite Palette technischer Fähigkeiten zu<br />

entwickeln.<br />

Laufschriften,<br />

Benutzerschnittstelle<br />

im Stil der<br />

1980er Jahre, die<br />

Digitalkamera<br />

mit der niedrigsten<br />

Auflösung<br />

der Welt – was<br />

werden Sie mit<br />

dem <strong>Pi</strong> Lite<br />

anstellen?<br />

37


Grundlagen<br />

Kameramodul<br />

Fotografieren mit dem <strong>Pi</strong>.<br />

Hier ist zu<br />

sehen, wie das<br />

Kameramodul<br />

per Flachbandkabel<br />

mit dem<br />

<strong>Raspberry</strong> <strong>Pi</strong><br />

verbunden wird.<br />

Bevor wir darüber sprechen, was das Kameramodul<br />

kann, sollten wir vielleicht darüber sprechen, was es<br />

nicht kann: Falls Sie nach einer billigen Webcam Ausschau<br />

halten, mit der Sie Videotelefonate per Skype führen<br />

können, ist das <strong>Pi</strong>-Kameramodul nicht das Richtige für Sie.<br />

Allein schon, weil Skype sowieso nicht auf dem Gerät läuft.<br />

<strong>Das</strong> Kameramodul lässt sich einfach bedienen, jedoch nicht<br />

im Sinne von „einstöpseln und Grafik-Tools benutzen“ – es<br />

handelt sich vielmehr um eine programmierbare Kamera.<br />

<strong>Das</strong> Kameramodul ist mit einer Flachbandschnittstelle<br />

ausgestattet, die beim <strong>Raspberry</strong> <strong>Pi</strong> in den vertikal angeordneten<br />

Anschluss zwischen dem Ethernet-Port (beziehungsweise<br />

der entsprechenden Aussparung beim Modell A) und<br />

dem HDMI-Port gesteckt wird. Wenn das Flachband eingerastet<br />

ist, prüfen Sie, ob Sie die neueste Version von Raspbian<br />

installiert haben, und zwar mit folgendem Kommando:<br />

sudo apt-get update<br />

sudo apt-get upgrade<br />

sudo rpi-update<br />

Lassen Sie danach raspi-config laufen, und achten Sie darauf,<br />

dass die Kamera aktiviert ist. Zuletzt führen Sie einen<br />

Neustart durch, und schon kann es losgehen. Die Steuerung<br />

der Kamera basiert auf zwei Befehlen, raspistill und raspivid.<br />

Mit dem ersten nehmen Sie Fotos, mit dem zweiten Videos<br />

auf. Um einen Schnappschuss zu machen, tippen Sie:<br />

raspistill -o image.jpg<br />

<strong>Das</strong> ist natürlich nur der erste Anfang, denn spannend wird<br />

es dadurch, dass Sie die Befehle – die ja direkt per Kommandozeile<br />

eingegeben werden – in Ihre Programme integrieren<br />

können. Falls Sie beispielsweise stets unsicher sind, welchen<br />

Weißabgleich Sie verwenden sollen, können Sie alle zusammen<br />

verwenden, etwa mit folgendem Python-Skript:<br />

from subprocess import call<br />

for awb in [‘off’,’auto’,’sun’,’cloud’,’shade’,’tungsten’,’fluoresce<br />

nt’,’incandescent’,’flash’,’horizon’]:<br />

call([“raspistill -n -awb “ + awb + “ -o image” + awb + “.jpg”],<br />

shell=True)<br />

Wie Sie sehen, können Sie das Kameramodul aus Python heraus<br />

kontrollieren, obwohl keine Python-Sprachanbindung<br />

vorliegt, nämlich mithilfe eines System Calls. Dies funktioniert<br />

mit den meisten Programmiersprachen, daher können<br />

Sie beinahe beliebig draufloshacken. Da alle Optionen als<br />

Kommandozeilen-Switch realisiert werden können, ist es<br />

recht einfach, die gewünschten Optionen in den System Call<br />

einzubauen. Wie wäre es mit einem Stop-Motion-Cartoon?<br />

raspistill -ifx cartoon -ISO 800 -tl 100 -t 10000 -w 300 -h 300<br />

-o test_%04d.jpg<br />

Hier werden diverse Kommandozeilenoptionen benutzt. -ifx<br />

steht für Image Effects, also Bildeffekte, und bietet etliche<br />

Möglichkeiten. Im Beispiel werden die Aufnahmen im Cartoon-Stil<br />

gerendert. Mit -ISO legen Sie die Filmempfindlichkeit<br />

fest. Mit -t1 wird die Unterbrechungszeit in Millisekunden<br />

eingestellt und mit -t die Gesamtzeit des Aufnahmezyklus. -w<br />

und -h stehen für Breite und Höhe des Bildes in <strong>Pi</strong>xeln, und -o<br />

bezeichnet den Dateinamen des Fotos (wobei _%04d eine<br />

Zahl darstellt, die mit jedem Bild hochgezählt wird).<br />

Um sich eine vollständige Liste aller Optionen der Kamera<br />

anzeigen zu lassen, geben Sie einfach raspistill in die Kommandozeile<br />

ein. Einige der Optionen erfordern für den sinnvollen<br />

Einsatz ein wenig Erfahrung im Fotografieren.<br />

Nun kommen wir zur Videofunktion. Mit dem Befehl raspivid<br />

können Sie eine Aufnahme anfertigen:<br />

raspivid -t 5000 -o video.h264<br />

Auch bei der Videofunktion haben Sie etliche Optionen, die<br />

den Foto-Optionen ähneln.<br />

Im Internet sind Anleitungen und Vorschläge zu einigen interessanten<br />

Projekten mit dem <strong>Pi</strong>-Kameramodul zu finden.<br />

Wie wäre es etwa mit einer Gesichtserkennung mithilfe von<br />

OpenCV? Näheres finden Sie unter http://bit.ly/1ap4S7G.<br />

Andere Kameras<br />

Webcam oder DSLR anschließen<br />

Bislang ist die offizielle <strong>Raspberry</strong>-<strong>Pi</strong>-Kamera das einzige<br />

Kameramodul, das sich mit dem vertikalen Anschluss<br />

verbinden lässt. Allerdings kann der <strong>Raspberry</strong> <strong>Pi</strong> auch via<br />

USB eine Kamera ansprechen, und hier sind die Möglichkeiten<br />

weitaus größer. Nicht alle Webcams werden funktionieren,<br />

aber es sind bereits mehr, als auf der Liste unter<br />

http://elinux.org/R<strong>Pi</strong>_USB_Webcams verzeichnet<br />

sind.<br />

Auch gewöhnliche Digitalkameras können Sie mithilfe<br />

von gPhoto2 ansteuern. Die meisten aktuellen Modelle<br />

werden bis zu einem gewissen Grad unterstützt, aber oft<br />

stehen nicht alle Features zur Verfügung (beispielsweise<br />

Fernsteuerung). Bilder herunterladen geht aber bei so<br />

ziemlich jeder Kamera. Weitere Infos erhalten Sie auf<br />

www.gphoto.org und www.gphoto.org/doc/remote/.<br />

38


Grundlagen<br />

GPIO-Expander von Quick2Wire<br />

Zusätzliche Anschlüsse für den <strong>Raspberry</strong> <strong>Pi</strong>.<br />

Ein Hauch von<br />

Retro-Schick<br />

dank bunter<br />

Flachbandkabel.<br />

Allerdings lassen<br />

sich einige<br />

Gehäuse für<br />

den <strong>Raspberry</strong><br />

<strong>Pi</strong> nicht damit<br />

kombinieren.<br />

Eins der genialsten Features des <strong>Raspberry</strong> <strong>Pi</strong> sind die<br />

direkt zugänglichen GPIO-<strong>Pi</strong>ns, die den Anschluss beliebiger<br />

Schaltkreise ermöglichen. Diese Kontaktstifte<br />

sind einfach zu benutzen und einfach zu verstehen: Mit einer<br />

einzigen Befehlszeile in Python oder Bash lassen sie sich einund<br />

ausschalten oder kann Input ausgelesen werden.<br />

Allerdings gibt es auch einige Unzulänglichkeiten bei den<br />

GPIO-<strong>Pi</strong>ns: So sind nicht alle <strong>Pi</strong>ns tatsächlich benutzbar, es<br />

existieren keine Analog-Inputs und -Outputs, und die Kontaktstifte<br />

sind sehr empfindlich und können den gesamten<br />

<strong>Raspberry</strong> <strong>Pi</strong> zerstören, wenn etwa die falsche Spannung angelegt<br />

wird.<br />

Mehrere Firmen haben Produkte entwickelt, um hier Abhilfe<br />

zu schaffen. So gibt es etwa von Ciseco das Slice of <strong>Pi</strong> –<br />

ein Board mit Zugriff auf 16 GPIOs, die geschützt sind und sowohl<br />

mit 3 V als auch 5 V arbeiten. <strong>Das</strong> <strong>Pi</strong>Face fügt ein paar<br />

nützliche Features wie Knöpfe, LEDs und Relays (zum Beispiel<br />

zur Motorsteuerung) hinzu. <strong>Das</strong> Gertboard bietet ein<br />

breites Spektrum an Input- und Output-Lösungen, und man<br />

kann sogar ein Arduino anschließen und die Anschlüsse<br />

damit steuern (allerdings erfordert dies einiges Programmieren<br />

in C).<br />

GPIO-Erweiterung<br />

Besonderes Augenmerk möchten wir hier auf die Boards von<br />

Quick2Wire legen. Quick2Wire bietet eine Platine mit Schnittstellen<br />

für die seriellen Datenbusse I2C und SPI an, bei der<br />

ein Schutzmechanismus für den <strong>Raspberry</strong> <strong>Pi</strong> sowie Spannungswählschalter<br />

enthalten sind. Auch Boards mit GPIO-<br />

Ports und analogen Input- und Output-Anschlüssen sind<br />

„Es gibt eine Fülle von<br />

Zubehör und Erweiterungen<br />

für den <strong>Raspberry</strong> <strong>Pi</strong><br />

auf dem Markt.”<br />

erhältlich. Die Platinen können sogar in Reihe geschaltet werden.<br />

Bei den angebotenen Sets muss man selbst eine Menge<br />

Lötarbeiten durchführen, doch danach lassen sich die Boards<br />

einfach per Flachbandkabel anschließen.<br />

Doch auch auf der Softwareseite ist noch einiges an Arbeit<br />

erforderlich, bis die Quick2Wire-Boards mit dem <strong>Raspberry</strong><br />

<strong>Pi</strong> laufen. Unter Umständen müssen einzelne Kernelmodule<br />

konfiguriert werden. Unter http://quick2wire.com/<br />

articles/beta-kit finden Sie eine Anleitung. Diese ist jedoch<br />

unvollständig, darum konsultieren Sie auch https://github.<br />

com/quick2wire/quick2wire-python-api – dort finden Sie<br />

den Ort der Python-Bibliothek. Nach geglückter Installation<br />

des Quick2Wire-Boards kann man mithilfe von Python spannende<br />

Dinge damit anstellen.<br />

Welches der hier genannten GPIO-Zubehöre am besten für<br />

Ihr Projekt geeignet ist, hängt von den jeweiligen Erfordernissen<br />

ab. <strong>Das</strong> Slice of <strong>Pi</strong> von Ciseco ist ein preisgünstiges Produkt,<br />

das Ihren <strong>Raspberry</strong> <strong>Pi</strong> in puncto GPIO-Verwendung<br />

schützt, das <strong>Pi</strong>Face eignet sich besonders gut zum allgemeinen<br />

Experimentieren im Bereich des Physical Computing,<br />

und die Platinen von Quick2Wire sind unglaublich nützlich,<br />

wenn Sie I2C oder SPI benötigen, um Peripheriegeräte und<br />

Port-Expander in Reihe zu schalten.<br />

Noch mehr Extras<br />

Zubehör und Ausbausets<br />

Derzeit gibt es eine überwältigende Fülle von<br />

Zubehör und Erweiterungen für den <strong>Raspberry</strong> <strong>Pi</strong><br />

auf dem Markt, beispielsweise von Adafruit<br />

(www.adafruit.com/distributors/) oder <strong>Pi</strong>moroni.<br />

Neben den allgemeinen Zubehörprodukten gibt es auch<br />

viele speziellere Dinge. Als Beispiel sei das faszinierende<br />

Brew<strong>Pi</strong> (brewpi.com) genannt, mit dessen Hilfe man<br />

selber Bier brauen kann. Sogar ein Arcade-Automat<br />

namens <strong>Pi</strong>cade ist in Vorbereitung; die zugehörige<br />

Kickstarter-Kampagne wurde erfolgreich abgeschlossen.<br />

39


Projekte<br />

40


Projekte<br />

Projekte<br />

Der erste Schritt beim arbeiten mit dem<br />

<strong>Raspberry</strong> <strong>Pi</strong> ist die Wahl des Betriebssystems.<br />

Es folgt die Wahl eines Projektes, denn der <strong>Pi</strong><br />

soll ja auch Nutzen bringen. Vielleicht haben Sie ja<br />

sogar Muße, selbst eigene Projekte anzugehen?<br />

Betriebssysteme für den <strong>Raspberry</strong> <strong>Pi</strong>.......................................42<br />

Betriebssystem: Raspbian....................................................................48<br />

Zünde den <strong>Raspberry</strong>-Booster...........................................................54<br />

Arch Linux...........................................................................................................62<br />

System: Eigene Distribution.................................................................66<br />

XBMC enthüllt.................................................................................................70<br />

Auto-Backups per Bash-Skript............................................................74<br />

dnsmasq: DNS servers...........................................................................78<br />

Syslog: Loggen per E-Mail.....................................................................80<br />

Desktop: Eigene Schreibtische.........................................................82<br />

41


Roundup Projekte<br />

Office suites<br />

Im Vergleich<br />

Betriebssysteme für<br />

den <strong>Raspberry</strong> <strong>Pi</strong><br />

Wir stellen Ihnen eine feine Auswahl empfehlenswerter<br />

Betriebssysteme für Ihren <strong>Raspberry</strong> <strong>Pi</strong> vor.<br />

<strong>Das</strong> sind unsere<br />

Testkriterien<br />

Es gibt zwei Modelle des <strong>Raspberry</strong><br />

<strong>Pi</strong>, das Modell A und das Modell B,<br />

und vom Modell B wiederum zwei<br />

Versionen – eine ältere mit<br />

256 MB und eine neuere mit<br />

512 MB Speicher. Um einen gründlichen<br />

Blick auf die unterschiedlichen<br />

Betriebssysteme werfen zu<br />

können, haben wir diese jeweils auf<br />

eine SD-Karte mit 4 GB Speicher<br />

installiert und mit beiden Versionen<br />

von Modell B ausprobiert.<br />

Im Rahmen unseres Tests prüfen<br />

wir die Installation, die vorinstallierte<br />

Software, die Medienwiedergabe<br />

„out of the box“ sowie das Design<br />

und die Handhabung. Daneben<br />

sind die Quellcode-Offenheit des<br />

jeweiligen Betriebssystems sowie<br />

dessen Community weitere Kriterien.<br />

Wir schauen uns das Thema<br />

zudem aus der Sicht von Nutzern an,<br />

die noch nicht mit Linux vertraut sind.<br />

Unsere<br />

Auswahl<br />

Raspbian<br />

Risc OS<br />

Plan 9<br />

Android<br />

Arch<br />

<strong>Das</strong> Phänomen <strong>Raspberry</strong> <strong>Pi</strong><br />

(R<strong>Pi</strong>) scheint nicht aufzuhalten<br />

zu sein, wie eine Lokomotive<br />

rast es vorwärts und erkämpft<br />

sich einen Platz in den Annalen. Kein<br />

Wunder: Die <strong>Hardware</strong> des Computers<br />

ist genau auf die Nutzerbedürfnisse<br />

zugeschnitten, der Preis lässt<br />

keine Wünsche offen, und die Vielseitigkeit<br />

von Linux rundet das Ganze<br />

perfekt ab.<br />

Die meisten R<strong>Pi</strong>-Neukäufer installieren<br />

wie auf der offiziellen Website der<br />

<strong>Raspberry</strong> <strong>Pi</strong> Foundation empfohlen<br />

das Betriebssystem Raspbian (eine<br />

Linux-Distribution) auf ihrem Rechner.<br />

Damit können sie dann zum Beispiel<br />

den armen kleinen R<strong>Pi</strong> passend programmieren<br />

und einrichten und ihn an<br />

einem Wetterballon befestigt zum äußeren<br />

Rand der Atmosphäre hinaufschicken.<br />

Viele Nutzer des <strong>Raspberry</strong> <strong>Pi</strong> wissen<br />

jedoch vermutlich gar nicht, dass<br />

es außer Raspbian noch eine Menge<br />

anderer Betriebssysteme für ihren<br />

Computer gibt. Diesen Nutzern möchten<br />

wir auf den folgenden Seiten eine<br />

feine Auswahl verschiedener Systeme<br />

vorstellen.<br />

„Viele Nutzer wissen nicht, dass es außer<br />

Raspbian noch viele andere Betriebssysteme<br />

für ihren Computer gibt.“<br />

42


Projekte<br />

Installation<br />

Einfach oder kompliziert?<br />

Wie man ein Abbild (Image)<br />

eines Betriebssystems installiert,<br />

ist auf der Webseite<br />

elinux.org/R<strong>Pi</strong>_Easy_SD_Card_Setup<br />

gut dokumentiert. Dort finden Sie<br />

alles Notwendige, um das Image auf<br />

die SD-Karte zu ziehen. Der Vorgang<br />

ist schnell erledigt. Anschließend setzen<br />

Sie die Speicherkarte ein, schalten<br />

den Strom ein, und der Spaß kann<br />

beginnen.<br />

Die fünf von uns getesteten Betriebssysteme<br />

haben alle ihre Eigenheiten,<br />

wenn es darum geht, dem<br />

Nutzer eine grafische Oberfläche<br />

(GUI) während der Installation zu bieten.<br />

Eine GUI ist an sich nicht zwingend<br />

notwendig bei der Installation,<br />

hilft aber insbesondere Linux-Neulingen.<br />

In der Disziplin, neue Nutzer behutsam<br />

an Linux heranzuführen, war<br />

Raspbian einst einsame Spitze, doch<br />

die anderen Systeme holen allmählich<br />

auf.<br />

Nehmen wir hier Risc OS als Beispiel:<br />

Ist es einmal auf der SD-Karte<br />

und gebootet, sehen wir sogleich eine<br />

farbenfrohe und freundliche GUI mit<br />

detaillierten Benachrichtigungen über<br />

den Bootvorgang und das Setup. Von<br />

dort aus starten Sie die Konfiguration<br />

und führen Änderungen aus, falls<br />

gewünscht.<br />

Bei Arch Linux für R<strong>Pi</strong> sieht die<br />

Sache schon anders aus. Nach dem<br />

Booten finden Sie sich in einer Terminal-Umgebung<br />

wieder. Dort sollen Sie<br />

das Betriebssystem herunterladen, installieren<br />

und einrichten. Wenn Sie<br />

Arch erst einmal eingerichtet haben,<br />

dann ist es eines der besten verfügbaren<br />

Betriebssysteme. Es sind jedoch<br />

einige Kniffe nötig, bis Sie zum fertigen<br />

Desktop kommen.<br />

Android für den R<strong>Pi</strong> nimmt allmählich<br />

Gestalt an. Ist das System hochgefahren,<br />

sehen Sie den offiziellen<br />

Sperrbildschirm von Android. Darauf<br />

folgt die konventionelle Android-Oberfläche,<br />

wie viele Smartphone- und Tablet-Nutzer<br />

sie kennen. <strong>Das</strong> R<strong>Pi</strong>-Android<br />

hat noch einige Bugs und stürzt<br />

öfters ab. Dazu ist es langsam, fast<br />

ungeeignet für die 256-MB-Version<br />

Raspbian ließ sich einst mit Abstand am einfachsten installieren.<br />

Doch der Wettbewerb scheint aufgeholt zu haben.<br />

des R<strong>Pi</strong>. Auf dem neueren Modell läuft<br />

es ein wenig besser.<br />

Plan 9 bietet eine effektive Benutzeroberfläche<br />

und ist gut dokumentiert,<br />

fordert aber eine steile Lernkurve<br />

vom Nutzer.<br />

Raspbian bietet ein textbasiertes<br />

Menü beim Bootvorgang. Sie können<br />

das System konfigurieren, SSH-Zugriff<br />

aktivieren und das System automatisch<br />

in die nutzerfreundliche<br />

LXDE-GUI booten lassen.<br />

Wir empfehlen Raspbian oder Risc<br />

OS für Einsteiger und Arch für<br />

Fortgeschrittene.<br />

Wertung<br />

Raspbian<br />

Risc OS<br />

Plan 9<br />

Android<br />

Arch<br />

Bei Raspbian<br />

gibt es eine<br />

vertraute und<br />

intuitive<br />

Desktop-GUI.<br />

Vorinstallierte Software<br />

Welches Zubehör wird mitgeliefert?<br />

Die Softwarepakete der R<strong>Pi</strong>-Betriebssysteme<br />

variieren stark<br />

und sind häufig der Grund, sich<br />

für oder gegen ein bestimmtes System<br />

zu entscheiden. Natürlich sollten<br />

Sie nichts zu Komplexes erwarten<br />

Beeindruckend, was diese Kategorie im Menü von<br />

Arch bereithält.<br />

– es handelt sich in allen Fällen um ein<br />

Betriebssystem, das auf einer SD-Karte<br />

läuft und von einem Rechner befeuert<br />

wird, der die Größe einer Kreditkarte<br />

und im Vergleich zu einem<br />

Desktop-Computer minimale Ressourcen<br />

hat. Trotzdem:<br />

Während Office-<br />

Anwendungen,<br />

Multimedia und Grafikbearbeitung<br />

Standard<br />

bei gewöhnlichen<br />

Linux-Paketen<br />

sind, waren wir überrascht,<br />

welches Zu<br />

behör uns unsere<br />

Auswahl an R<strong>Pi</strong>-<br />

Betriebssystemen<br />

bescherte.<br />

Wie erwartet führt<br />

Raspbian das Feld<br />

mit reichlich<br />

Standard-Software an. Risc OS liegt<br />

nicht weit zurück. Wenn Sie für gut<br />

40 Euro das Nut<strong>Pi</strong>-Paket kaufen, bekommen<br />

Sie zudem einen vollausgestatteten<br />

<strong>Raspberry</strong>-<strong>Pi</strong>-Desktop mit<br />

Office-Suite, Webbrowser und Messenger.<br />

Arch bringt Sie wie bereits erwähnt<br />

zu einem Terminal. Wenn Sie<br />

die richtigen Kommandos kennen,<br />

dann können Sie sich ein ähnlich umfangreiches<br />

Angebot wie auf einem<br />

Desk top-Computer zusammenstellen.<br />

R<strong>Pi</strong>-Android sorgte für eine negative<br />

Überraschung. Es gab zwar eine<br />

vernünftige Auswahl an Medien-Software,<br />

dafür jedoch keine Office-App.<br />

Plan 9 ist eher freudlos. Einmal bis<br />

zum Rio-Desktop vorgestoßen, fanden<br />

wir wenig vor, mit dem wir effektiv<br />

arbeiten konnten. Einsteigern dürfte<br />

es ähnlich ergehen.<br />

Wertung<br />

Raspbian<br />

Risc OS<br />

Plan 9<br />

Android<br />

Arch<br />

Wenn Sie für<br />

das Nut<strong>Pi</strong>-Paket<br />

zahlen, dann<br />

können Sie mit<br />

Risc OS kaum<br />

etwas falsch<br />

machen.<br />

43


Projekte<br />

Design und Handhabung<br />

Aussehen und Benutzerfreundlichkeit ist nicht alles? Oh doch!<br />

Desktop-Effekte sind für viele Linux-Nutzer ein heimliches<br />

Laster. Obwohl Linux allgemein den Ruf eines<br />

schlanken, funktionalen Systems besitzt, installieren<br />

etliche Anwender rotierende 3D-Objekte, Feuer-Effekte und<br />

anderen grafischen Schnickschnack. Es ist natürlich persönlicher<br />

Geschmack, aber irgendwann ist die Nutzerfreundlichkeit<br />

vor lauter Grafikeffekten dahin, Stichwort Windows Vista.<br />

Bedenken Sie dies also auch bei Ihrem Betriebssystem für<br />

den <strong>Raspberry</strong> <strong>Pi</strong>: Sie tauschen stets ein wenig der begrenzten<br />

Leistung gegen optischen Komfort. Wir schauen uns hier<br />

an, wie die Systeme „nackt“ aussehen und wie sie sich aufmotzen<br />

lassen.<br />

Raspbian<br />

Raspbian bietet dem Nutzer einen funktionellen Desktop. Mit Xfce als<br />

Desktop-Umgebung haben Sie die R<strong>Pi</strong>-Ressourcen gut im Griff und<br />

nicht für ineffizienten Ballast verschwendet. Dennoch können Sie den<br />

Raspbian-Desktop mit wenigen Mitteln grundlegend verändern. Mit Programmen<br />

wie Mate können Sie dem Desktop das „Look and Feel“ einer<br />

klassischen Gnome-2-Umgebung verleihen, das heißt, Sie können anschließend<br />

alles nach eigenem Gusto anpassen.<br />

In Sachen Nutzerfreundlichkeit liegt Raspbian in der Basisausstattung<br />

ganz weit vorn. Ein allzu ausschweifender Gebrauch des apt-Befehls<br />

und die Installation Hunderter von Anwendungen kann den <strong>Raspberry</strong><br />

<strong>Pi</strong> allerdings leistungsmäßig in die Knie zwingen.<br />

Arch<br />

Arch ist ein wundersames System. Es beginnt sein Leben auf dem R<strong>Pi</strong><br />

mit nichts weiter als einer Kommandozeile, doch stößt man in die Tiefen<br />

von Arch vor, entpuppt es sich als eines der besten Betriebssysteme.<br />

Arch ist ein schlichtes, modernes Programm. Selbst nach der Installation<br />

einer Desktop-Umgebung wie etwa OpenBox arbeitet das System<br />

schnell. Wenn Sie OpenBox mit einem R<strong>Pi</strong>-Theme und Conky kombinieren,<br />

dann sind Sie auf dem besten Wege zu einem komfortablen<br />

Desktop.<br />

Die Stärke von Arch ist, alles Nötige ohne Ballast nachinstallieren zu<br />

können. Arch ist somit das am besten individualisierbare Betriebssystem<br />

für den <strong>Raspberry</strong> <strong>Pi</strong>. Ein paar installierte Pakete, und Arch lässt<br />

seinen großen Bruder Raspbian spielend leicht hinter sich.<br />

Die Community<br />

Die Gemeinschaft der Nutzer bildet ein relevantes Kriterium.<br />

Wertung<br />

Raspbian<br />

Seine eingeschworene Userschaft<br />

macht Linux aus. Sie besteht<br />

aus Individuen, die helfen,<br />

teilen und sich für das eigene Lieblings-Betriebssystem<br />

starkmachen.<br />

Die Gemeinschaft ist ein Ort des Lernens<br />

und der Weitergabe von Wissen.<br />

Raspbian und Arch haben die größten<br />

Communitys: insbesondere Raspbian,<br />

das im Forum der R<strong>Pi</strong>-Website<br />

den größten Fokus erhält. Arch hingegen<br />

folgt mit einem Hauch von<br />

Rivalität, die zunimmt, während<br />

immer mehr Nutzer sich mit unterschiedlichen<br />

Betriebssystemen<br />

auseinandersetzen.<br />

<strong>Das</strong> Android-Projekt für den <strong>Raspberry</strong><br />

<strong>Pi</strong> nimmt an Fahrt auf. Immer<br />

mehr Nutzer interessieren sich für<br />

das Potenzial der R<strong>Pi</strong>-Portierung. Gegenwärtig<br />

spielt Android jedoch noch<br />

eine untergeordnete Rolle. Risc OS<br />

kommt mit vielen langjährigen Nutzern<br />

auf eine lebhafte Gemeinschaft.<br />

Plan 9 mag neuer sein, doch die Nutzer<br />

haben detaillierte und gut dokumentierte<br />

Hilfestellungen verfasst.<br />

Die meisten Community-Angebote<br />

finden sich auf den offiziellen Webseiten<br />

– nehmen Sie sich Zeit, das <strong>Raspberry</strong>-<strong>Pi</strong>-Forum<br />

zu durchforsten.<br />

Haben Sie keine Angst, Fragen zu<br />

stellen, denn es gibt sehr viele hilfsbereite<br />

Nutzer, die Einsteigern und<br />

Fortgeschrittenen gerne unter die<br />

Arme greifen.<br />

Risc OS<br />

Plan 9<br />

Android<br />

Arch<br />

Die Linux-<br />

Community ist<br />

ein Quell des<br />

Wissens, den<br />

man nutzen und<br />

fördern sollte.<br />

44


Projekte<br />

Android<br />

Android 2.3 ist an sich ein gut aussehendes Betriebssystem: ansehnliche<br />

Animationen, Symbole, Themes, bewegliche Hintergründe<br />

und Desktops sorgen für eine attraktive Umgebung. Auf einem<br />

<strong>Raspberry</strong> <strong>Pi</strong> geht jedoch einiges davon schief.<br />

Android für den R<strong>Pi</strong> ist derzeit weit davon entfernt, ein perfektes<br />

Betriebssystem zu sein. Auf einem 256-MB-R<strong>Pi</strong> ist es unbenutzbar,<br />

doch der <strong>erweiterte</strong> Arbeitsspeicher des 512-MB-Modells macht sich<br />

immerhin positiv bemerkbar. Es bleibt abzuwarten, wie sich die Sache<br />

entwickelt.<br />

Risc OS<br />

Risc OS bringt Sie wie Raspbian vom Start weg zu einer netten GUI. Die<br />

Oberfläche von Risc OS ist ausgewogen, farbenfroh und nett, vor allem<br />

wenn Sie es in 1080p hochfahren und mit einem passenden Bildschirm<br />

nutzen können. In Sachen Design ist der Basis-Desktop womöglich der<br />

einzige, den brauchen werden. Er orientiert sich an der glorreichen Vergangenheit<br />

von Risc, wirkt retro, aber nicht so billig wie zu 8-Bit-Zeiten.<br />

Die Bedienung erfordert etwas Erfahrung, beispielsweise ist der Netzwerk-Port<br />

standardmäßig deaktiviert. Es gibt zwar genügend Anleitungen,<br />

wie man ihn aktiviert, doch Einsteiger könnten damit schnell überfordert<br />

sein. Dennoch wird Sie Ausdauer wie bei allen anderen<br />

Computer-Themen voranbringen. Innerhalb einer Stunde sollte man<br />

sich ganz gut in Risc OS einarbeiten können.<br />

Plan 9<br />

Wenn Sie Plan 9 nutzen wollen, dann vergessen Sie alles, was Sie bei<br />

Windows, OS X, Linux oder gar Unix gelernt haben. Die Befehle sind<br />

zwar ähnlich, aber bis Sie tatsächlich welche eingeben können, ist einiges<br />

an Arbeit nötig. <strong>Das</strong> Verständnis von Plan 9 erfordert eine steile<br />

Lernkurve, der Start ist also nicht leicht. Dafür gibt es aber unzählige<br />

Dokumentationen.<br />

Rio, das Window-System von Plan 9, wirkt wie ein Rückschritt in<br />

Amiga- oder gar Atari-ST-Zeiten, weil die Fassade recht ähnlich aussieht.<br />

Wenn Sie durchhalten, werden Sie mit einem einfachen, eleganten und<br />

pfeilschnellen Desktop belohnt.<br />

Kindgerechte Systeme<br />

Kommen auch junge Anwender zurecht?<br />

Wertung<br />

Raspbian<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> ist beim Computer-Nachwuchs<br />

sehr beliebt,<br />

aber wie benutzerfreundlich<br />

sind seine Betriebssysteme im Hinblick<br />

auf Kinder und Jugendliche? Es ist ein<br />

ehrenwerter Ansatz seitens der <strong>Raspberry</strong><br />

<strong>Pi</strong> Foundation, der heranwachsenden<br />

Generation auf der <strong>Hardware</strong>seite<br />

die Werkzeuge in die Hand zu<br />

geben, um experimentierfreudiger mit<br />

Computern umgehen zu können –<br />

doch wenn die <strong>Hardware</strong> sich mithilfe<br />

der Software nicht gut bedienen lässt,<br />

dann werden insbesondere junge Anwender<br />

womöglich schnell das Interesse<br />

verlieren. Um dies besser einschätzen<br />

zu können, haben wir Daniel (11)<br />

und Hannah (10) als Tester rekrutiert.<br />

Raspbian und Risc OS führen das<br />

Feld an, Einrichtung und Benutzung<br />

waren einfach. Android und Plan 9 hinterließen<br />

einen schlechten Beigeschmack.<br />

Arch sorgte für blanke Ahnungslosigkeit<br />

und leere Gesichter, die<br />

jedoch nach ein bisschen Einarbeitung<br />

wieder an Farbe gewannen.<br />

Daniel entschied sich klar für Raspbian<br />

als Sieger, Hannah für Risc OS, welches<br />

für sie vor allem „netter aussieht“.<br />

Risc OS<br />

Plan 9<br />

Android<br />

Arch<br />

Unsere<br />

jugendlichen<br />

Tester ließen sich<br />

von Raspbian<br />

und Risc OS<br />

überzeugen.<br />

45


Projekte<br />

Medienwiedergabe<br />

Ein Media-Center ist fein, doch funktioniert es auf Anhieb?<br />

Mit der Medienwiedergabe<br />

unter Linux ist es so eine<br />

Sache. Einige Distributionen<br />

bieten alles Notwendige an Tools und<br />

Codecs an, andere nicht. Gut ist, dass<br />

Sie Linux nach Ihrem Gusto einrichten<br />

können – doch wie schneiden die von<br />

uns getesteten Betriebssysteme in der<br />

Standardausstattung ab?<br />

Android überraschte mit einer ordentlichen<br />

Wiedergabe unseres<br />

HD-Testfilms, allerdings war auf dem<br />

256-MB-R<strong>Pi</strong> schon nach zwei Minuten<br />

Schluss. Wir mussten daraufhin sogar<br />

die SD-Karte neu mit dem Betriebssystem<br />

bespielen, weil Android nicht<br />

mehr booten wollte. Der 512-MB-R<strong>Pi</strong><br />

streikte bei der Wiedergabe mit<br />

In der Basisausstattung fehlt Raspbian ein Media-Player für Filme und MP3s,<br />

doch auf lange Sicht ist das Betriebssystem die erste Wahl für die Medienwiedergabe<br />

auf dem <strong>Raspberry</strong> <strong>Pi</strong>.<br />

Android nach 15 Minuten. <strong>Das</strong> Video<br />

lief befriedigend, Kamerabewegungen<br />

führten jedoch zu Bildreißen (Tearing):<br />

mehr erlaubt der gegenwärtige<br />

Stand von R<strong>Pi</strong>-Android wohl nicht.<br />

MP3-Playback über den Audio-Port<br />

funktionierte, doch die 256-MB-Version<br />

des R<strong>Pi</strong> war weit davon entfernt,<br />

anständige Media-Player-Qualitäten<br />

aufzuweisen.<br />

Raspbian bot von Haus aus keinerlei<br />

Software, um Filme oder MP3s abzuspielen,<br />

was umso bedauerlicher ist,<br />

als eine Integrierung des OMXplayer<br />

wohl niemandem wehgetan hätte.<br />

Risc OS schnitt auch nicht besser ab.<br />

Sowohl Filme als auch MP3s ließen<br />

sich nicht laden – genau wie auch bei<br />

Plan 9. Obwohl beide Systeme sehr<br />

gute Medienzentralen abgeben würden,<br />

sind die Pakete nach der Ersteinrichtung<br />

nicht in der Lage, auch nur die<br />

gängigsten Medienformate abzuspielen.<br />

Es bedarf weiterer Downloads und<br />

einiger Kniffe, um Abhilfe zu schaffen.<br />

Arch reiht sich ebenfalls ein. Es bootet<br />

ins Terminal – die Hoffnung, direkt<br />

etwas Grafisches in Bewegung setzen<br />

zu können, ist verschwindend gering.<br />

Arch lässt sich als toller Media-Player<br />

einrichten, doch die erforderliche Lernkurve<br />

dürfte manchen Einsteiger<br />

überfordern.<br />

Wertung<br />

Raspbian<br />

Risc OS<br />

Plan 9<br />

Android<br />

Arch<br />

Android<br />

funktioniert<br />

einigermaßen<br />

mit dem<br />

512-MB-R<strong>Pi</strong>,<br />

doch auf lange<br />

Sicht ist Raspbian<br />

am besten.<br />

Open-Source-Software<br />

Bestnote für alle Systeme dank Linux-Philosophie.<br />

Die Quellcodes aller getesteten<br />

Betriebssysteme sind im Netz<br />

frei verfügbar. Sollte sich<br />

daran aus irgendwelchen Gründen<br />

etwas ändern, werden die entsprechenden<br />

Communitys ohne Frage sofort<br />

auf die Barrikaden gehen.<br />

Risc OS für den <strong>Raspberry</strong> <strong>Pi</strong> ist als<br />

Version 5.19 quelloffen, eine Gruppe<br />

von Freiwilligen kümmert sich darum.<br />

Die neueste Version 6 erfordert hingegen<br />

den Abschluss eines Select-Abonnements<br />

zu einem Preis von rund 120<br />

Euro pro Jahr. Dementsprechend handelt<br />

es sich bei Risc OS 6 um proprietäre<br />

Software, sprich sie wird lizenziert<br />

und ist nicht mehr quelloffen.<br />

Plan 9, Arch, Android und Raspbian<br />

sind nach wie vor frei zugänglich und<br />

individuell erweiterbar gemäß den<br />

Grundsätzen der gesamten Linux-<br />

Gemeinschaft und speziell denen der<br />

Raspberrry <strong>Pi</strong> Foundation.<br />

Die generelle Haltung zum Thema<br />

Software-Freiheit ist bei allen Projekten<br />

hinsichtlich der Verbesserung der<br />

Programme, des Einsatzes für Bildungszwecke<br />

und des Gebrauchs der<br />

Software ähnlich und befindet sich in<br />

Übereinstimmung mit den Grundsätzen<br />

der Open-Source-Community.<br />

Es wäre unfair, Risc OS hier abzuwerten,<br />

weil Risc OS 6 keine Open-<br />

Source-Software mehr ist, denn die<br />

Community hinter Version 5.19 für<br />

<strong>Raspberry</strong> <strong>Pi</strong> kümmert sich weiterhin<br />

um das Programm und den Grundgedanken<br />

freier Software.<br />

Risc OS erfordert ab Version 6 ein<br />

Select-Abo, das rund 120 Euro im Jahr<br />

kostet.<br />

Wertung<br />

Rasbian<br />

RISC OS<br />

Plan 9<br />

Android<br />

Arch<br />

Bestnoten für<br />

alle Systeme,<br />

wobei jedoch das<br />

neueste Risc OS<br />

nicht mehr<br />

quelloffen ist.<br />

46


Projekte<br />

Betriebssysteme für den <strong>Raspberry</strong> <strong>Pi</strong><br />

<strong>Das</strong> Fazit<br />

Ein Sieg für<br />

Raspbian, doch<br />

die Konkurrenz<br />

rückt näher!<br />

Von allen getesteten Betriebssystemen<br />

entpuppte sich Raspbian<br />

als nutzerfreundlichstes,<br />

bestaussehendes und bestausgestattetes.<br />

Allerdings nähern die anderen<br />

Systeme sich langsam, aber sicher an.<br />

Für Einsteiger ist Raspbian ein guter<br />

Startpunkt – nicht nur in die Welt des<br />

<strong>Raspberry</strong> <strong>Pi</strong>, sondern auch für die<br />

ersten Schritte in die große Welt von<br />

Linux und anderen alternativen Betriebssystemen.<br />

Sollte ein Anfänger<br />

über die Einstiegshürden hinweg sein,<br />

besteht eine hohe Wahrscheinlichkeit,<br />

dass er sich für Arch, Risc OS oder<br />

Plan 9 als Betriebssystem für seinen<br />

<strong>Raspberry</strong> <strong>Pi</strong> entscheiden wird.<br />

Android für R<strong>Pi</strong> ist sicher interessant<br />

und hat Potenzial, doch bislang<br />

bleiben dessen Möglichkeiten weit hinter<br />

denen aktueller Android-Mobilgeräte<br />

zurück.<br />

Mehr Leistung fürs Volk<br />

Die Leistung ist entscheidend. Während<br />

die minimalistischen Vertreter<br />

Arch und Plan 9 die jetzigen R<strong>Pi</strong>-Modelle<br />

nicht zum Schwitzen bringen<br />

sollten, ist diese Wahrscheinlichkeit<br />

bei Raspbian recht hoch.<br />

Sollte die <strong>Raspberry</strong> <strong>Pi</strong> Foundation<br />

jemals ein leistungsfähigeres Modell<br />

entwickeln, dürfte die Anzahl der Betriebssysteme<br />

in kurzer Zeit sprunghaft<br />

ansteigen. <strong>Das</strong> Problem liegt<br />

hierbei jedoch bei den Kosten. Der<br />

jetzige Preis von rund 35 Euro ist das,<br />

was den R<strong>Pi</strong> so attraktiv macht. Mit<br />

mehr Leistung und Performance<br />

gehen allgemein höhere Kosten einher.<br />

Gegenwärtig geht es uns mit<br />

der Anzahl guter Betriebssysteme<br />

recht gut. Es gibt keinen Konkurrenzkampf,<br />

dafür aber die Möglichkeit,<br />

dass ein R<strong>Pi</strong>-Nutzer die Hand<br />

nach einem neuen OS ausstreckt,<br />

davon lernt und sich – wie beim gesamten<br />

Thema Linux – individuell<br />

weiterentwickelt.<br />

Denken Sie also daran: Raspbian<br />

gewinnt den Vergleichstest zwar,<br />

doch die anderen Betriebssysteme<br />

sind Projekte, die auf experimentierfreudige<br />

Menschen warten.<br />

„Raspbian entpuppte sich<br />

im Test als das nutzerfreundlichste<br />

System.“<br />

1.<br />

2.<br />

Raspbian<br />

Download: http://goo.gl/4WwPJ<br />

Raspbian ist perfekt für Einsteiger, Fortgeschrittene schauen sich<br />

woanders um.<br />

Risc OS<br />

Download: http://goo.gl/pn2NP<br />

Mit wenig Aufwand ist Risc OS ein voll funktionsfähiges Desktop-<br />

Betriebssystem.<br />

4.<br />

Android for R<strong>Pi</strong><br />

Download: http://goo.gl/w4eoy<br />

Arbeitet kaum auf dem 256-MB-R<strong>Pi</strong>, doch man darf auf die Zukunft gespannt<br />

sein.<br />

5.<br />

Plan 9<br />

Download: http://goo.gl/qtN7E<br />

Sieht retro aus, kann Ihnen mit genügend Geduld jedoch das geben,<br />

was Sie wollen.<br />

3.<br />

Arch Linux ARM<br />

Download: http://goo.gl/L5HtQ<br />

Arch erfordert mehr Erfahrung, ist dafür aber am Ende stärker.<br />

<strong>Pi</strong>Bang – noch ein<br />

Betriebssystem<br />

Falls Ihnen die getesteten Systeme nicht zusagen, werfen Sie<br />

einen Blick auf <strong>Pi</strong>Bang, eine Linux-Distribution, die sich am<br />

beliebten CrunchBang Linux orientiert. <strong>Pi</strong>Bang sieht dank der<br />

gelungenen Kombination aus OpenBox, Tint2 und Nitrogen<br />

fantastisch aus, dazu ist es schnell, läuft flüssig und stabil. <strong>Pi</strong>-<br />

Bang beinhaltet OMXplayer und VLC, wenngleich VLC sich<br />

laut den Machern auf dem <strong>Raspberry</strong> <strong>Pi</strong> noch nicht dazu<br />

eignet, Videos flüssig abzuspielen, sondern vorerst Testzwecken<br />

und der Musikwiedergabe dient. <strong>Pi</strong>Bang bietet darüber<br />

hinaus eine vollwertige Desktop-Umgebung. Es nutzt dieselben<br />

Software-Quellen wie Raspbian – also sind sie kompatibel.<br />

Wir haben <strong>Pi</strong>Bang dennoch nicht in unseren Vergleichstest<br />

aufgenommen, da es bisher leider noch nicht allzu viel<br />

Beachtung gefunden hat.<br />

47


Projekte<br />

Betriebssystem:<br />

Mit Windows-Tools kopieren Sie Raspbian einfach auf eine SD-Karte.<br />

Schritt-für-Schritt-Anleitung: Windows<br />

1 Tools herunterladen<br />

Obwohl Windows von Microsoft nicht viel mit der<br />

Linux-Version, die auf dem <strong>Raspberry</strong> <strong>Pi</strong> läuft, gemein<br />

hat, bedeutet dies nicht, dass Windows-Anwender<br />

im Nachteil wären, wenn es um die Einrichtung<br />

eines funktionierenden <strong>Pi</strong>-Systems geht.<br />

<strong>Das</strong> liegt unter anderem daran, dass die vielen<br />

verschiedenen Einsatzzwecke von Windows und<br />

die zahlreichen Tools im Prinzip gar nicht so unterschiedlich<br />

zum Ansatz des <strong>Raspberry</strong> <strong>Pi</strong> sind.<br />

Beide Systeme bieten dem Nutzer grundsätzlich<br />

die gleichen Freiheiten bei der Verwendung von<br />

Anwendungen. Wenn man genauer sucht, findet<br />

man sogar bei Windows eine Kommandozeile,<br />

und viele Open-Source-Programme sind auch für<br />

den Betrieb mit Windows ausgelegt.<br />

Windows-Anwender profitieren darüber hinaus<br />

von einer relativ gefahrlosen Installationsroutine<br />

in Form der Open-Source-Software Win32 Disk<br />

Imager. Als Erstes sollten Sie sich daher das<br />

Tool unter folgender Adresse herunterladen:<br />

sourceforge.net/projects/win32diskimager<br />

Sie brauchen Win32 Disk Imager nicht zu<br />

installieren, es reicht aus, wenn Sie das ZIP-File<br />

mit einem Rechtsklick in einen Ordner entpacken.<br />

Um Raspbian auf eine SD-Karte zu kopieren,<br />

benötigen Sie natürlich auch eine Kopie der<br />

entsprechenden Image-Datei. Unsere Methode<br />

funktioniert grundsätzlich mit allen <strong>Raspberry</strong>-<strong>Pi</strong>-<br />

Betriebssystemen und kann auch für das Schreiben<br />

anderer Images auf ein externes USB-Gerät<br />

verwendet werden.<br />

Sie können das Open-Source-Tool Win32 Disk<br />

Imager für den Schreibvorgang verwenden.<br />

2 USB-Speicher prüfen<br />

Bevor Sie das Tool zum Schreiben des Image-<br />

Files starten, sollten Sie sichergehen, dass auf<br />

der SD-Karte keine wichtigen Dateien mehr<br />

gespeichert sind und der SD-Kartenspeicher<br />

einen selbsterklärenden Namen wie beispielsweise<br />

„Raspbian“ trägt. Viele <strong>PC</strong>s besitzen<br />

einen eingebauten SD-Kartenleser, allerdings<br />

gibt es Berichte, nach denen es mit solchen<br />

Kartenlesern öfter Probleme geben soll, wenn<br />

man eine bootbare Version von Raspbian auf<br />

einer SD-Karte erstellen will. Die besten Ergebnisse<br />

konnten wir mit einen Kartenleser erzielen,<br />

der extern via USB mit dem <strong>PC</strong> verbunden war.<br />

Sollten Sie ebenfalls auf Probleme stoßen, sollten<br />

Sie als Erstes beim Kartenleser ansetzen.<br />

Die SD-Karte sollte nach dem Einschieben in<br />

den Kartenleser als eigenes Laufwerk angezeigt<br />

werden – merken Sie sich den Laufwerksbuchstaben,<br />

und prüfen Sie bei dieser Gelegenheit<br />

nochmals, ob das Laufwerk noch wichtige Daten<br />

enthält.<br />

Windows zeigt in der Übersicht die Größe der<br />

Partitionen, nicht der Laufwerke an.<br />

3 Win32 Disk Imager starten<br />

Jetzt können Sie die ausführbare Datei des<br />

Open-Source-Tools Win32 Disk Imager starten.<br />

Manchmal warnt Windows vor unbekannten<br />

Datei quellen, im Zweifelsfall können Sie die ausführbare<br />

Datei von einem aktuellen Virenprogramm<br />

prüfen lassen. Seien Sie sich bei Windows-Dateien<br />

lieber ganz sicher, denn unter<br />

Linux gibt es kaum Viren – also besser am Anfang<br />

etwas mehr Sorgfalt walten lassen, als sich<br />

der Gefahr einer Virusinfektion auszusetzen. <strong>Das</strong><br />

Hauptfenster des Tools ist nicht besonders intuitiv,<br />

für den Moment sind aber nur zwei Schaltflächen<br />

für die erfolgreiche Arbeit wichtig. Ein Knopf<br />

ist zuständig für die Auswahl des Image-Files,<br />

der andere – rechts daneben – erlaubt die Zielauswahl<br />

des Ortes, auf den die Daten des<br />

Image-Files geschrieben werden sollen. Wenn<br />

Sie auf das kleine Ordner-Icon klicken, müssen<br />

Sie dem Programm zeigen, wo das Image-File<br />

liegt. In der Regel werden nur *.img-Dateien angezeigt.<br />

Der kleine „Geräte“-Knopf zeigt dem Programm<br />

im Anschluss den Ort, wohin die Dateien<br />

geschrieben werden sollen. Win32 Disk Imager<br />

wählt meist das korrekte Ziel automatisch aus,<br />

aber prüfen Sie unbedingt den Laufwerksbuchstaben,<br />

sonst werden eventuell wichtige Dateien<br />

unbeabsichtigt gelöscht.<br />

<strong>Das</strong> User-Interface ist zwar schlicht, aber es<br />

zeigt alle wichtigen Schaltflächen.<br />

48


Projekte<br />

Raspbian<br />

4 Daten schreiben<br />

Wenn Sie alles geprüft und korrekt eingestellt<br />

haben, können Sie auf den „Write“-Knopf<br />

drücken. Es erscheint eine Warnung, die erneut<br />

die Gefahren für das Ziellaufwerk aufführt,<br />

diese können Sie allerdings ignorieren. Die<br />

SD-Karte wird auf dem untersten „Level“ mit<br />

den neuen Daten überschrieben, dazu zählen<br />

auch die Partitionstabelle und weitere grundlegende<br />

Formatierungen. Diese Low-Level-Formatierung<br />

ist notwendig, damit die SD-Karte<br />

später auch bootbar ist. Nach dem Start sollte,<br />

falls vorhanden, eine kleine LED beim SD-Kartenleser<br />

flackern, so können Sie ebenfalls sicherstellen,<br />

dass Sie den richtigen Laufwerksbuchstaben<br />

ausgewählt haben. Man kann nicht<br />

oft genug betonen, dass Sie hier extrem sorgfältig<br />

zu Werke gehen müssen, denn so ein<br />

Schreibvorgang auf einer der internen Festplatten<br />

sorgt dafür, dass alle Daten auf diesem<br />

Daten träger verloren sind. Der Schreibvorgang<br />

benötigt rund 20 Minuten, dieser wird von einer<br />

Balkenanzeige und von der Angabe der Schreibleistung<br />

pro Sekunde ergänzt.<br />

Während die Daten auf die SD-Karte geschrieben<br />

werden, informiert Sie ein Balken über den<br />

Fortschritt.<br />

5<br />

Die Installation prüfen<br />

Bevor Sie die neu beschriebene SD-Karte in<br />

Ihren <strong>Raspberry</strong> <strong>Pi</strong> stecken, sollten Sie die Installationsdateien<br />

prüfen. Dieser Schritt gibt<br />

Ihnen auch einige Einblicke in die neue Formatierung<br />

der SD-Karte. Schauen Sie im ersten<br />

Schritt mithilfe der Laufwerksübersicht auf der<br />

SD-Karte nach, ob die neuen Dateien tatsächlich<br />

auf dem Speichermedium vorhanden sind.<br />

Die neue Linux-Partition auf der SD-Karte kann<br />

aber von einem Windows-<strong>PC</strong> nicht gelesen<br />

werden, da Windows das Linux-Dateisystem<br />

nicht versteht. Nutzen Sie zur Überprüfung<br />

daher ein gesondertes Windows-Tool, welches<br />

Sie durch die Suche nach „Erstellen und Formatieren<br />

einer Festplattenpartition“ finden können.<br />

Auf der Übersichtsseite der Computerverwaltung<br />

werden alle Laufwerke und Partitionen, die<br />

derzeit angeschlossen sind, angezeigt. Suchen<br />

Sie den Laufwerksbuchstaben der SD-Karte,<br />

darunter sollten drei Partitionen angezeigt<br />

werden: eine im FAT-Dateisystem mit rund<br />

56 MB Speicher platz, dann die Linux-Partition<br />

sowie eine dritte, die den nicht zugewiesenen<br />

Speicherplatz anzeigt. Wenn Sie also drei<br />

Partitionen auf der SD-Karte vorfinden, ist dem<br />

Anschein nach alles so verlaufen, wie es<br />

geplant war.<br />

Die Partitionsanzeige von Windows liefert<br />

brauchbare Hinweise, ob der Kopiervorgang ohne<br />

Probleme abgelaufen ist.<br />

NOOBS – es geht noch einfacher!<br />

Es ist grundsätzlich immer von Vorteil, wenn man<br />

die einzelnen Abläufe und Maßnahmen kennt, die<br />

beispielsweise zur Erstellung einer bootbaren<br />

SD-Karte erforderlich sind. Daher geben wir Ihnen<br />

für Windows, OS X und Linux auch diese Schrittfür-Schritt-Anleitungen<br />

an die Hand. Es gibt allerdings<br />

eine noch einfachere Methode, mit der man<br />

das gewünschte Resultat erzielen kann.<br />

Dazu benötigen Sie die Software NOOBS, mit der<br />

man Raspbian und andere Linux-Versionen auf<br />

einem <strong>Raspberry</strong> <strong>Pi</strong> installieren kann. NOOBS ist<br />

ein Recovery-Tool für <strong>Raspberry</strong> <strong>Pi</strong> und enthält<br />

Images von OS-Varianten wie Raspbian, RiscOS,<br />

Arch Linux, <strong>Pi</strong>dora, Raspbmc und OpenElec.<br />

<strong>Das</strong> ganze Paket ist rund 1 GB groß und unter<br />

www.raspberrypi.org/downloads erhältlich. Um<br />

NOOBS zu nutzen, benötigen Sie eine SD-Karte<br />

mit 4 GB oder mehr Speicherplatz, als Dateisystem<br />

muss FAT32 verwendet werden. NOOBS wird<br />

installiert, indem Sie den Inhalt des NOOBS-Zip-<br />

Files auf die leere SD-Karte kopieren. Nun können<br />

Sie bereits die SD-Karte in einen <strong>Raspberry</strong> <strong>Pi</strong><br />

stecken und das System starten. Beim ersten<br />

Bootvorgang wird NOOBS automatisch geladen<br />

und begrüßt Sie mit einem sehr übersichtlichen<br />

Aufbau. Um ein Betriebssystem zu installieren,<br />

müssen Sie im zugehörigen Menü einfach nur<br />

„Install OS“ auswählen – fertig. Es folgt ein grafischer<br />

Installationsassistent, der Sie über das<br />

ausgewählte Betriebssystem informiert. Eine der<br />

besten NOOBS-Funktionen ist, dass Sie beim<br />

Booten einfach die Shift-Taste gedrückt halten<br />

können und dann ein anderes der zur Verfügung<br />

stehenden Betriebssysteme auswählen können.<br />

Beachten Sie aber, dass der Start mit einem<br />

anderen OS die Daten des vorherigen löscht.<br />

49


Projekte<br />

Betriebssystem:<br />

Für Apple-Anwender gibt es eine schnelle Installationsmöglichkeit ohne<br />

großen Aufwand.<br />

Schritt-für-Schritt-Anleitung: Apple<br />

1 Die Vorbereitung<br />

Obwohl OS X an jeder Stelle die Apple-Handschrift<br />

trägt und viele Dinge stark vereinfacht<br />

implementiert sind, hat das Apple-OS doch viele<br />

Dinge mit Linux gemeinsam. Beide Betriebssysteme<br />

basieren auf einem älteren Multi-User-<br />

System namens UNIX, und viele Tools und Anwendungen<br />

haben denselben Ursprung. Dies<br />

gibt erfahrenen OS X-Anwendern einen Vorteil,<br />

denn wenn Sie bereits mit der Kommandozeile<br />

von OS X gearbeitet haben, wird Sie das Linux-<br />

System vor keine großen Herausforderungen<br />

stellen. Ebenfalls sehr ähnlich sind die Konzepte<br />

der Anwenderkonten, der Verzeichnisse, des Dateiaustauschs<br />

und der Netzwerk-Drucker. Sie<br />

können den <strong>Raspberry</strong> <strong>Pi</strong> mit OS X über die<br />

Kommandozeile konfigurieren und steuern, ohne<br />

dabei spezielle Software installieren zu müssen.<br />

Darüber hinaus sind auch virtuelle Desktops<br />

kein Problem, und in dieser Disziplin können<br />

beide Systeme ihre Wurzeln nicht verleugnen.<br />

Bevor Sie allerdings diese Schnittstellen des<br />

Mac nutzen können, müssen Sie Raspbian natürlich<br />

erst auf einer Speicherkarte installieren.<br />

OS X bietet von Haus aus Tools, die Sie auch<br />

auf einem <strong>Raspberry</strong> <strong>Pi</strong> finden.<br />

2 Tools herunterladen<br />

Die Standard-Installationsvariante von Raspbian<br />

mit einem Mac ist, genau wie bei Linux,<br />

über die Kommandozeile durchzuführen. Über<br />

diese installieren Sie Raspbian auf einer SD-<br />

Karte. Wenn Sie diesen Weg gehen möchten,<br />

folgen Sie der Schritt-für-Schritt-Anleitung für<br />

Linux und passen Sie die Gerätenamen denen<br />

bei OS X an. Es gibt auf dem Mac aber auch<br />

eine einfachere und sicherere Lösung, bei der<br />

die Installation über ein grafisches Benutzerinterface<br />

angegangen wird. Dazu benötigen Sie<br />

das Tool R<strong>Pi</strong>-sd card builder, welches derzeit in<br />

der Version 1.2 verfügbar ist. <strong>Das</strong> Tool finden<br />

Sie unter:<br />

alltheware.wordpress.com/2012/12/11/<br />

easiest-way-sd-card-setup.<br />

Speichern Sie das Tool in einem lokalen Ordner<br />

auf Ihrem Mac, und stellen Sie sicher, dass<br />

Sie die aktuelle Version des Raspbian-Images<br />

zur Hand haben, da dieses bereits im ersten<br />

Schritt der Installation benötigt wird. Die aktuelle<br />

Version des Raspbian-Images finden Sie<br />

unter www.raspberrypi.org/downloads. Verwenden<br />

Sie die Version, die mit dem Namenszusatz<br />

„wheezy“ versehen ist. Da die Image-Datei nur<br />

rund 500 MB groß ist, sollte der Download nur<br />

wenige Minuten dauern – dies hängt natürlich<br />

auch von Ihrem Internetanschluss und der<br />

Server-Geschwindigkeit ab.<br />

Der R<strong>Pi</strong>-sd card builder erspart Ihnen den mühsamen<br />

Weg über die Kommandozeile und ist für<br />

Einsteiger ideal.<br />

3 Den Builder starten<br />

Der Download ist als Zip-File verpackt. Auf<br />

einem Mac werden die Zip-Dateien in der Regel<br />

nach dem Download automatisch entpackt.<br />

Sie erhalten dann eine Datei mit einem Namen<br />

wie 2012-12-16-wheezy-raspbian.img – wobei<br />

die genaue Bezeichnung vom Download-Datum<br />

und der jeweiligen Software-Version abhängt.<br />

Wenn Sie die Datei selbst entpacken müssen,<br />

genügt ein Doppelklick auf die heruntergeladene<br />

Zip-Datei. Der R<strong>Pi</strong>-sd card builder sollte<br />

nach dem Herunterladen ebenfalls im<br />

Download-Ordner abgelegt worden sein und ist<br />

recht einfach durch das <strong>Raspberry</strong>-<strong>Pi</strong>-Icon zu<br />

identifizieren. Starten Sie nun den R<strong>Pi</strong>-sd card<br />

builder, und dieser fordert Sie auf, das jeweilige<br />

Image auszuwählen, das Sie für die Installation<br />

auf Ihrem <strong>Raspberry</strong> <strong>Pi</strong> heruntergeladen<br />

haben – da Sie das Image vorher in einem<br />

speziellen Ordner abgelegt haben, sollte es<br />

leicht zu finden sein. Anschließend drücken Sie<br />

noch auf den „Choose“-Knopf, und das Tool<br />

beginnt mit der Verarbeitung der<br />

Raspbian-Image-Datei.<br />

Der R<strong>Pi</strong>-sd card builder fordert Sie auf, manuell<br />

den Speicherort des Image-Files für die Installation<br />

auszuwählen.<br />

50


Projekte<br />

Raspbian<br />

4 SD-Karte auswählen<br />

Der R<strong>Pi</strong>-sd card builder wird sich nach dem Start<br />

beschweren, dass keine SD-Karte gefunden wird<br />

– egal, ob diese korrekt angeschlossen ist oder<br />

nicht. Wir verwenden für unsere Arbeiten einen<br />

Standard-USB-Kartenleser, ein ähnliches Gerät<br />

sollten Sie mit der eingelegten SD-Karte an<br />

Ihrem Mac anschließen. Stellen Sie sicher, dass<br />

der Schreibschutz der SD-Karte nicht aktiviert ist.<br />

Bei Karten mit diesem Feature finden Sie an der<br />

Seite einen kleinen Plastikschieber – stellen Sie<br />

sicher, dass dieser korrekt eingestellt ist. Achten<br />

Sie ebenfalls darauf, dass auf der eingelegten<br />

SD-Karte keine Daten mehr gespeichert sind, die<br />

Sie behalten möchten, denn diese werden im folgenden<br />

Prozess vollständig überschrieben.<br />

Der angeschlossene SD-Kartenleser wird automatisch<br />

nach dem Anschluss auf dem Desktop<br />

angezeigt. Nachdem Sie den Kartenleser samt<br />

Karte angeschlossen haben, klicken Sie in dem<br />

Programm R<strong>Pi</strong>-sd card builder auf „Continue“.<br />

Der folgende Bildschirm zeigt alle Laufwerke an,<br />

hier müssen Sie den SD-Kartenleser und die SD-<br />

Karte auswählen – seien Sie 100 % sicher, dass<br />

Sie das richtige Ziel auswählen, denn sonst wird<br />

im schlimmsten Fall Ihre Festplatte gelöscht. In<br />

der rechten Spalte der Übersicht sehen Sie den<br />

Namen des ausgewählten Geräts, dieser sollte<br />

mit dem Namen der SD-Karte übereinstimmen.<br />

Vergleichen Sie auch die Größenangabe der SD-<br />

Karte mit Ihren Informationen. Wenn alles passt,<br />

klicken Sie auf „OK“.<br />

Überprüfen Sie den Namen des Zielgeräts zur<br />

Not dreimal, damit Sie absolut sicher sind.<br />

5 Raspbian schreiben<br />

Nun werden Sie gebeten, Ihr Passwort einzugeben.<br />

Sie müssen am Mac als Administrator angemeldet<br />

sein – eine weitere Ähnlichkeit mit<br />

dem Linux-System. Die meisten Mac-Anwender<br />

haben ohnehin Administratorenrechte, also können<br />

Sie ein gewünschtes Passwort in der Regel<br />

ohne Vorarbeiten eingeben. Ein weiteres Fenster<br />

verkündet nun, dass das Gerät erst entfernt<br />

(„unmount“) werden muss. Dies ist erforderlich,<br />

da Inhalte im „Low Level“-Format geschrieben<br />

werden müssen und dies am Mac nicht möglich<br />

ist, wenn das Gerät vom Desktop aus erreicht<br />

werden kann. Warten Sie also, bis das Icon der<br />

SD-Karte vom Desktop verschwunden ist, dann<br />

klicken Sie auf „Continue“. Der eigentliche<br />

Schreibvorgang dauert rund 15 Minuten. Hinter<br />

dem rotierenden Zahnrad oben am Bildschirm<br />

verbirgt sich zusätzlich eine Statusleiste.<br />

Sie müssen Ihr Passwort<br />

eingeben, um der Anwendung<br />

die benötigen Schreibrechte<br />

einzuräumen.<br />

6 Die Installation prüfen<br />

Wenn der Vorgang abgeschlossen ist, sollte die<br />

SD-Karte für den ersten Einsatz im <strong>Raspberry</strong> <strong>Pi</strong><br />

bereit sein. Bevor Sie sie benutzen, sollten Sie<br />

sich den Inhalt der SD-Karte aber nochmal auf<br />

dem Desktop anschauen. Dadurch können Sie<br />

schon früh Fehler bei der Vorbereitung ausschließen,<br />

damit es später keine Probleme gibt. Kurz<br />

nach dem Abschluss des Kopiervorgangs sollte<br />

die SD-Karte wieder auf dem Desktop auftauchen.<br />

Dieses Laufwerk sollte nur 18 MB Daten<br />

beherbergen, und angeblich sind nur noch etwa<br />

41 MB auf dem Laufwerk frei. Dies liegt daran,<br />

dass Sie sich so zwar die Boot-Partition anzeigen<br />

lassen können, aber die anderen Partitionen auf<br />

der SD-Karte für den Mac unsichtbar sind. Wenn<br />

Sie diese Partitionen sehen wollen, müssen Sie<br />

die Datenträgerverwaltung des Mac verwenden.<br />

Diese zeigt bei der Auswahl das jeweilige Speichermedium,<br />

und wenn Sie es auswählen, können<br />

Sie sich auch die Partitionen anzeigen lassen.<br />

Wenn alles korrekt abgelaufen ist, sehen<br />

Sie zwei Partitionen und etwas ungenutzten Platz<br />

auf der SD-Karte. Diesen können Sie später mit<br />

einem Linux-Tool dem freien Patz auf der SD-<br />

Karte hinzufügen.<br />

Prüfen Sie mit der Datenträgerverwaltung die<br />

Installation auf der SD-Karte, bevor Sie den <strong>Pi</strong><br />

starten.<br />

51


Projekte<br />

Betriebssystem:<br />

Die Installation von Linux auf dem <strong>Raspberry</strong> <strong>Pi</strong> mithilfe eines Linux-Rechners ist<br />

vermutlich die sicherste Variante, und etwas lernen können Sie dabei auch noch.<br />

Schritt-für-Schritt-Anleitung: Linux<br />

1 Funktionsvielfalt<br />

Wenn Sie bislang Linux noch nicht verwendet<br />

haben, müssen Sie sich deswegen keine Sorgen<br />

machen. Linux ist mittlerweile so einfach zu verwenden<br />

wie andere Betriebssysteme auch. Bei<br />

manchen Dingen ist es sogar einfacher zu bedienen.<br />

Man muss beispielsweise keine Treiber<br />

suchen, und Anwendungen werden quasi über<br />

einen eigenen App Store installiert. Und da Sie<br />

ohnehin Linux auf einem <strong>Raspberry</strong> <strong>Pi</strong> installieren<br />

wollen, können Sie auch schon mit den Vorbereitungen<br />

unter Linux beginnen. Wir empfehlen<br />

Ubuntu für die ersten Schritte mit Linux, die<br />

Tipps funktionieren im Prinzip aber auch mit<br />

jeder anderen Linux-Distribution. Linux ist auch<br />

für Notfälle eine gute Option, denn es kann von<br />

einer CD gestartet werden – ganz ohne Festplatte.<br />

Nach dem Einlegen einer Ubuntu-CD erscheint<br />

ein Auswahlmenü. Wählen Sie hier das<br />

Optionsmenü „Try Ubuntu“, denn so kommen wir<br />

auf den Ubuntu-Desktop, den Sie für Notfälle benötigen.<br />

Die Software ist kostenlos im Netz erhältlich<br />

und kann auf CD gebrannt werden.<br />

Auch ohne Linux installiert zu haben,<br />

können Sie mit Ubuntu das System<br />

bis zum Desktop laden.<br />

2 Vorbereitung<br />

Allerdings ist das Problem mit dem Start von der<br />

Ubuntu-Boot-CD, dass Sie damit Raspbian nicht<br />

herunterladen können, da Sie die Dateien nicht<br />

speichern können. Der Grund liegt darin, dass<br />

der Ubuntu-Anwendung zu wenig Speicher für<br />

den gesamten Download von Raspbian zur<br />

Verfügung steht. Sie müssen die Daten also auf<br />

einem externen Datenspeicher ablegen, aber<br />

nicht auf der SD-Karte, auf der ja das Image erzeugt<br />

werden soll. Wenn Sie ein installiertes<br />

Linux-System besitzen, sieht die Sache natürlich<br />

anders aus, dann können Sie die Daten einfach<br />

auf dem Datenträger ablegen. Nachdem das<br />

Image heruntergeladen wurde, sollten Sie sich<br />

ein Bild von der SD-Karte machen. Alle Daten<br />

auf dem Datenträger werden gelöscht. Stellen<br />

Sie also sicher, dass keine wichtigen Informationen<br />

auf der SD-Karte abgelegt sind.<br />

Wenn Sie unter Ubuntu ein<br />

USB-Laufwerk einlegen, zeigt Ihnen<br />

Ubuntu sämtliche Partitionen<br />

auf diesem an.<br />

3 ImageWriter installieren<br />

Wir werden das Tool ImageWriter als grafisches<br />

Frontend für den Schreibvorgang von Raspbian<br />

nutzen. Dieses Tool kann über das Software-Center<br />

von Ubuntu installiert werden. Dieses starten<br />

Sie durch einen Klick auf das Korb-Icon. Suchen<br />

Sie dann nach „imagewriter“. Es sollte nur ein<br />

einziges Tool angezeigt werden. Machen Sie<br />

einen Doppelklick auf das Programm, und es erscheint<br />

eine Anzeige, nach der die Software von<br />

der „universe“-Quelle erhältlich ist. Diese Quelle<br />

ist standardmäßig nicht aktiviert, sondern muss<br />

mit einem Klick auf „Use this Source“ freigegeben<br />

werden. Warten Sie, bis der Fortschrittsbalken<br />

durchgelaufen ist und die interne Angebotsliste<br />

aktualisiert wurde. Löschen Sie das<br />

Suchfeld, und geben Sie erneut „imagewriter“<br />

ein. <strong>Das</strong> Softwareangebot sollte nun aktualisiert<br />

worden sein, und Sie können nun auf einen<br />

„Install“-Knopf klicken. Sie werden sich vielleicht<br />

fragen, warum man ein Zusatzpaket, nicht aber<br />

Raspbian ohne zusätzlichen Speicherplatz installieren<br />

kann. <strong>Das</strong> liegt daran, dass das Paket<br />

deutlich kleiner als Raspbian ausfällt.<br />

ImageWriter kann auch mit der<br />

Live-CD von Ubuntu installiert und<br />

genutzt werden.<br />

52


Projekte<br />

Raspbian<br />

4 <strong>Das</strong> Raspbian-Image schreiben<br />

ImageWriter muss mit der „gemounteten“ SD-<br />

Karte gestartet werden, sonst startet es nicht<br />

und beschwert sich, dass kein Speicherplatz verfügbar<br />

ist. Wenn der Hauptbildschirm erscheint,<br />

müssen Sie der Software einige Parameter verraten.<br />

Der erste ist die Position des Raspbian-<br />

Images, das Sie auf den USB-Stick schreiben<br />

wollen, der zweite bezeichnet das Gerät, auf welches<br />

das Image geschrieben werden soll. Die<br />

zweite Einstellung ist besonders wichtig, da Sie,<br />

falls Sie mehrere Speicherplätze auf Ihrem System<br />

haben, sicherstellen müssen, dass Sie die<br />

Daten nicht auf das falsche Laufwerk aufspielen,<br />

um nicht unabsichtlich irgendwelche Daten zu<br />

löschen. Es wird auch der Name des Geräteherstellers<br />

angezeigt, dies könnte Sie ebenfalls vor<br />

einer falschen Auswahl bewahren. Nun können<br />

Sie das Programm mit einem Klick auf „Write to<br />

Device“ starten. Wenn das USB-Laufwerk mit der<br />

SD-Karte eine LED für Laufwerksaktivitäten besitzt,<br />

sollte diese jetzt flackern. Der Schreibprozess<br />

wird eine gute Weile dauern, die genaue<br />

Zeitspanne hängt von der Geschwindigkeit der<br />

USB-Ports und anderer Komponenten ab. Normalerweise<br />

können Sie von rund 15 Minuten<br />

ausgehen, danach können Sie die SD-Karte<br />

testen.<br />

ImageWriter benötigt nur das Image und die<br />

SD-Karte als Ziel, dann kann es auch schon<br />

losgehen.<br />

5 SD-Karte testen<br />

Anders als Windows und OS X kann Linux als<br />

einziges Betriebssystem die beiden Partitionen<br />

der neuen <strong>Raspberry</strong>-<strong>Pi</strong>-SD-Karte lesen. Die<br />

erste ist in einem Windows-FAT-Format formatiert<br />

und sollte rund 60 MB groß sein. Über<br />

diese Partition startet das System, und anschließend<br />

übergibt Raspbian quasi die Kontrolle<br />

an die zweite Partition. Diese ist mit den<br />

wichtigsten Inhalten von Raspbian angefüllt,<br />

hier ist also das Root-Dateisystem von Linux<br />

zu finden. Beide Partitionen werden erkannt,<br />

wenn Sie die SD-Karte an ein Linux-System<br />

anschließen. Die Linux-Partition sieht der Ihres<br />

Ubuntu-Systems recht ähnlich. Dies liegt daran,<br />

dass beide Systeme vom selben Ursprung namens<br />

Debian abstammen. Der „Home“-Ordner<br />

besitzt beispielsweise einen Anwender-Ordner, in<br />

dem Dateien und Settings gespeichert werden.<br />

Raspbian ist auf einen einzigen Anwender „pi“<br />

vorkonfiguriert. Dies lässt sich später natürlich<br />

schnell ändern. Sie können sehen, was sich in<br />

diesem Ordner befindet, wenn Sie auf „Home“<br />

klicken. Wenn Sie fertig sind, „unmounten“ Sie<br />

die SD-Karte und stecken Sie diese in Ihren<br />

<strong>Raspberry</strong> <strong>Pi</strong>.<br />

Linux kann das Windows- und Mac-Dateisystem<br />

ohne die Installation von Zusatzsoftware problemlos<br />

auslesen.<br />

6 Alternativ-Installation<br />

Es gibt eine weitere Methode, Raspbian auf eine<br />

SD-Karte zu schreiben. Da diese allerdings relativ<br />

gefährlich für den Inhalt anderer Datenträger sein<br />

kann, sollten Sie diesen Weg nur gehen, wenn<br />

die anderen nicht verfügbar sind. Bei dieser Methode<br />

müssen Sie über die Kommandozeile arbeiten<br />

und das dd-Kommando verwenden. Dieser<br />

Befehl kopiert die Daten quasi „roh“, also Byte<br />

für Byte. Wenn Sie sich hier mit der Zieleingabe<br />

vertun, wird Ihre wichtigste Festplatte schlimmstenfalls<br />

mit einem unbrauchbaren Raspbian-<br />

Image überschrieben. Nehmen Sie die SD-Karte<br />

aus dem System und starten Sie das Terminal<br />

von Ubuntu. Dieses ermöglicht nun die Kommandozeileneingabe.<br />

Tippen Sie tail -f /var/log/<br />

syslog ein, und stecken Sie die SD-Karte in den<br />

Rechner. Halten Sie nach einem Systemevent mit<br />

der Schreibweise sdb: sdb1 Ausschau. Dies bedeutet,<br />

dass eine neue Festplatte erkannt wurde,<br />

in diesem Fall die eingelegte SD-Karte. Es werden<br />

vermutlich auch viele weitere Ausgaben angezeigt,<br />

da das Linux-System versucht, alle Inhalte<br />

auf der SD-Karte zu erfassen. Falls es „ge -<br />

mountet“ ist, sollten Sie es jetzt „unmounten“<br />

und dann den Befehl sudo dd bs=1M if=<br />

raspbian.img of=/dev/sdX eingeben. Sie müssen<br />

jedoch den *.img-Dateinamen durch die korrekte<br />

Beschriftung des Image-Files ersetzen und<br />

den /dev/sdX-Node um Ihre eigenen Spezifikationen<br />

ergänzen. <strong>Das</strong> Image wird jetzt auf die SD-<br />

Karte geschrieben, ganz ohne Desktop-Befehle.<br />

Sie können den dd-Befehl durch die Tastenkombination<br />

STRG+C abbrechen.<br />

53


Projekte<br />

Zünde den<br />

<strong>Raspberry</strong>-Booster<br />

Als die ersten Exemplare des <strong>Raspberry</strong><br />

<strong>Pi</strong> Ende Februar 2012 in den<br />

Vorverkauf gingen, ahnten die<br />

Schöpfer des Mini-Computers recht schnell,<br />

dass sie einen Nerv getroffen hatten. <strong>Das</strong><br />

Interesse war von Beginn an gewaltig, die<br />

Erstauflage von 10.000 Stück stand zwanzigmal<br />

so vielen Vorbestellungen gegenüber.<br />

Ab Mitte April 2012 wurde dann endlich<br />

ausgeliefert, und die Produktion wurde hochgefahren,<br />

um die immer weiter steigende<br />

Nachfrage bedienen zu können. Im September<br />

2012 waren 500.000, im Februar 2013<br />

1 Million Einheiten des <strong>Raspberry</strong> <strong>Pi</strong> verkauft.<br />

Bis Ende 2013 fanden weit über 2 Millionen<br />

Exemplare des kleinen Rechners einen Käufer,<br />

was sogar die optimistische Prognose des<br />

Entwicklerteams noch übertraf. Man kann<br />

ohne Übertreibung sagen, dass dieser Erfolg<br />

in den letzten Jahren einzigartig gewesen ist.<br />

Abseits dieser beeindruckenden Zahlen ist<br />

jedoch die Tatsache an sich, dass der <strong>Raspberry</strong><br />

<strong>Pi</strong> Anklang bei Computer-Fans in aller<br />

Welt findet, durchaus nicht so erstaunlich,<br />

denn für etwa 35 Euro bekommt man einen<br />

voll funktionsfähigen Linux-Rechner mit ARM-<br />

Ben Everard zückt den (nicht nur)<br />

virtuellen Lötkolben und zeigt Ihnen, was<br />

Sie mit dem <strong>Pi</strong> so alles anstellen können.<br />

Prozessor und 512 MB RAM (jedenfalls in der<br />

ab Oktober 2012 ausgelieferten Modellvariante)<br />

in den Abmessungen einer Kreditkarte.<br />

<strong>Das</strong> Ziel der <strong>Raspberry</strong>-<strong>Pi</strong>-Schöpfer um<br />

Eben Upton war es, die IT-Ausbildung in Großbritannien,<br />

die nicht mehr am Puls der Zeit<br />

war, zu revolutionieren. Ob dieses Ziel dereinst<br />

erreicht wird, ist noch nicht abzusehen,<br />

doch eines lässt sich mit Sicherheit schon<br />

heute sagen: Die Welt der Hobbyschrauber im<br />

Computerbereich ist nicht mehr dieselbe wie<br />

zuvor! Die winzigen, aber voll funktionsfähigen<br />

Geräte sind perfekt dazu geeignet, überall<br />

dort eingesetzt zu werden, wo Stromversorgung<br />

und räumliche Verhältnisse begrenzende<br />

Faktoren sind – und natürlich auch dort, wo<br />

Geld gespart werden muss.<br />

<strong>Raspberry</strong> <strong>Pi</strong>s sind bereits ins Weltall und<br />

über den Ozean geschickt worden, sie werden<br />

als Steuerungseinheiten von Robotern,<br />

Sicher heitssysteme und für alle möglichen<br />

Experimente eingesetzt, und der Einfallsreichtum<br />

der <strong>Pi</strong>-Enthusiasten kennt schier keine<br />

Grenzen.<br />

54


Distributionen<br />

Es gibt etliche Distributionen (Betriebssystemvarianten)<br />

für den <strong>Raspberry</strong> <strong>Pi</strong>,<br />

und laufend kommen neue hinzu. Auf<br />

dieser Seite stellen wir einige der wichtigsten<br />

„Distros“ vor.<br />

Eine Distribution wird auf dem <strong>Raspberry</strong> <strong>Pi</strong><br />

etwas anders installiert als auf einem normalen<br />

<strong>PC</strong>. Da die Software beim <strong>Pi</strong> von einer SD-Karte<br />

aus läuft, braucht man das Betriebssystem und<br />

weitere Programmpakete nur auf diese Karte zu<br />

schreiben. Am einfachsten ist das mit dem Befehlszeilen-Tool<br />

dd zu bewerkstelligen. Mit diesem<br />

Kommando erzeugt man Bit-für-Bit-Kopien<br />

von Daten zwischen Geräten und Dateien. Distributionen<br />

werden als Image-Dateien zur Verfügung<br />

gestellt, die gegebenenfalls noch entpackt<br />

werden müssen und auf einen Datenträger geschrieben<br />

werden können. Die Befehle lauten:<br />

sudo dd if= of= bs=4k<br />

sudo sync<br />

Die zweite Zeile sorgt dafür, dass die gesamten<br />

Daten auf die Karte geschrieben werden<br />

und nicht in irgendwelchen Zwischenspeichern<br />

hängen bleiben. Benutzt man beispielsweise<br />

einen <strong>PC</strong> mit zwei Festplatten sda und sdb, so<br />

wäre die SD-Karte dev/sdc. Sollten Sie<br />

unsicher über den Gerätenamen Ihrer SD-Karte<br />

sein, lassen Sie sich durch Eingabe von df -h in<br />

die Befehlszeile eine Liste aller Geräte<br />

ausgeben.<br />

Um eine Sicherheitskopie Ihres <strong>Raspberry</strong>-<strong>Pi</strong>-<br />

Setups anzulegen, können Sie eine neue Image-<br />

Datei erzeugen, indem Sie die if- und of-Flags,<br />

die für Input und Output stehen, beim dd-Befehl<br />

umkehren:<br />

sudo dd if= of=<br />

bs=4k<br />

<strong>Das</strong> Image kann dann noch komprimiert werden,<br />

beispielsweise mit gzip oder bzip.<br />

+<br />

Raspbian<br />

Arch Linux<br />

Raspbian ist die Distribution, die<br />

von der <strong>Raspberry</strong> <strong>Pi</strong> Foundation<br />

offiziell empfohlen wird. Falls Sie<br />

keinen triftigen Grund haben, ein<br />

anderes Ssystem zu verwenden,<br />

können Sie ruhig zu Raspbian<br />

greifen. Es basiert auf Wheezy,<br />

der neuesten Version der beliebten<br />

GNU/Linux-Distribution Debian,<br />

und kann daher auf die umfangreichen<br />

Debian-Repositorys<br />

zurückgreifen. Die Standard-<br />

Desktopumgebung von Raspbian<br />

heißt LXDE, eine sehr schlanke,<br />

dadurch aber auch etwas spartanische<br />

Benutzeroberfläche. Wer<br />

mehr fürs Auge möchte, fährt mit<br />

Xfce vielleicht besser. Im Lieferumfang<br />

von Raspbian ist das<br />

praktische Konfigurationsprogramm<br />

raspi-config enthalten.<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> ist so konzipiert,<br />

dass auch Kinder mit ihm<br />

zurechtkommen, und diesem<br />

Ansatz folgt auch Raspbian.<br />

Bezugsquelle: raspberrypi.org<br />

Im Gegensatz zu Raspbian, das<br />

den Anwender eher vom internen<br />

Setup des Systems abschirmt,<br />

ist Arch Linux so konzipiert,<br />

dass es dem Anwender<br />

das Verständnis der<br />

Arbeitsweise des Systems<br />

erleichtert. <strong>Das</strong> Basis-Image<br />

enthält nur die nötigsten<br />

Komponenten, und alles<br />

Weitere kann man später je<br />

nach Wunsch hinzunehmen,<br />

was allerdings auch einiges an<br />

Arbeit (und natürlich jede<br />

Menge Erfahrung in der<br />

Zusammenstellung der<br />

Einzelteile einer Distribution)<br />

mit sich bringt. <strong>Das</strong> offizielle<br />

Wiki zu Arch Linux finden Sie<br />

auf archlinux.org.<br />

Bezugsquelle: raspberrypi.org<br />

Raspbmc<br />

Android<br />

Auch wenn der <strong>Raspberry</strong> <strong>Pi</strong><br />

im Hinblick auf Bildungszwecke<br />

konzipiert wurde, haben viele<br />

Bastler sehr schnell auch die<br />

Spiele- und Unterhaltungsmöglichkeiten<br />

des Geräts für sich<br />

entdeckt. Die Distribution Raspbmc<br />

verwandelt Ihren <strong>Raspberry</strong><br />

<strong>Pi</strong> in ein Medienzentrum, mit<br />

dem Sie Ihr Fernsehgerät steuern<br />

können.<br />

Raspbmc basiert auf XBMC,<br />

das es ermöglicht, Musik- und<br />

Videodateien aus Ihrem Fundus<br />

abzuspielen oder Inhalte aus<br />

dem Netz zu streamen.<br />

Mehr zu Raspbmc gibt es auf<br />

Seite 67 in diesem Heft.<br />

Bezugsquelle: raspbmc.com<br />

Vielleicht bleibt es nur ein frommer<br />

Wunsch, vielleicht wird es<br />

eines Tages Wirklichkeit: ein gut<br />

lauffähiges Android auf dem <strong>Raspberry</strong><br />

<strong>Pi</strong>. Von offizieller Seite wird<br />

inzwischen abgewunken, aber einige<br />

Fans versuchen weiterhin einen<br />

eigenen Ansatz, wobei jedoch<br />

alles ziemlich ruckelt und holpert.<br />

Falls sich etwas tut, werden Sie<br />

es auf razdroid.net erfahren.<br />

Bezugsquelle: Ask Google<br />

55


Projekte<br />

Raspbian<br />

+<br />

Für die meisten <strong>Pi</strong>-Benutzer wird Raspbian<br />

das „Gesicht“ ihres Geräts darstellen.<br />

Eine Schritt-für-Schritt-Anleitung<br />

zur Installation von Raspbian finden Sie auf<br />

Seite 16-21. Sie können das Betriebssystem<br />

sehr einfach auf dem neuesten Stand halten,<br />

wenn Sie mit den folgenden Befehlen<br />

Updates und Upgrades durchführen:<br />

sudo apt-get update<br />

sudo apt-get upgrade<br />

<strong>Das</strong> Konfigurationsprogramm raspi-config<br />

ist ein sehr nützliches Werkzeug, um Ihren<br />

<strong>Raspberry</strong> <strong>Pi</strong> optimal einzustellen. Es startet<br />

beim erstmaligen Booten des Geräts automatisch,<br />

kann aber ansonsten jederzeit mit<br />

der Eingabe des Befehls sudo raspi-config in<br />

die Kommandozeile aufgerufen werden. Eine<br />

genaue Übersicht über die Optionen, die<br />

Ihnen das Tool bietet, finden Sie auf Seite<br />

28-31, hier seien nur einige in aller Kürze<br />

herausgegriffen:<br />

expand_rootfs: <strong>Das</strong> Dateisystem von<br />

Rasp bian belegt nur 2 GB Speicherplatz.<br />

Falls Sie also eine größere SD-Karte benutzen,<br />

würde der ungenutzte Platz verfallen,<br />

oder aber Sie erweitern das Dateisystem<br />

mit dieser Option.<br />

memory_split: Der <strong>Pi</strong> verwendet denselben<br />

RAM-Speicher sowohl für seine CPU als auch<br />

für seine GPU. Mit dieser Option können Sie<br />

die Ressourcenaufteilung zwischen den beiden<br />

Chips verändern.<br />

overclock: 50 % mehr Prozessorleistung!<br />

Ja, und wie? Schauen Sie in den Kasten<br />

unten auf dieser Seite.<br />

boot_behaviour: Hier können Sie einstellen,<br />

dass der <strong>Raspberry</strong> <strong>Pi</strong> direkt in<br />

die grafische Benutzeroberfläche booten<br />

soll.<br />

Die Installationssoftware von Raspbian<br />

umfasst nicht allzu viele Tools. Was Sie<br />

vermissen, können Sie jedoch nachinstallieren.<br />

Die benötigten Pakete finden Sie<br />

in den umfangreichen Debian-Repositorys.<br />

Falls Sie Ihre Softwareverwaltung lieber<br />

auf einer grafischen Oberfläche vornehmen,<br />

empfehlen wir ihnen das Paketmanager-Interface<br />

Synaptic. Installieren Sie<br />

es mit<br />

sudo apt-get install synaptic<br />

und öffnen Sie es über die Einstellungsoptionen<br />

im LXDE-Menü.<br />

12 coole <strong>Raspberry</strong>-Projekte<br />

Wie alle guten Distributionen enthält natürlich<br />

auch Raspbian eine Auswahl süchtig machender<br />

Zeitfresser wie etwa Squirrels hier im Bild.<br />

1 Ein Kindle als Bildschirm: www.ponnuki.net/2012/09/kindleberry-pi<br />

2 <strong>Pi</strong>-Supercomputer (aus Lego): http://bit.ly/OGBGfD<br />

3 Steuerung einer Arduino-Plattform über das Web: http://bit.ly/Xyjsld<br />

4 Bau eines Synthesizers: www.raspberrypi.org/archives/1878<br />

5 Roboterfahrzeug mit Nachtsichtgerät: www.aonsquared.co.uk/the_dark_pi_rises<br />

6 Solar-Datenlogging mit dem <strong>Raspberry</strong> <strong>Pi</strong>: http://bit.ly/MHwCHF<br />

7 Echtzeitübersetzung: www.willpowell.co.uk/blog/?p=219<br />

8 <strong>Pi</strong> in einem Wetterballon hoch über der Erde: www.daveakerman.com/?p=592<br />

9 Bierbrauanlage: http://bit.ly/PSfdzr<br />

10 <strong>Pi</strong> als Retro-Spielekonsole: http://petrockblog.wordpress.com/retropie<br />

11 Wie man ein Betriebssystem baut: www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os<br />

12 <strong>Pi</strong> als Erinnerungsfoto-Drucker: http://bit.ly/PvmWjF<br />

Overclocking<br />

Der Prozessor unter der Haube des <strong>Raspberry</strong><br />

<strong>Pi</strong> ist dafür ausgelegt, mit einer Taktung von<br />

700 MHz zu arbeiten. <strong>Das</strong> bedeutet, er führt<br />

700.000.000 Rechenoperationen pro Sekunde<br />

aus. Allerdings bedeutet „dafür ausgelegt“ nicht,<br />

dass man diesen Wert nicht noch steigern<br />

könnte. <strong>Das</strong> kann man nämlich.<br />

Damit einher geht allerdings ein höherer<br />

Stromverbrauch, woraus wiederum eine größere<br />

Wärmeentwicklung resultiert. Hier muss man<br />

etwas aufpassen, denn dadurch kann die<br />

Platine beschädigt werden.<br />

Praktischerweise enthält das Konfigurationswerkzeug<br />

des <strong>Raspberry</strong> <strong>Pi</strong>, raspi-config, eine<br />

Option (jedenfalls in den Programmversionen<br />

seit Ende 2012), bei der man das Overclocking<br />

(Übertakten) schrittweise einstellen kann und<br />

gleichzeitig die erlaubte Wärmeentwicklung<br />

gedeckelt ist. Da es sich um ein offizielles Tool<br />

des Herstellers handelt, erlischt durch das Overclocking<br />

auch nicht die Garantie des Geräts<br />

(wie das bei Eigenmaßnahmen der Fall wäre).<br />

<strong>Das</strong> Konfigurationsprogramm rufen Sie mit<br />

dem Befehl sudo raspi-config in der Kommandozeile<br />

auf, suchen Sie dort dann die Option overclock.<br />

Es gibt mehrere Einstellungsschritte bis<br />

zu einer Mehrleistung von 50 %. Sollten Sie im<br />

übertakteten Modus Stabilitätsprobleme bei<br />

Ihrem <strong>Raspberry</strong> <strong>Pi</strong> feststellen, starten Sie ihn<br />

neu und drücken Sie während des Bootens die<br />

Shift-Taste, um das Overclocking zu<br />

deaktivieren.<br />

Falls Sie die Temperatur des Prozessors in<br />

konkreten Werten angezeigt bekommen möchten,<br />

können Sie der LXDE-Oberfläche ein Temperatur-Widget<br />

hinzufügen. So oder so schaltet<br />

sich das Overclocking automatisch aus, sobald<br />

eine Temperatur von 85 Grad Celsius erreicht<br />

wird.<br />

Die Übertaktung des <strong>Pi</strong>-Prozessors führt zu<br />

einem Mehr an Stromverbrauch, und das kann<br />

sich auf die Stabilität der Rechenleistung<br />

auswirken.<br />

56


Raspbmc<br />

Falls Sie Ihren <strong>Raspberry</strong> <strong>Pi</strong> im Sinne<br />

eines Computers für den allgemeinen<br />

Gebrauch mit gelegentlicher Medienwiedergabe<br />

verwenden, können Sie einen<br />

Media-Player wie VLC auf dem Raspbian-<br />

Betriebssystem installieren und sind vermutlich<br />

damit gut versorgt. Die geringe<br />

Größe und der geräuschfreie Betrieb des<br />

<strong>Raspberry</strong> <strong>Pi</strong> machen diesen aber auch zum<br />

perfekten Kandidaten für die Einrichtung<br />

eines persönlichen Entertainment-Centers.<br />

Ein solches Projekt lässt sich sicher auch<br />

auf der Grundlage von Raspbian umsetzen,<br />

aber wenn Sie sich die Arbeit nicht machen<br />

möchten, können Sie direkt auf ein vorgefertigtes<br />

Media-Betriebssystem namens<br />

Raspbmc zurückgreifen. <strong>Das</strong> geht so:<br />

Laden Sie das Installationsprogramm<br />

von der offiziellen Website raspbmc.com<br />

herunter, kopieren Sie es auf den <strong>Pi</strong> (wozu<br />

ein funktionierendes Raspbian notwendig<br />

ist), und geben Sie Folgendes ein:<br />

sudo python install.py<br />

Im Zuge der Installation werden die<br />

Daten auf Ihrer SD-Karte gelöscht. Sichern<br />

Sie also zuvor alles Wichtige. Nachdem das<br />

Installationsprogramm durchgelaufen ist,<br />

führen Sie einen Neustart des Systems<br />

durch. Sobald die grafische Oberfläche lädt,<br />

sehen Sie sofort den Unterschied:<br />

Raspbmc verwendet den beliebten XBMC-<br />

Media-Desktop, der sich ziemlich vom<br />

schlichten Design der Raspbian-Standardoberfläche<br />

LXDE unterscheidet. Sie können<br />

mit Raspbmc Medien abspielen, die lokal<br />

auf Ihrem Gerät gespeichert sind, aber<br />

Die Platinen der neueren Variante des <strong>Raspberry</strong><br />

<strong>Pi</strong> (Revision 2) besitzen Befestigungslöcher,<br />

damit das Gerät elegant untergebracht<br />

werden kann.<br />

Dies ist die Standardoptik der Fernbedienungsfunktion von Raspbmc, aber Sie können bei den<br />

Settings ein anderes Design einstellen.<br />

auch Inhalte aus dem Internet streamen,<br />

wofür Sie dann allerdings spezielle Add-ons<br />

brauchen.<br />

Lokale Musik- und Videodateien können<br />

entweder von einem USB-Speichergerät<br />

geladen werden oder per FTP (mit den<br />

üblichen Logindaten „pi“ und „raspberry“)<br />

direkt von der SD-Karte.<br />

Je nachdem, über welchen Anschluss<br />

(Audio-Ausgang mit 3,5-mm-Klinkenbuchse<br />

oder HDMI-Buchse) sie das Tonsignal senden<br />

möchten, müssen Sie bei den Systemeinstellungen<br />

noch zwischen analog und<br />

HDMI wählen.<br />

Bliebe noch die Frage, wie Sie Ihr Fernsehgerät<br />

vom <strong>Raspberry</strong> <strong>Pi</strong> aus ansteuern.<br />

Mit Tastatur und Maus könnte das auf die<br />

Dauer ein wenig unbequem werden. Die<br />

Entwickler von XBMC haben darum einen<br />

Fernbedienungsmodus eingebaut. Am einfachsten<br />

und sichersten lässt sich das mithilfe<br />

der Weboberfläche von Raspbmc bewerkstelligen<br />

– so können Sie mit jedem<br />

Gerät, das sich im selben Netzwerk befindet<br />

und auf dem ein Webbrowser installiert<br />

ist, die Wiedergabe steuern. Dieser Modus<br />

ist standardmäßig eingestellt, das heißt,<br />

Sie benötigen nur noch die IP-Adresse Ihres<br />

<strong>Raspberry</strong> <strong>Pi</strong>, um diesen von einem anderen<br />

Gerät aus per Webbrowser ansprechen<br />

zu können. Die IP-Adresse finden Sie unter<br />

System > System Info.<br />

Sie können für die Fernsteuerung auch<br />

ein Android- oder iOS-Mobilgerät benutzen.<br />

Hierzu sind diverse Anwendungen in den jeweiligen<br />

App Stores zu finden.<br />

Für Fortgeschrittene<br />

Wenn man möchte, kann man sogar seinen<br />

gesamten Fernsehkonsum – auch das Anschauen<br />

von TV-Sendungen direkt aus dem<br />

Live-Programm und die Aufzeichnung von<br />

Sendungen – per Linux steuern. Dies geht<br />

mittels MythTV (Bezugsquelle: mythtv.org),<br />

wobei ein separater Computer mit TV-Anschluss<br />

als Server fungieren muss. Leider<br />

ist MythTV dafür bekannt, dass die Installation<br />

extrem kompliziert ist.<br />

Sie können auch Videos abspielen, die<br />

auf anderen Geräten innerhalb Ihres Netzwerks<br />

gespeichert sind, zum Beispiel auf<br />

einem Dateiserver. Die genaue Vorgehensweise<br />

kann sich dabei je nach <strong>Hardware</strong><br />

und Datentyp unterscheiden. Konsultieren<br />

Sie am besten das XBMC-Wiki unter<br />

http://bit.ly/OOvXb6.<br />

57


Projekte<br />

Kamera-Controller<br />

Sichern Sie Ihre Fotoaufnahmen mithilfe des <strong>Raspberry</strong> <strong>Pi</strong>.<br />

Da der <strong>Raspberry</strong> <strong>Pi</strong> so klein ist, eignet<br />

er sich hervorragend dafür, andere eingebettete<br />

Systeme zu steuern. Man<br />

könnte zwar meinen, das wäre überflüssig,<br />

da die eingebetteten Systeme selbst ja bereits<br />

eine eigene Steuereinheit besitzen, aber<br />

mit dem <strong>Pi</strong> haben wir die Möglichkeit, den<br />

entsprechenden Geräten neue Funktionen<br />

angedeihen zu lassen, die sie aus eigener<br />

Kraft nicht (oder nur mit viel Aufwand) bewältigen<br />

könnten. Fast alles, was man an einen<br />

normalen Desktop-<strong>PC</strong> anschließen kann,<br />

lässt sich auch vom <strong>Pi</strong> mit einem Skript ansprechen,<br />

doch in unserem Beispiel wählen<br />

wir eine Digitalkamera als Versuchsobjekt<br />

aus, und zwar aus zwei Gründen: Erstens<br />

unterstützt Linux beinahe jede Kamera, und<br />

zweitens gibt es eine Menge nützlicher Anwendungen,<br />

die man mit dem <strong>Pi</strong> und einer<br />

Kamera durchführen kann, sobald man das<br />

Grundkonzept verinnerlicht hat.<br />

<strong>Das</strong> beste Befehlszeilen-Tool für die Steuerung<br />

von Digitalkameras, das unter Linux zu<br />

haben ist, heißt gPhoto2. Holen Sie es sich<br />

mit folgendem Kommando:<br />

apt-get install gphoto2<br />

Bevor wir in die Einzelheiten unseres Projekts<br />

gehen, beschäftigen wir uns kurz mit<br />

diesem nützlichen Werkzeug und seinen<br />

Fähig keiten. Da die grafische Benutzeroberfläche<br />

des <strong>Raspberry</strong> <strong>Pi</strong> möglicherweise versuchen<br />

würde, die Kamera als Ressource<br />

einzubinden, und dies gPhoto2 vor einige Probleme<br />

stellen würde, ist es ratsam, den <strong>Pi</strong><br />

ohne den grafischen Desktop hochzufahren.<br />

Stromversorgung<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> bezieht seine Stromversorgung<br />

über den Micro-USB-Port. Dieser liefert eine<br />

Spannung von 5 V, und die <strong>Raspberry</strong> <strong>Pi</strong> Foundation<br />

empfiehlt eine Stromstärke von mindestens<br />

700 mA. Diese kann problemlos von einem<br />

Netzteil oder per USB-Verbindung von einem<br />

anderen Computer zur Verfügung gestellt werden.<br />

Dies können Sie im Konfigurationsprogramm<br />

raspi-config einstellen. Öffnen Sie dieses mit<br />

dem Befehl sudo raspbi-conf, wählen Sie<br />

beim Punkt boot_behaviour „No“, um den <strong>Pi</strong><br />

ohne Desktop hochzufahren (siehe auch<br />

Seite 31), und booten Sie erneut.<br />

„Der <strong>Pi</strong> eignet sich hervorragend<br />

dafür, andere eingebettete<br />

Systeme zu steuern.“<br />

Sie befinden sich nun in der Nur-Text-<br />

Steuerungsumgebung des <strong>Pi</strong>. Schließen Sie<br />

die Kamera an und tippen Sie:<br />

gphoto2 --auto-detect<br />

Dieses Kommando führt dazu, dass nach<br />

Kameras gesucht wird, die mit dem <strong>Pi</strong> verbunden<br />

sind. Die allermeisten Digitalkameras<br />

werden unterstützt. Sollten Sie jedoch das<br />

seltene Pech haben, dass gerade Ihr Modell<br />

nicht auf der Liste steht, haben Sie leider<br />

keine Möglichkeit, es auf dem <strong>Pi</strong> zu<br />

Mithilfe eines kleinen Skripts können Sie den <strong>Raspberry</strong> <strong>Pi</strong> automatisch Fotos von einer<br />

Digitalkamera herunterladen lassen.<br />

Wenn Sie den <strong>Pi</strong> als portables Gerät benutzen<br />

möchten, gibt es andere Optionen. Vier AA-<br />

Batterien sollten – eine adäquate Verbindung<br />

zum Gerät vorausgesetzt – genügend Strom zur<br />

Verfügung stellen. Am besten gefiel uns jedoch<br />

die Variante, einen Ersatzakku für Smartphones<br />

direkt am <strong>Raspberry</strong> <strong>Pi</strong> einzustecken.<br />

aktivieren, sondern müssen auf eine andere<br />

Kamera ausweichen, wenn Sie den Versuch<br />

durchführen möchten.<br />

Da die unterstützten Kameras sich in Ihren<br />

Steuerungsmöglichkeiten voneinander unterscheiden,<br />

müssen wir zunächst etwas über<br />

die spezifischen Gegebenheiten<br />

des verwendeten Modells herausfinden.<br />

Mit dem Kommando<br />

gphoto2 --auto-detect --abilities<br />

lassen Sie sich die verfügbaren<br />

Aktionen anzeigen. Grundsätzlich<br />

gibt es zwei verschiedene<br />

Gruppen von steuerbaren Aktionen:<br />

Capture (Aufnahme) sowie Upload/Download.<br />

Falls Aufnahmeaktionen möglich sind – was<br />

in der Regel eher bei höherwertigen Kameras<br />

der Fall ist –, kann man mittels Skriptbefehlen<br />

Fotos schießen. Upload/Download bedeutet,<br />

dass Bilder, die auf der Speicherkarte<br />

archiviert sind, weiterverarbeitet werden können<br />

– diese Aktionsart ist bei den meisten<br />

unterstützten Kameras verfügbar.<br />

Im Rahmen dieses Projekts beschränken<br />

wir uns auf die Upload/Download-Funktionen.<br />

<strong>Das</strong> simpelste Kommando, dass wir einer<br />

Kamera übermitteln können, ist die Anweisung,<br />

alle gespeicherten Fotos zu<br />

übertragen:<br />

gphoto2 --auto-detect --get-all-files<br />

Damit werden alle Dateien von der Kamera<br />

in das aktuelle Verzeichnis heruntergeladen.<br />

Bei einem normalen <strong>PC</strong> wäre das problemlos<br />

möglich, doch beim <strong>Raspberry</strong> <strong>Pi</strong> sollte man<br />

angesichts des begrenzten Speicherplatzes<br />

auf der SD-Karte die Fotos lieber auf einem<br />

anderen Medium wie zum Beispiel einem<br />

USB-Stick speichern. Um dies in einer interaktiven<br />

Sitzung durchzuführen, könnte man<br />

den USB-Stick einfach mithilfe eines Tools<br />

mit grafischer Benutzeroberfläche einhängen,<br />

dann den Befehl df -h ausführen, um den Einhängepunkt<br />

festzustellen, und schließlich mittels<br />

cd in das entsprechende Verzeichnis<br />

wechseln.<br />

58


Da das Ganze jedoch automatisch vonstattengehen<br />

wird, müssen wir den Ort des Geräts<br />

kennen. Es gibt mehrere Möglichkeiten,<br />

diesen festzumachen, aber wir werden es<br />

einfach halten. Wir hängen die erste Partition<br />

der ersten seriellen Platte ein und speichern<br />

die Bilder dort.<br />

Wir gehen davon aus, dass Sie den Standardnutzer<br />

„pi“ verwenden, andernfalls müssen<br />

Sie das Skript entsprechend anpassen.<br />

Zunächst müssen wir einen Einhängepunkt<br />

für das Laufwerk festlegen. Es handelt sich<br />

dabei lediglich um einen Ordner, und dieser<br />

kann an einer beliebigen Stelle angelegt werden.<br />

Wir weichen hier von der Konvention ab<br />

und erstellen den Ordner im Home-Verzeichnis<br />

– wie folgt:<br />

mkdir /home/pi/pic_mount<br />

Danach können wir mit dem Skript beginnen.<br />

Mit diesem werden wir das Laufwerk<br />

einhängen und die Fotos herunterladen:<br />

#!/bin/bash<br />

if mount /dev/sda1 /home/pi/pic_mount ;<br />

then<br />

echo „Partition mounted“<br />

cd /home/pi/pic_mount<br />

yes ‚n‘ | gphoto2 --auto-detect<br />

--get-all-files<br />

umount /dev/sda1<br />

else<br />

echo „/dev/sda1 could not be mounted“<br />

fi<br />

Der Befehl yes ‚n‘ gibt lediglich eine Reihe<br />

von n Zeichen aus, das heißt, wenn mit<br />

gphoto2 eine zuvor heruntergeladene Datei<br />

überschrieben werden soll, wird dies zurückgewiesen.<br />

<strong>Das</strong> umount ist unabdingbar, da<br />

es dafür sorgt, dass das Laufwerk korrekt<br />

synchronisiert wird und dann entfernt werden<br />

kann.<br />

Wir nennen das Skript get-pics.sh und<br />

speichern es im Home-Verzeichnis des <strong>Raspberry</strong><br />

<strong>Pi</strong> ab. Um es ausführbar zu machen,<br />

geben Sie ein:<br />

chmod +x /home/pi/get-pics.sh<br />

Sie sollten das Skript nun manuell starten<br />

können. Dabei müssen Sie sudo verwenden,<br />

Netzwerkverbindung<br />

Einen <strong>Raspberry</strong> <strong>Pi</strong> mit dem Internet zu verbinden,<br />

bewerkstelligen Sie (jedenfalls beim Modell B) am<br />

einfachsten über ein Ethernet-Kabel. In Fällen, wo<br />

eine Kabelverbindung unpraktisch ist (und generell<br />

beim Modell A, das keinen Ethernet-Anschluss<br />

besitzt), bietet sich ein USB-Wireless-Adapter als<br />

drahtlose Alternative an. Diesen können Sie mit<br />

Ihrem Router verbinden, aber es ist auch möglich,<br />

ein Smartphone als Modem einzusetzen. Falls<br />

diese Funktion (Tethering) nicht vom Telefonanbieter<br />

gesperrt worden ist, können Sie zum<br />

Beispiel bei einem Android-Mobilgerät dessen<br />

WLAN- oder 3G-Verbindung mit dem <strong>Pi</strong> teilen.<br />

da das Skript das Laufwerk einhängen muss.<br />

Der letzte Schritt besteht darin, das Skript<br />

automatisch ausführen zu lassen. Dazu<br />

fügen wir es der Datei etc/rc.local hinzu.<br />

<strong>Das</strong> Skript startet während des Bootvorgangs<br />

und läuft unter Root, darum brauchen wir uns<br />

keine Gedanken über irgendwelche Berechtigungen<br />

zu machen. Öffnen Sie einfach die<br />

Datei als Root mit einem Texteditor,<br />

beispielsweise mit dem Befehl sudo nano /<br />

etc/rc.local, und fügen Sie<br />

/home/pi/get-pics.sh<br />

///end code///<br />

direkt vor der Zeile exit 0 ein.<br />

Jetzt brauchen Sie nur noch Ihre Kamera<br />

anzuschließen (und einzuschalten!) und den<br />

USB-Stick einzustecken, und schon werden<br />

Ihre Fotos automatisch während des Bootvorgangs<br />

auf den Stick kopiert.<br />

Ausblick<br />

Statt die Fotos auf einem USB-Stick zu speichern,<br />

könnten Sie sie auch zu einem Online-<br />

Dienst wie Flickr hochladen (siehe dazu Seite<br />

106-109). Sie könnten auch eine Art Schalter<br />

einbauen, mithilfe dessen Sie Ihrem <strong>Raspberry</strong><br />

<strong>Pi</strong> mitteilen, welche Fotos er uploaden und<br />

welche er auf den USB-Stick speichern soll,<br />

beispielsweise in Abhängigkeit von der Bildauflösung:<br />

kleine Bilddateien auf Flickr hochladen<br />

und große speichern.<br />

Dabei müssen Sie aber nicht stehen bleiben.<br />

Wenn Sie einen Wireless-Dongle an den<br />

<strong>Pi</strong> anschließen, könnten Sie den Rechner als<br />

HTTP-Server verwenden. Mithilfe von PHP<br />

oder einer anderen webgeeigneten Skriptsprache<br />

ist es möglich, eine Schnittstelle zu<br />

gPhoto2 einzurichten, über die man sich per<br />

Smartphone mit dem Gerät verbinden kann.<br />

Schließlich könnten Sie sich – sofern Ihre<br />

Kamera dies unterstützt – auch der erwähnten<br />

anderen Gruppe steuerbarer Aktionen zuwenden,<br />

nämlich Capture, und mithilfe des<br />

<strong>Raspberry</strong> <strong>Pi</strong> die Fotoaufnahme auslösen.<br />

gPhoto2 bietet noch viele weitere Features, auf die wir hier nicht näher eingehen, beispielsweise Javaund<br />

Python-Anbindung. Infos dazu gibt es auf der Projekt-Website www.gphoto.org.<br />

Sofern Ihr Mobilfunkvertrag eine Begrenzung des<br />

Datenvolumens vorsieht, sollten Sie dies allerdings<br />

im Hinterkopf behalten, wenn Sie mit dem<br />

<strong>Pi</strong> größere Dateien aus dem Netz herunterladen.<br />

Aktivieren Sie das Tethering auf Ihrem Mobilgerät<br />

(bei den WLAN- und Netzwerkeinstellungen),<br />

und verbinden Sie es mit dem <strong>Raspberry</strong> <strong>Pi</strong>. Auf<br />

dem <strong>Pi</strong> tippen Sie sudo ifconfig in die Kommandozeile,<br />

dann sollte die Schnittstelle als usb0<br />

angezeigt werden, allerdings ohne IP-Adresse.<br />

Netzwerkschnittstellen kontrollieren Sie auf dem<br />

<strong>Pi</strong> mithilfe der Datei /etc/network/interfaces.<br />

Standardmäßig existiert darin kein Eintrag für<br />

USB-Networking, darum müssen Sie einen solchen<br />

Eintrag selber vornehmen. Öffnen Sie die<br />

Datei als sudo mit einem Texteditor, etwa mit<br />

dem Befehl sudo nano /etc/network/interfaces,<br />

und fügen Sie dort die folgenden Zeilen hinzu:<br />

iface usb0 inet dhcp<br />

nameserver 208.67.220.220<br />

nameserver 208.67.222.222<br />

Es handelt sich hierbei um allgemeine Nameserver<br />

des Unternehmens OpenDNS, es stehen aber auch<br />

Alternativen zur Verfügung. Nach einem Neustart<br />

werden die Änderungen wirksam, und Ihr <strong>Raspberry</strong><br />

<strong>Pi</strong> sollte mit dem Internet verbunden sein!<br />

59


Projekte<br />

LED-Anzeige<br />

Die GPIO-<strong>Pi</strong>ns des <strong>Raspberry</strong> <strong>Pi</strong> und was man mit ihnen machen kann.<br />

Da der <strong>Raspberry</strong> <strong>Pi</strong> so klein ist, eignet<br />

er sich hervorragend dafür, andere<br />

eingebettete Systeme zu steuern. Ja,<br />

das hatten wir schon, aber es bleibt richtig<br />

und zeigt die Vielseitigkeit dieses Wunder -<br />

winzlings.<br />

Es gibt allerdings ein kleines Problem, und<br />

das ist, dass man nicht erkennen kann, was<br />

gerade im <strong>Raspberry</strong> <strong>Pi</strong> vor sich geht, wenn<br />

man ihn „headless“ betreibt, also ohne angeschlossenen<br />

Monitor und Tastatur. An eine<br />

mögliche Lösung dieses Problems haben die<br />

<strong>Pi</strong>-Entwickler jedoch bereits gedacht: Der<br />

Rechner ist mit einer Reihe GPIO-<strong>Pi</strong>ns ausgestattet.<br />

Dies sind Kontaktstifte mit integrierten<br />

Schaltkreisen zur Allzweckein- und<br />

-ausgabe.<br />

Die insgesamt 26 GPIO-<strong>Pi</strong>ns befinden sich<br />

<strong>Das</strong> ohmsche Gesetz<br />

am Rand der Platine, zwischen dem Video-<br />

Ausgang und dem Anschluss für die SD-<br />

Karte. Die Schaltkreise können Informationen<br />

von beliebigen Quellen ausgeben, doch in<br />

diesem Beispiel werden wir sie dazu benutzen,<br />

das letzte Byte (entspricht dem vierten<br />

„Wenn man die falschen<br />

Kontakte verbindet, kann<br />

man den <strong>Pi</strong> zerstören!“<br />

Zahlenblock) der aktuellen IP-Adresse des<br />

Geräts anzuzeigen. Dies ist nützlich, wenn<br />

man den <strong>Raspberry</strong> <strong>Pi</strong> per Fernzugriff steuern<br />

möchte, aber keine statische IP-Adresse einrichten<br />

kann – etwa, weil das Gerät in<br />

GND <strong>Pi</strong>n 7 <strong>Pi</strong>n 8 <strong>Pi</strong>n 25 <strong>Pi</strong>n 23<br />

A<br />

B<br />

C<br />

D<br />

E<br />

F<br />

G<br />

H<br />

I<br />

J<br />

1 5 10 15 20 25 30<br />

1 5 10 15 20 25 30<br />

Abbildung 1: Hier Sehen Sie, wie wir die einzelnen Bauteile auf einer Steckplatine angeordnet<br />

haben. Die übrigen vier LEDs werden in gleicher Weise verdrahtet.<br />

verschiedenen Netzwerken eingesetzt wird.<br />

Die ersten drei Bytes (oder Zahlenblöcke) der<br />

IP-Adresse lassen sich meist mithilfe der<br />

Netzmaske herausfinden, doch das letzte<br />

Byte ist oft schwierig zu ermitteln, wenn kein<br />

Monitor angeschlossen ist.<br />

Für unser Projekt benötigen wir<br />

das Programm gpio, das ein Element<br />

der Wiring<strong>Pi</strong>-Bibliothek darstellt. Vertiefende<br />

Informationen dazu sind<br />

unter http://bit.ly/RP8UKJ zu finden.<br />

Da die Software als Quellcode<br />

zur Verfügung gestellt wird, müssen<br />

Sie sie zunächst entpacken und kompilieren.<br />

tar xvf wiring<strong>Pi</strong>.tgz<br />

cd wiring<strong>Pi</strong>/wiring<strong>Pi</strong><br />

make<br />

sudo make install<br />

cd ../gpio<br />

make<br />

sudo make install<br />

Außerdem brauchen wir noch bc:<br />

sudo apt-get install bc<br />

So viel zur Software, nun ist die <strong>Hardware</strong><br />

an der Reihe. Zuvor jedoch ein warnender<br />

Hinweis: Wenn man die falschen Kontakte<br />

miteinander verbindet, kann man dem <strong>Raspberry</strong><br />

<strong>Pi</strong> den Garaus machen! Vergewissern<br />

Sie sich daher lieber zweimal, ob Sie den<br />

richtigen Draht in der Hand haben, bevor Sie<br />

etwas zusammenlöten oder -stecken.<br />

Die Schaltung ist bei unserem Versuch<br />

sehr simpel: Wir müssen jeden Output mit<br />

dem Pluspol (dem langen Anschlussstift)<br />

einer LED verbinden, den Minuspol (den kurzen<br />

Stift) jeder LED mit einem elektrischen<br />

Widerstand von 1 kOhm und das andere<br />

Ende jedes Widerstandes erden (siehe Abbildung<br />

3). Die einzelnen Bauteile haben wir auf<br />

einer Steckplatine angeordnet (siehe Abbildung<br />

1).<br />

Wenn Sie alles zusammengebaut und mit<br />

dem <strong>Pi</strong> verbunden haben, können Sie mit der<br />

Elektrizität wird in zwei physikalischen Größen<br />

gemessen: Spannung und Stromstärke. Die<br />

Spannung – die in Volt (V) gemessen wird – ist<br />

die Menge Energie, die eine bestimmte Anzahl<br />

von Elektronen besitzt, während die Stromstärke<br />

– die in Ampere (A) gemessen wird – die Menge<br />

an Elektronen angibt, die einen Punkt passiert.<br />

Im ohmschen Gesetz wird ein Zusammenhang<br />

zwischen den beiden Größen hergestellt:<br />

Spannung = Stromstärke x Widerstand (oder als<br />

Formel: U = IR). Sie können dieses Gesetz anwenden,<br />

um zu verhindern, dass Ihr <strong>Raspberry</strong> <strong>Pi</strong> zu<br />

Toast wird, indem zu viel Strom in ihn hineinfließt.<br />

<strong>Das</strong> Setup des <strong>Pi</strong> ist in dieser Hinsicht recht komplex.<br />

Gert van Loo, einer der Entwickler des Geräts,<br />

erklärt es unter http://bit.ly/Qp4PMl ausführlich.<br />

Aber als Faustregel lässt sich sagen, dass 3,3 V<br />

und 16 mA das Maximum an Output und Input bei<br />

einem GPIO-<strong>Pi</strong>n sind. Nach dem ohmschen Gesetz<br />

errechnet sich daraus ein Widerstand von 206,25<br />

Ohm, der mindestens gegeben sein muss, damit<br />

der <strong>Raspberry</strong> <strong>Pi</strong> nicht beschädigt wird. Sie sollten<br />

jedoch einen Sicherheitsabstand von den erwähnten<br />

Werten einhalten, um das Gerät keiner Gefahr<br />

auszusetzen. In unseren Schaltungen haben wir<br />

einen Widerstand von 1.000 Ohm benutzt, also<br />

sozusagen einen Sicherheitsfaktor von 5 eingebaut.<br />

60


Programmierung beginnen. Für den Anfang<br />

nehmen wir uns nur den letzten <strong>Pi</strong>n vor, dies<br />

ist <strong>Pi</strong>n Nr. 7 (die Nummerierung der <strong>Pi</strong>ns folgt<br />

nicht der Reihenfolge ihrer Anordnung). Öffnen<br />

Sie die Befehlszeile, und setzen Sie den<br />

<strong>Pi</strong>n auf Output:<br />

gpio -g mode 7 out<br />

Nun können Sie den <strong>Pi</strong>n aktivieren:<br />

gpio -g write 7 1<br />

Und deaktivieren:<br />

gpio -g write 7 0<br />

Jetzt können wir uns das komplette Skript<br />

vornehmen. Es besteht aus vier Teilen. Der<br />

erste sorgt lediglich dafür, dass sich die einzelnen<br />

<strong>Pi</strong>ns im korrekten Modus befinden<br />

und ausgeschaltet sind:<br />

pins=“7 8 25 24 23 18 15 14“<br />

for x in $pins<br />

do<br />

gpio -g mode $x out<br />

gpio -g write $x 0<br />

done<br />

Im zweiten Teil wird mithilfe von ifconfig<br />

die IP-Adresse des <strong>Pi</strong> ausgelesen, ins Binärformat<br />

umgewandelt und gegebenenfalls mit<br />

Führungsnullen aufgefüllt.<br />

ipaddress=‘ifconfig eth0 | grep ‚inet ‚ |<br />

awk ‚{print $2}‘ | cut -f4 -d‘.‘‘<br />

binary=‘echo<br />

„ibase=10;obase=2;$ipaddress“ | bc‘<br />

paddedBinary=‘printf %08d $binary‘<br />

Im dritten Teil extrahieren wir mittels cut-<br />

Befehl den gewünschten Teil aus dem Binärstring<br />

und leiten die Information an den zuständigen<br />

<strong>Pi</strong>n weiter.<br />

bit=1<br />

for x in $pins<br />

do<br />

out=‘echo $paddedBinary | cut -b$bit‘<br />

gpio -g write $x $out<br />

bit=$((bit+1))<br />

done<br />

Im letzten Teil weisen wir das Skript an,<br />

5 Minuten lang zu schlafen und dann die<br />

Offizielles Zubehör: Gertboard<br />

Indem Sie eine direkte Verbindung mit den GPIO-<br />

<strong>Pi</strong>ns Ihres <strong>Raspberry</strong> <strong>Pi</strong> herstellen, erlangen Sie<br />

eine einfache Eingabe- und Ausgabekontrolle,<br />

doch diese ist in den Möglichkeiten begrenzt.<br />

Es gibt jedoch ein sehr interessantes Zubehör<br />

für den <strong>Pi</strong>, das Sie einsetzen können, um die<br />

Interaktion sehr viel genauer zu gestalten.<br />

<strong>Das</strong> Zubehör heißt Gertboard. Es handelt sich<br />

um ein umfassendes Erweiterungsset, das<br />

jedoch in der Basisausttattung aus Einzelteilen<br />

<strong>Pi</strong>n 7 <strong>Pi</strong>n 8 <strong>Pi</strong>n 25 <strong>Pi</strong>n 24<br />

LEDs auszuschalten.<br />

sleep 5m<br />

for x in $pins<br />

do<br />

gpio -g write $x 0<br />

done<br />

<strong>Das</strong> war es auch schon. Erstellen Sie die<br />

Datei showIP.sh, und machen Sie sie zu<br />

einer ausführbaren Datei:<br />

chmod a+x showIP.sh<br />

Geben Sie sudo ./showIP.sh ein, um die<br />

IP-Adresse anzeigen zu lassen. Um das Programm<br />

beim Booten automatisch starten zu<br />

<strong>Pi</strong>n 7 <strong>Pi</strong>n 8 <strong>Pi</strong>n 25 <strong>Pi</strong>n 24 <strong>Pi</strong>n 23 <strong>Pi</strong>n 18 <strong>Pi</strong>n 15 <strong>Pi</strong>n 14 GND<br />

Abbildung 2: Verbinden Sie die Steckplatine mit den hier gezeigten <strong>Pi</strong>ns. Wir haben handelsübliche<br />

einpolige Stecker verwendet, Sie können aber auch zum Lötkolben greifen.<br />

GND<br />

besteht und selbst zusammengebaut werden<br />

muss (es gibt aber auch vorgefertigte Gertboards<br />

zu kaufen). Es ist ideal zum Experimentieren<br />

geeignet, da es unter anderem mit einem Arduino<br />

(Micro-Controller), LEDs, A/D- und D/A-Wandler<br />

sowie Schaltern ausgestattet ist. Es kann direkt<br />

in den <strong>Raspberry</strong> <strong>Pi</strong> eingestöpselt werden.<br />

Der Namensgeber des Gertboards ist Gert van<br />

Loo, der entscheidend an der Entwicklung des<br />

<strong>Raspberry</strong> <strong>Pi</strong> beteiligt war.<br />

<strong>Pi</strong>n 23 <strong>Pi</strong>n 18 <strong>Pi</strong>n 15 <strong>Pi</strong>n 14<br />

Abbildung 3: Hier eine schematische Darstellung unseres Schaltplans. GND steht für die Erdung.<br />

lassen, müssen Sie in rc.local noch folgende<br />

Zeile einfügen (siehe dazu auch Seite 69):<br />

/home/pi/showIP.sh &<br />

Sie haben nun gesehen, wie Sie mithilfe<br />

der GPIO-<strong>Pi</strong>ns Output erzeugen können. Sie<br />

können aber, da die <strong>Pi</strong>ns sowohl der Aus- als<br />

auch der Eingabe dienen, ebenso gut Input<br />

verarbeiten. Dabei ist es allerdings noch wichtiger,<br />

dass nicht zu viel Strom in die <strong>Pi</strong>ns hineinfließt.<br />

Um einen Kontaktstift von Output<br />

auf Input umzuschalten, müssen sie dessen<br />

Modus mit gpio -g mode in<br />

ändern und den Wert mit gpio -g read auslesen.<br />

Da unsere Schaltung beliebige acht Bits<br />

an Information darstellen kann, brauchen Sie<br />

sich nicht auf die Anzeige der IP-Adresse zu<br />

beschränken. Es wäre beispielsweise denkbar,<br />

den Kamera-Controller von Seite 68-69<br />

zu modifizieren, indem Sie die LEDs dessen<br />

Aktivität anzeigen lassen.<br />

Sehr detaillierte Informationen zu allen<br />

26 GPIO-<strong>Pi</strong>ns des <strong>Raspberry</strong> <strong>Pi</strong> erhalten Sie<br />

unter http://bit.ly/JTlFE3. Die <strong>Pi</strong>ns, die wir<br />

mit unserem Skript benutzt haben, haben in<br />

Revision 1 und Revision 2 des <strong>Raspberry</strong> <strong>Pi</strong><br />

die gleiche Funktion, allerdings sind einige<br />

der restlichen <strong>Pi</strong>ns beim Wechsel der Revisionen<br />

anders belegt worden. Falls Sie eigene<br />

Schaltpläne entwickeln oder welche aus dem<br />

Internet nachbauen, vergewissern Sie sich,<br />

dass sie mit der korrekten <strong>Pi</strong>n-Belegung<br />

arbeiten.<br />

61


Arch Linux<br />

Kann eine sich schnell ändernde, manchmal kaputte,<br />

rasant vorpreschende Distribution ein ernsthafter<br />

Mitbewerber sein? Zeit, das zu untersuchen.<br />

Wissen Sie, was ein Ricer ist? Ricer<br />

sind Leute, die ihre Autos mit<br />

riesigen Spoilern, gigantischen<br />

Auspuffen, teuren Radfelgen und<br />

ähnlichem Schnickschnack aufmotzen, wobei<br />

all diese Modifikationen jedoch so gut wie<br />

keinen Effekt auf die tatsächliche Leistung des<br />

Fahrzeugs haben.<br />

Als Anfang der 2000er Jahre Gentoo Linux<br />

in Fahrt kam, tauchte eine neue Art von<br />

Ricer am Horizont auf: der Linux-Ricer. Die<br />

Linux-Ricer trieben das quellcodebasierte<br />

Design von Gentoo auf die Spitze und investierten<br />

endlose Arbeitsstunden in das Feintuning<br />

der Compiler-Optionen, nur um gedit<br />

0,05 % schneller starten zu lassen. Gentoo<br />

war (und ist immer noch) eine großartige<br />

Distribution, aber das Verhalten einiger<br />

Fans, die jeden anpöbeln, weil er „langsame“<br />

Binärpakete nutzt, verliehen dem Betriebssystem<br />

einen schlechten Ruf. Gentoo war außerdem<br />

– eine Neuheit in jener Zeit – eine Rolling-<br />

Release-Distribution: Während für fast alle<br />

anderen Distributionen ein bis zwei Mal im<br />

„Arch simplifiziert nichts,<br />

Sie haben von Anfang an<br />

alles unter Kontrolle.“<br />

Jahr ein großes Update mit vielen Änderungen<br />

anstand, wurde Gentoo kontinuierlich mit kleinen<br />

Aktualisierungen versorgt. Man konnte<br />

Gentoo zu jedem Zeitpunkt updaten und erhielt<br />

dabei die volle Packung aus der Welt der<br />

freien Software, ohne eine zeitaufwendige Überholung<br />

des gesamten Systems durchführen zu<br />

müssen.<br />

Wie auch immer: Anno 2014 ist Gentoo immer<br />

noch am Leben, doch viele Anhänger des Rolling-<br />

Release-Ansatzes sind zu Arch Linux<br />

(archlinux.org) übergelaufen. Die Distributionen<br />

sind sich in Vielem ähnlich, auch<br />

wenn Arch auf einem System aus Binärpaketen<br />

basiert. Die Aushängeschilder der<br />

Distribution sind ihre Einfachheit, die Geschwindigkeit,<br />

mit der Pakete aktualisiert<br />

werden, sowie die Tatsache, dass sie<br />

nichts simplifiziert: Sie haben von Anfang an alles<br />

unter Kontrolle. Arch hat vermutlich genauso<br />

viele leidenschaftliche Befürworter wie Kritiker.<br />

Lassen Sie uns mal nachsehen, was innerhalb<br />

dieses Projekts so alles passiert.<br />

62


Projekte<br />

<strong>Das</strong> Arch-Konzept<br />

Arch beherzigt das KISS-Prinzip („Keep it simple (and)<br />

stupid“, also „Halte es einfach (und) schlicht“) und<br />

setzt dieses mit einem recht minimalen und leichtgewichtigen<br />

Basissystem um, das für Nutzer einen guten Startpunkt<br />

für eigene Anpassungen und das Hinzufügen von Paketen<br />

bietet.<br />

Arch versucht nicht, Vermutungen anzustellen, was Ihnen<br />

gefallen könnte, sondern sagt, „Hier ist die Basis, nimm sie<br />

und baue die Linux-Distribution, die du haben möchtest.“<br />

Ebenso versucht Arch, es so weit wie möglich zu vermeiden,<br />

Software zu patchen. Manche Distributionen nehmen den<br />

Original-Quellcode und fügen einen Patch nach dem anderen<br />

hinzu, womit sich das Resultat über kurz oder lang stark von<br />

der ursprünglichen Version unterscheidet. <strong>Das</strong> macht nicht<br />

nur alles komplexer (alle Patches synchron zu halten), es<br />

kann auch schwerer werden, einen Bug in der offiziellen Version<br />

zu melden.<br />

Während Arch großes Gewicht auf die Einfachheit legt,<br />

schlägt sich dies nicht unbedingt in der Benutzerfreundlichkeit<br />

nieder. Sie werden bei Arch kaum distributionsspezifische<br />

Einrichtungsassistenten oder Einstellungswerkzeuge<br />

finden: Diese werden als separate und unnötige Schicht der<br />

Abstraktion empfunden. Stattdessen werden Sie dazu aufgefordert,<br />

Verantwortung zu übernehmen und Linux in seinem<br />

aufgeräumten und reinen Zustand zu erforschen, indem Sie<br />

die bei fast allen Linux-Distributionen gängigen Werkzeuge<br />

benutzen. Hier passt eine leicht veränderte Faustformel, welche<br />

bereits bei Slackware häufig benutzt wurde: „Benutze<br />

Ubuntu, und du lernst Ubuntu. Benutze Red Hat, und du<br />

lernst Red Hat. Benutze Arch, und du lernst Linux“.<br />

Wer gibt den Ton an?<br />

Sie haben nun also eine Distribution, die minimalistisch und<br />

weitestgehend ungepatcht ist, die zum Erforschen einlädt<br />

und – zugegeben – eine steile Lernkurve hat. Die Entwicklung<br />

von Arch findet ziemlich dezentral statt. Laut Allan McRae,<br />

der zum Arch-Kernteam gehört, existiert keine richtige Hierarchie<br />

unter den Arch-Entwicklern, auch wenn diejenigen, die<br />

schon lange dabei sind und viel beigetragen haben, sich oft<br />

mehr Gehör verschaffen können.<br />

Aber was, wenn wichtige Entscheidungen getroffen werden<br />

müssen, die die Aufmachung von Arch drastisch verändern?<br />

Varianten von Arch<br />

Hierzu sagt McRae: „<strong>Das</strong> Treffen von Entscheidungen ist bei<br />

Arch meist nichts weiter als die Feststellung der Abwesenheit<br />

von Einwänden. Wir gehen gemeinhin davon aus, dass die<br />

Person, die an einer bestimmten Komponente arbeitet, auch<br />

diejenige ist, die sich damit am besten auskennt. Bei tiefgreifenderen<br />

Entscheidungen kann das jedoch viele weitere Fragen<br />

nach sich ziehen, bis die letzten Zweifel der anderen Entwickler<br />

ausgeräumt sind.“<br />

Ein Beispiel dafür ist der Umstieg auf systemd. McRae erzählte<br />

uns, dass dieser Prozess kontinuierlich vonstatten ging,<br />

beginnend mit einem Entwickler, der experimentelle Pakete<br />

erstellte, gleich nachdem das neue Boot-System freigegeben<br />

worden war. Der Entwickler zweifelte, ob systemd je Einzug in<br />

Arch finden würde. Aber als die Zeit fortschritt, begann Arch,<br />

der Einfachheit halber die gleichen Konfigurationsdateien zu<br />

nutzen. „Nach einer Weile stellten wir fest, dass viele Programme<br />

die systemd-Dienstdateien integrierten und dass<br />

viele Arch-Entwickler auf systemd umsteigen mussten. <strong>Das</strong><br />

führte zu einem Vorschlag auf einer Mailingliste, formell auf<br />

systemd umzusteigen und initscripts fallen zu lassen.“<br />

Die meisten der verbleibenden Arch-Entwickler stiegen<br />

auf systemd um, und die auf der Mailingliste vorherrschende<br />

Meinung war, dass es sich um die technisch bessere Lösung<br />

handelt. „Die Änderungen wurden aufgrund fehlender Einwände<br />

gemacht“, erklärt McRae, und es ist diese technische,<br />

begründungsbasierte Herangehensweise, die viele Arch-<br />

Fans mögen. Große Entscheidungen werden umsichtig getroffen,<br />

sobald jeder das Pro und Contra des Vorschlags abgewogen<br />

hat.<br />

Die Installation<br />

von Arch ist eine<br />

langwierige und<br />

komplizierte Aufgabe,<br />

besonders<br />

im Vergleich zu<br />

anderen Distributionen.<br />

Der<br />

Vorgang ist aber<br />

außergewöhnlich<br />

gut dokumentiert.<br />

Seit der Einführung von Arch im Jahr<br />

2002 sind mehrere Distributionen<br />

erstellt worden. Die meisten zielen<br />

darauf ab, Arch ein wenig aufzupolieren<br />

und benutzerfreundlicher zu<br />

machen. Hier eine Auswahl:<br />

Manjaro (manjaro.org) ist in<br />

mehreren Abwandlungen erhältlich<br />

und deckt die meisten Desktop-<br />

Umgebungen ab. Manjaro hat<br />

einen eigenen Paketmanager und<br />

Konfigurationstools und benutzt<br />

den Installer von Linux Mint.<br />

Chakra (chakra-project.org) ist<br />

ein Vorzeigeprodukt für den aktuellen<br />

KDE-Desktop. Chakra hat einen<br />

„halben“ Rolling-Release-Zyklus:<br />

Während das Basissystem langsamer<br />

als bei traditionellen Distributionen<br />

aktualisiert wird, werden Desktop-<br />

Anwendungen weit öfter gepflegt.<br />

ArchBang (archbang.org) ist<br />

eine einfache, leichtgewichtige Distribution,<br />

bei der X und der Openbox-<br />

Fenstermanager vorinstalliert sind.<br />

Es wird alle paar Monate aktualisiert.<br />

Der Installer von Chakra schmeichelt dem Auge,<br />

genauso wie der Rest der Distribution.<br />

63


Projekte<br />

Arch im Detail<br />

Da es bei Arch Linux keine Release-Versionen in dem<br />

Sinne gibt, neue Nutzer jedoch eine praktikable Möglichkeit<br />

brauchen, es auf ihren Rechner zu bekommen,<br />

veröffentlicht das Arch-Team jeden Monat ein frisches<br />

Installer-Image. Dieses ist etwa 520 MB groß und enthält nur<br />

die notwendigste Software, um den Rechner zu booten.<br />

Alles Weitere können Sie später mit Pacman herunterladen.<br />

<strong>Das</strong> ist auch der Punkt, an dem das Rolling Release ins<br />

Spiel kommt. <strong>Das</strong> Arch-Team empfiehlt die Verwendung von<br />

pacman -Syu alle ein bis zwei Wochen, um die Distribution<br />

über die Arch-Repositorys auf den aktuellen Stand zu<br />

bringen.<br />

Inzwischen laufen die Updates meist problemlos ab,<br />

manchmal gehen aber auch Dinge kaputt. Sie sollten sich<br />

dringend die News auf der Arch-<br />

„Ein falscher Befehl,<br />

und Sie könnten Ihr<br />

System ruinieren.“<br />

<strong>Das</strong> ArchServer-Projekt<br />

liegt<br />

leider auf Eis,<br />

aber vielleicht tut<br />

sich irgendwann<br />

wieder etwas<br />

bei dieser Initiative,<br />

die darauf<br />

abzielte, Arch für<br />

die Verwendung<br />

als Server-Betriebssystem<br />

stabiler<br />

zu machen.<br />

Website durchlesen, bevor Sie ein<br />

Update durchführen. <strong>Das</strong> ist eine<br />

der kontroverseren Eigenschaften<br />

von Arch Linux, im Grunde aber<br />

konsequent. Manchmal jedoch ist<br />

der Schaden so gravierend, dass<br />

man sich gut überlegen sollte, ob man Arch auf Produktivrechnern<br />

einsetzt.<br />

Stabilität versus Aktualität<br />

So kündigte das Arch-Team im Sommer 2013 an, ein vereinigtes<br />

Verzeichnis /usr/bin einzuführen und dafür /bin<br />

und /sbin zu entfernen – an sich ein aus Gründen der Übersichtlichkeit<br />

begrüßenswertes Vorhaben. Allerdings war der<br />

Aufwand der Nutzer, um die Änderung zu bewerkstelligen,<br />

alles andere als trivial. Sie mussten Dateien manuell hin und<br />

her kopieren, das System auf eine Vielzahl von Paketen hin<br />

überprüfen sowie Befehle wie diesen ausführen:<br />

paclist | awk ‘ { print $1 } ‘ | pacman -Ql - | grep ‘<br />

/s\?bin/\| /usr/sbin/’<br />

All das ist für fortgeschrittene Linux-Nutzer machbar,<br />

allerdings braucht es Zeit und eine Menge Konzentration.<br />

Ein falscher Befehl, und Sie könnten Ihr System ruinieren.<br />

Falls Sie Linux als Hobby betrachten und damit auf einem<br />

sonst unbenutzten Rechner herumspielen, ist das vertretbar,<br />

doch was ist, wenn Sie Linux auf der Arbeit einsetzen<br />

oder als Server? Ausfälle aufgrund derartiger Anpassungen<br />

kann man sich nicht leisten, ebenso wenig, dass Anwendungen<br />

danach nicht mehr funktionieren.<br />

Wenn man den größten Wert auf ein stabiles System<br />

legt, das sich wenig verändert und nur Flicken für kritische<br />

Sicherheitslücken erhält, ist man wohl bei Debian, RHEL<br />

oder CentOS am besten aufgehoben.<br />

Andererseits entgehen einem<br />

dann die Vorzüge eines Rolling-Release-Systems<br />

wie Arch Linux, wie<br />

zum Beispiel eine höhere Aktualität.<br />

<strong>Das</strong> Arch-Team ist sich dieses<br />

Problems jedoch bewusst und hat<br />

Schritte unternommen, es zu lindern.<br />

Die Distribution besitzt ein „linux-lts“-Paket,<br />

welches einen Kernel<br />

mit Langzeit-Unterstützung beinhaltet.<br />

Dieser ändert sich nicht so<br />

schnell wie der Kernel des Hauptzweigs<br />

von Arch Linux. Unter<br />

http://tinyurl.com/44alfmh finden<br />

Sie detaillierte Erklärungen, wie<br />

Sie die Stabilität einer Arch-Installation<br />

verbessern können.<br />

Was gehört wohin?<br />

Wie fast jede andere Linux-Distribution<br />

stellt auch Arch seine Software in diversen<br />

Repositorys zur Verfügung. Zwischen<br />

diesen wird sehr genau unterschieden:<br />

Core Die allerwichtigsten Pakete, um ein<br />

System zu starten, es mit dem Internet zu<br />

verbinden und ein kaputtes Dateisystem zu<br />

reparieren. Einige weniger wichtige, aber häufig<br />

genutzte Werkzeuge wie etwa OpenSSH<br />

sind ebenfalls dabei. Core hat die restriktivste<br />

Qualitätskontrolle aller Repositorys.<br />

Extra Was nach einem Repository voll<br />

mit optionaler Software klingt, enthält in<br />

Wirklichkeit fast die gesamte Software,<br />

deren Nutzung Sie gewohnt sind, wie etwa<br />

X.org, Firefox, KDE, Apache und so weiter.<br />

Community Pakete vom Arch User<br />

Repository (siehe unten), die ein positives<br />

Feedback erhalten haben.<br />

Testing Diese Pakete sind nicht für<br />

den Alltagsgebrauch zu empfehlen,<br />

da hier experimentelle Pakete landen,<br />

deren Bugs erst ausgebügelt werden<br />

müssen. Danach wandern die Pakete<br />

entweder nach Core oder nach Extra.<br />

Arch User Repository (AUR) Eine<br />

großartige Quelle seltener Software, die<br />

sich mitten in der Entwicklung befindet und<br />

noch nicht verpackt wurde oder aufgrund<br />

von Lizenzproblemen nicht in den anderen<br />

Repositorys untergebracht werden kann.<br />

Jeder darf bei AUR mitmachen, weshalb<br />

die Qualität der Software stark schwankt.<br />

64


Projekte<br />

<strong>Das</strong> sagen Admins<br />

Arch behauptet von sich, jeder Aufgabe gewachsen und<br />

eine ideale Distribution für Server zu sein, doch die<br />

Schilderungen auf den vorherigen Seiten lassen Zweifel<br />

daran aufkommen. Wir haben Allan McRae mit unseren Bedenken<br />

konfrontiert, und das Folgende ist seine Sicht der Dinge.<br />

Allan McRae: Der ausschlaggebende Faktor ist, wie gut der<br />

Administrator sich mit Arch auskennt. Da Arch ein Rolling Release<br />

ist, gibt es gelegentlich Update-Probleme. Wenn Sie<br />

nicht damit vertraut sind, wäre eine Distribution, die lediglich<br />

Sicherheits-Updates zur Verfügung stellt, besser für Sie geeignet.<br />

Die typische Antwort darauf, ob Arch gut als Server-<br />

Betriebssystem geeignet sei, lautet darum auch: „Nicht, wenn<br />

du fragen musst.“<br />

Ein weiterer zentraler Punkt ist, wo man Zeit investieren<br />

möchte. Arch erfordert immer wieder ein bisschen Zeit, um<br />

das System aktuell zu halten und Softwaretests durchzuführen,<br />

bevor Änderungen in das Produktivsystem übernommen<br />

werden können. Ein Sammel-Release stellt zwar Sicherheits-<br />

Updates zur Verfügung, die kaum Testaufwand mit sich bringen,<br />

doch dafür ist der Aufwand größer, wenn Sie ein Distributions-Update<br />

durchführen müssen. Weil Arch Linux nur eine<br />

oder einige wenige Komponenten auf einmal aktualisiert, kann<br />

es leichter sein, etwaige Probleme einem bestimmten Paket<br />

zuzuordnen, als es bei einem Distributions-Update der Fall ist.<br />

Auch wenn Sie einmal eine neue Version einer Software benötigen,<br />

etwa weil Sie ein neues Feature dringend brauchen, ist<br />

Arch klar im Vorteil.<br />

Was Sicherheits-Updates angeht, so gibt es bei Arch reguläre<br />

größere Updates und gelegentliche kleinere Patches dort,<br />

wo sie nötig sind. Es ist schwer zu sagen, was den Anwender<br />

einem größeren Sicherheitsrisiko aussetzt: das – oder eine<br />

Distribution, die stabile Softwareversionen nutzt, in Kombination<br />

mit rückportierten Sicherheitspatches. Ich warte noch<br />

darauf, dass jemand dies untersucht, damit Arch gegebenenfalls<br />

seine Sicherheitsstrategie anpassen kann.<br />

Berichte aus der Praxis<br />

So weit also die Perspektive eines der Hauptentwickler von<br />

Arch. Wichtig sind jedoch insbesondere auch die Erfahrungen<br />

der Nutzer. Wir haben bei einigen Administratoren nachgefragt,<br />

die Arch Linux auf Servern einsetzen.<br />

Paul Gideon Dann: Ich betreibe Arch Linux auf zwei Servern<br />

auf der Arbeit. Einer ist ein Vielzweck-Server, welcher einige<br />

interne Web-Apps hostet, den Serverraum überwacht und als<br />

Quellcode-Repository dient. Der andere Server ist ein Beowulf-Servercluster,<br />

an dem 36 Knoten für anspruchsvolle<br />

Rechenaufgaben hängen. Bis jetzt konnte ich keine nennenswerten<br />

Downtimes feststellen. Die Änderung am /usr-Verzeichnis<br />

war etwas kritisch, ging aber noch gut aus, auch<br />

wenn es bedeutete, von Legacy Grub auf Syslinux umzusteigen.<br />

Ich reboote das System alle ein bis zwei Monate, um den<br />

Kernel aktuell zu halten. Meist aber laufen die Systeme einfach<br />

durch.<br />

ich höre von einer kritischen Lücke in einer Komponente, die<br />

vom Internet aus erreichbar ist (etwa WordPress).<br />

Ich stelle nur sicher, dass die Downtimes am Freitag oder<br />

am Samstag erfolgen. Falls etwas schief geht, kann es öfter<br />

mal etwas mehr Zeit verschlingen, als das bei einer konventionellen<br />

Distribution der Fall wäre. Als Sicherheitsexperte weiß<br />

ich es zu schätzen, immer auf dem aktuellen Stand zu sein,<br />

genauso wie mehr Kontrolle darüber zu haben, was auf meinem<br />

System läuft. Ich habe die Angriffsfläche durch das Weglassen<br />

von Paketen, die ich niemals brauche, massiv<br />

verkleinert.<br />

Gene: Ich habe bereits mit Red Hat, Fedora und Arch Server<br />

betrieben. Arch ist aus meiner Sicht fraglos die beste Lösung<br />

für ein Server-System. Änderungen sind unvermeidlich, und<br />

bei Arch erreichen mich<br />

„Arch ist aus meiner Sicht<br />

fraglos die beste Lösung für<br />

ein Server-System.“<br />

die Änderungen in kleineren<br />

Portionen, sodass<br />

ich die Gelegenheit<br />

habe, sie eine nach der<br />

anderen abzuarbeiten<br />

(wie etwa die Migration<br />

zu systemd). Jede der Änderungen kann größer oder kleiner<br />

sein, doch bei Arch bekomme ich zumindest die Chance,<br />

mich immer nur auf eine zur selben Zeit konzentrieren zu<br />

müssen. Ohne einen Rolling Release muss ich alle paar Jahre<br />

(oder bei Fedora alle sechs bis neun Monate) eine Neuinstallation<br />

vornehmen, die alle Anpassungen beinhaltet.<br />

Ich teste alle Aktualisierungen zunächst auf einem Schattensystem,<br />

bevor ich sie auf dem Server selbst installiere. <strong>Das</strong><br />

ist die einzige vernünftige Vorgehensweise, egal welche Distribution<br />

man benutzt.<br />

Chris Down: Ich benutze Arch Linux nur in kleinen Produktivumgebungen<br />

und hatte nie irgendein Problem im Zusammenhang<br />

mit den Paketen. Die geringe Anzahl der Pakete reduziert<br />

das Fehlerrisiko.<br />

Dinge gehen auf Arch generell nicht einfach so kaputt,<br />

schließlich gibt es ja das Testing-Repository. Wenn etwas kaputt<br />

geht, passiert das normalerweise, weil jemand vor dem<br />

Update nicht auf Konfigurationsänderungen oder andere<br />

wichtige Details geachtet hat. Falls man sich nicht darum<br />

kümmert, was auf der Mailingliste und in den Repositorys<br />

passiert, wird das mit Arch Linux nicht gut ausgehen.<br />

Chester Wisniewski: Ich betreibe zwei produktive Arch-Server.<br />

Ich aktualisiere sie etwa zweimal pro Monat, es sei denn,<br />

65


Projekte<br />

System: Eigene<br />

Beim <strong>Raspberry</strong> <strong>Pi</strong> müssen Sie nicht einmal das Ende der Bootsequenz<br />

abwarten, bevor Sie an ihm herumbasteln können. John Lane zeigt Ihnen, wie<br />

Sie sich Ihre ganz persönliche Distribution zusammenstellen.<br />

auf dem <strong>Pi</strong>, und installieren Sie gegebenenfalls die nötigen<br />

Tools und Pakete:<br />

# pacman -Syu<br />

# pacman -S base-devel python2 git parted dosfstools<br />

In diesem Tutorial zeigen wir Ihnen, wie man ein individuelles<br />

Image für das <strong>Raspberry</strong>-<strong>Pi</strong>-Betriebssystem erstellt. Sie<br />

könnten ja den Wunsch verspüren, die Zusammenstellung<br />

der Pakete im Vergleich zu offiziellen Images zu ändern, die<br />

Konfiguration anzupassen und möglicherweise sogar den Kernel<br />

zu bearbeiten. Sie werden nach unserem Kurs in der Lage sein,<br />

das Image auf eine SD-Karte zu schreiben, um damit den <strong>Raspberry</strong><br />

<strong>Pi</strong> zu booten. Sie könnten aber auch einen Emulator verwenden,<br />

um das Image auf Ihrem <strong>PC</strong> zu booten. Da es zwar<br />

möglich ist, ein maßgeschneidertes Image direkt auf dem <strong>Pi</strong> zu<br />

erstellen, dies jedoch nur sehr langsam vonstattengehen würde,<br />

erklären wir Ihnen außerdem, wie Sie Ihren <strong>PC</strong> als Cross-Compiler<br />

verwenden oder auf ihm sogar ARM-Code ausführen können.<br />

Es ist zwar technisch kein Problem, auch an einem laufenden<br />

System Änderungen vorzunehmen, indem man einzelne Pakete<br />

hinzufügt oder entfernt, doch ist dies mit Risiken verbunden,<br />

denn ein einziger Fehler genügt unter Umständen, um einen Absturz<br />

herbeizuführen. Außerdem sind Änderungen am laufenden<br />

System schwieriger zu reproduzieren und vor allem zu automatisieren.<br />

Die Erstellung einer eigenen Distribution ist also aus unserer<br />

Sicht die weit bessere Möglichkeit.<br />

Um ein individuelles Betriebssystem-Image zu erzeugen, benötigen<br />

wir zunächst einmal bestimmte Werkzeuge. In diesem<br />

Tutorial verwenden wir Arch Linux als Ausgangspunkt, denn das<br />

ist eine tolle Distribution, die sowohl für den <strong>Raspberry</strong> <strong>Pi</strong> als<br />

auch für den <strong>PC</strong> erhältlich ist. Wir setzen an dieser Stelle voraus,<br />

dass Sie die neueste offizielle Version von Arch Linux samt<br />

Updates auf Ihrem <strong>Pi</strong> installiert haben. Booten Sie Arch Linux<br />

Wählen Sie Ihre Garnitur<br />

Der erste Schritt hin zu einem maßgeschneiderten Betriebssystem-Image<br />

ist die Überlegung, welche Dinge es enthalten soll.<br />

Eine gute Möglichkeit, sich der Auswahl anzunähern, ist es, bei<br />

der Standardausstattung von Arch Linux anzusetzen und auf<br />

dieser Basis Pakete zu entfernen oder bei Bedarf hinzuzufügen.<br />

Nicht erwünschte Kernel-Pakete sollten weggelassen und die<br />

speziellen <strong>Raspberry</strong>-<strong>Pi</strong>-Pakete ergänzt werden.<br />

Falls Sie individuelle Features einbauen möchten, müssen<br />

Sie einen eigenen Kernel zusammenstellen. Es kann außerdem<br />

sinnvoll sein, für Ihre Zwecke überflüssige Kernel-Funktionalitäten<br />

zu deaktivieren, um Platz zu sparen – besonders im Hinblick<br />

auf die beschränkten Speicherressourcen des <strong>Raspberry</strong> <strong>Pi</strong>.<br />

Da es auf die herkömmliche Weise über zehn Stunden dauern<br />

würde, den Kernel auf dem <strong>Pi</strong> zu kompilieren, ist eine Alternativmöglichkeit<br />

dringend erforderlich. Eine Variante ist die Verwendung<br />

eines Cross-Compilers. Eine andere bietet distcc, allerdings<br />

brauchen Sie auch bei diesem Client-Server-Tool einen<br />

Cross-Compiler, da der distcc-Server ARM-Code erzeugen muss.<br />

Die nachfolgenden Befehle demonstrieren, wie wir mithilfe<br />

von Pacman, dem Paketmanager von Arch Linux, die Paketliste<br />

der Basisgruppe holen, die unerwünschten Pakete löschen und<br />

die Pakete des <strong>Raspberry</strong>-<strong>Pi</strong>-Kernels sowie Firmware-Pakete hinzufügen.<br />

Sie können auch einen Texteditor benutzen, um damit<br />

weitere Pakete gemäß Ihren Vorstellungen zuzufügen (etwa<br />

OpenSSH) oder wegzunehmen.<br />

$ pacman -Sg base | awk ‘{print $2}’ | grep -v “^\<br />

(linux\|kernel\)” | tr ‘\n’ ’ ’ > base_packages<br />

$ sed -i -e ‘s/$/linux-raspberrypi linux-headers-raspberrypi<br />

raspberrypi-firmware/’ base_packages<br />

Nachdem Sie die Paketzusammenstellung festgelegt haben,<br />

müssen Sie die Pakete für das neue Image installieren. Mit<br />

mkarchroot geht das ganz leicht: Es installiert Pakete in ein<br />

Unterverzeichnis, welches Sie dann in ein Image umwandeln<br />

können.<br />

# mkarchroot archroot $(cat base_packages)<br />

Dieses Kommando erzeugt ein neues Unterverzeichnis<br />

namens archroot, das alles enthält, was für ein vollständiges<br />

System benötigt wird. Sie könnten es sogar mit chroot zum<br />

Root-Verzeichnis machen, und trotzdem würde alles weiter funktionieren.<br />

In der Tat ist dies der Weg, den Sie gehen würden,<br />

wenn Sie ein Root-Passwort setzen oder Benutzer hinzu fügen<br />

wollten.<br />

Wir erzeugen das System-Image in einer Datei. Sie könnten<br />

es auch direkt auf einer SD-Karte erstellen, doch ist es<br />

66


Projekte<br />

Distribution<br />

Innerhalb des Images arbeiten<br />

Manchmal ist es nützlich, innerhalb<br />

eines Dateisystem-Images wie archroot<br />

arbeiten zu können. Dies geht mithilfe<br />

von chroot, aber es ist ratsam, zuvor<br />

einige Teile des Dateisystems per<br />

Bind-Mount einzuhängen. Sie können<br />

dieses kleine Skript verwenden:<br />

#!/bin/bash<br />

mkdir -p $1/{dev/pts,proc}<br />

mount proc -t proc $1/proc<br />

mount devpts -t devpts $1/dev/pts<br />

chroot $1 /usr/bin/env -i<br />

TERM=“$TERM” /bin/bash --login<br />

umount $1/{dev/pts,proc}<br />

Der Prozessor-Emulator QEMU emuliert einen <strong>Raspberry</strong> <strong>Pi</strong>, der<br />

mit unserem Image Marke Eigenbau läuft.<br />

durchaus nützlich, das Image auf der Festplatte zu haben, da<br />

es dann schnell auf eine weitere Karte geschrieben werden<br />

kann oder sogar in einem Emulator zu booten geht, ohne dass<br />

es überhaupt auf irgendeine Karte geschrieben wurde. Der Kernel<br />

hat eine Loop-Funktionalität, mit deren Hilfe eine Datei wie<br />

eine physische Festplatte behandelt und partitioniert werden<br />

kann. <strong>Das</strong> Modul erzeugt einen normalen Geräteknoten in<br />

/dev, über den die Datei in dieser Weise angesprochen wird.<br />

<strong>Das</strong> Image muss groß genug sein, um das Dateisystem<br />

aufnehmen zu können, aber auch klein genug, um auf eine<br />

SD-Karte zu passen. Unser Image hat ein Volumen von 2 GiB,<br />

entspricht hinsichtlich seiner Größe also dem offiziellen Image.<br />

Stellen Sie sicher, dass das Loop-Modul des Kernels geladen<br />

wurde, generieren Sie die Datei, und erzeugen Sie ein Loop-<br />

Gerät dafür:<br />

# modprobe loop<br />

$ truncate -s 2G myimage<br />

$ device=$(losetup -f)<br />

# losetup $device myimage<br />

Wir verwenden losetup hier zweifach: erstens, um dem Loop-<br />

Gerät einen Gerätenamen (üblicherweise /dev/loop0) zuzuteilen,<br />

und zweitens, um es zu erzeugen (wir speichern den Gerätenamen<br />

in einer Variablen, um später darauf Bezug nehmen zu<br />

können). <strong>Das</strong> Image benötigt eine bestimmte Partitionierung:<br />

Die erste Partition muss FAT16 verwenden und die Bootdateien<br />

sowie das Kernel-Image enthalten, während die zweite Partition<br />

– mit ext4 – für das Root-Dateisystem benötigt wird. Falls Sie<br />

eine Austauschpartition wünschen, können Sie zu diesem<br />

Zweck noch eine dritte Partition einrichten. Die Boot-Firmware<br />

des <strong>Raspberry</strong> <strong>Pi</strong> hält nach einer MS-DOS-artigen MBR-Partitionstabelle<br />

Ausschau (anders als das BIOS eines <strong>PC</strong>s führt die<br />

Firmware keinen Bootloader aus dem MBR aus). Erzeugen Sie<br />

mit dem Kommando parted die Partitionstabelle auf der<br />

Image-Datei:<br />

# parted -s $device mktable msdos<br />

Wenn Sie Partitionen erstellen, ist es ratsam, diese mit den<br />

Erase Blocks der zu verwendenden SD-Karte in Übereinstimmung<br />

zu bringen. Bei den meisten Karten haben die Erase<br />

Blocks eine bevorzugte Größe von 4 MiB, doch Sie können das<br />

mit dem folgenden Befehl genau ermitteln:<br />

$ cat /sys/class/block/mmcblk0/device/preferred_erase_size<br />

Bei einer bevorzugten Größe von 4 MiB je Erase Block besteht<br />

alle 8.192 Sektoren eine Übereinstimmung (da die Sektoren<br />

je 512 Byte umfassen), daher sollten die Partitionen bei<br />

einem Sektor beginnen, dessen Nummer ein Vielfaches von<br />

8.192 darstellt: Der erste Erase Block beinhaltet die ersten<br />

8.192 Sektoren (0 bis 8.191), der zweite die nächsten (8.192<br />

bis 16.383) und so weiter. Der Sektor 0 ist der Partitionstabelle<br />

vorbehalten, darum muss die erste Partition mit Sektor 8.192<br />

beginnen.<br />

Eine gute Größe für die Boot-Partition wäre 40 MiB, dies entspricht<br />

81.920 Sektoren. <strong>Das</strong> ist ausreichend für die Bootdateien<br />

und stimmt überdies mit der Grenze eines Erase Blocks<br />

überein. Lassen Sie die Boot-Partition demzufolge mit Sektor<br />

8.192 beginnen und mit Sektor 90.111 (8.192 + 81.920 - 1)<br />

enden:<br />

# parted -s $device unit s mkpart primary fat32 8192 90111<br />

Reservieren Sie gegebenenfalls ein bisschen Platz für eine<br />

Austauschpartition (die SD-Karte dafür zu verwenden, wäre<br />

aus Geschwindigkeitsgründen nicht ratsam). Als ein Beispiel<br />

erzeugen wir eine Austauschpartition von 256 MiB (also<br />

524.288 Sektoren oder 64 Schreibblöcke).<br />

Unser 2-GiB-Image besteht aus 4.194.304 Sektoren, das<br />

heißt, der letzte Sektor trägt – da die Zählung bei 0 beginnt –<br />

die Nummer 4.194.303. Die Root-Partition kann den gesamten<br />

Speicherplatz zwischen der Boot-Partition und der Austauschpartition<br />

belegen und würde somit mit Sektor 90.112 beginnen<br />

und vor dem ersten Sektor der 256 MiB großen Austauschpartition<br />

enden. Heraus kommen also die folgenden Kommandos<br />

zur Partitionierung:<br />

# parted $device unit s mkpart primary ext2 90112 3670015<br />

Quick-<br />

Tipp<br />

Falls Sie ein 32-Bit-<br />

System verwenden,<br />

können Sie auf einen<br />

vorgefertigten Cross-<br />

Compiler bei den<br />

<strong>Raspberry</strong>-<strong>Pi</strong>-Tools<br />

zurückgreifen. Dieser<br />

heißt arm-bcm2708-<br />

linux-gnueabi und<br />

ist unter https://<br />

github.com/<br />

raspberrypi/tools<br />

zu finden.<br />

Quick-<br />

Tipp<br />

Holen Sie mehr<br />

aus Ihrem Mehrkernprozessor<br />

heraus: Beim Befehl<br />

make sorgt der<br />

Parameter -j dafür,<br />

dass gleichzeitig<br />

mehrere Prozesse<br />

gestartet werden.<br />

Geben Sie im Falle<br />

des Core i7 mit<br />

seinen vier Kernen<br />

(acht Threads) den<br />

Wert 8 ein.<br />

67


Projekte<br />

Quick-<br />

Tipp<br />

Falls Sie Yaourt<br />

noch nicht haben,<br />

finden Sie den<br />

Quellcode im Arch<br />

User Repository<br />

(AUR). Sie<br />

können sich das<br />

Selberbauen jedoch<br />

ersparen, wenn<br />

Sie das Paket aus<br />

einem inoffiziellen<br />

Repository<br />

verwenden: http://<br />

archlinux.fr/<br />

yaourt-en<br />

Quick-<br />

Tipp<br />

Die <strong>Raspberry</strong>-<strong>Pi</strong>-<br />

Utilities unseres<br />

Autors John Lane<br />

finden Sie unter<br />

https://github.<br />

com/johnlane/<br />

rpi-utils.<br />

# parted $device unit s mkpart primary linux-swap 3670016<br />

4194303<br />

Wenn Sie möchten, können Sie sich die Partitionstabelle mittels<br />

des Befehls parted -s $device unit s print ausdrucken. Als<br />

Nächstes generieren Sie die Dateisysteme. <strong>Das</strong> Loop-Gerät<br />

muss erneut erstellt werden, damit Geräteknoten für die Partitionen<br />

erzeugt werden (mithilfe der Option -P).<br />

# losetup -d $device<br />

# device=$(losetup -f)<br />

# losetup -P $device myimage<br />

Stimmen Sie die interne Struktur der Dateisysteme auf die<br />

Sektoren ab. Zur Abstimmung eines FAT-Dateisystems müssen<br />

Sie die Größe seiner Dateizuordnungstabelle (FAT) kennen. Sie<br />

müssen ein Dateisystem erstellen, um diese zu ermitteln:<br />

mkfs.vfat -I -F 16 -n boot -s 16 -v ${device}p1 | grep “FAT size”<br />

Um eine Übereinstimmung zu erzielen, erweitern Sie den reservierten<br />

Teil in der Weise, dass der Datenbereich an einer<br />

Blockgrenze beginnt. Die Größe des reservierten Bereichs sollte<br />

der Größe der Schreibblöcke abzüglich der beiden Dateizuordnungstabellen<br />

(FAT) entsprechen. Wenn wir unser Beispiel mit<br />

einer FAT-Größe von 32 Sektoren weiterführen, errechnet sich<br />

daraus ein reservierter Bereich von<br />

8.192 - 2 x 32 = 8.128 Sektoren. Erstellen Sie das Dateisystem<br />

erneut auf Grundlage dieser Information:<br />

mkfs.vfat -I -F 16 -n boot -s 16 -R 8128 -v ${device}p1<br />

Für die Root-Partition verwenden Sie bitte ein ext4-Dateisystem.<br />

Da bei ext4 die Erase Blocks lediglich 4 KiB groß sind,<br />

brauchen Sie diesmal keine Sektorenangaben zu machen:<br />

$ mkfs.ext4 -O ^has_journal -L root ${device}p2<br />

Mounten Sie die Dateisysteme und kopieren Sie die Dateien<br />

vom archroot-Unterverzeichnis an die richtige Stelle. Die Boot-<br />

Partition ist bei /boot auf der Root-Partition eingehängt, sodass<br />

Bootsequenz des <strong>Raspberry</strong> <strong>Pi</strong><br />

Der <strong>Raspberry</strong> <strong>Pi</strong> bootet anders als ein<br />

<strong>PC</strong>. Beim <strong>Pi</strong> wird der Prozess nicht vom<br />

ARM-Chip, sondern vom Grafikchip aus<br />

gestartet. Nach dem Einschalten initiiert<br />

die GPU den ersten Bootloader (ROM-Firmware),<br />

der dann weitere Stufen von der<br />

ersten (FAT16-formatierten) Partition der<br />

SD-Karte nachlädt. Der zweite Bootloader<br />

namens bootcode.ini wird im L2-Cache<br />

der GPU ausgeführt. Er lädt loader.bin,<br />

den Bootloader der dritten Stufe, ins RAM,<br />

dessen Aufgabe es ist, die GPU-Firmware<br />

Hier wird aus einem x86 plötzlich ein ARM!<br />

start.elf auszulesen. Die weiteren Dateien<br />

config.txt und cmdline.txt ermöglichen<br />

die Konfigurierung des Bootprozesses.<br />

Schließlich lädt start.elf das Kernel-Image<br />

von Linux namens kernel.img in den RAM-<br />

Speicher des ARM-Prozessors, der damit<br />

aktiviert ist. <strong>Das</strong> Image wird ausgeführt<br />

und der Linux-Bootprozess beginnt.<br />

Der klassische Master Boot Record (MBR)<br />

– Sektor 0 – der SD-Karte enthält lediglich<br />

die Partitionstabelle, und es wird – anders<br />

als beim <strong>PC</strong> – kein MBR-Code ausgeführt.<br />

die Bootdateien in der korrekten Partition platziert werden:<br />

# mount ${device}p2 /mnt<br />

# mkdir /mnt/boot<br />

# mount ${device}p1 /mnt/boot<br />

# (cd archroot ; cp -a * /mnt)<br />

# umount /mnt/boot /mnt<br />

Schreiben Sie nun das Image auf die SD-Karte. Falls Ihr<br />

Rasp berry <strong>Pi</strong> das Root-Dateisystem auf der Karte hat, müssen<br />

Sie das Image auf einen anderen Rechner mit einem Kartenlesegerät<br />

kopieren:<br />

# dd if=myimage of=/dev/mmcblk0 bs=4M<br />

Fahren Sie den <strong>Raspberry</strong> <strong>Pi</strong> herunter, stecken Sie die neue<br />

Karte ein, und booten Sie wieder. Alternativ können Sie das<br />

Image auch auf Ihren <strong>PC</strong> kopieren und es dort in einem Emulator<br />

laufen lassen.<br />

<strong>Das</strong> linux-raspberry-Paket, das wir in unserem Image Marke<br />

Eigenbau verwendet haben, enthält das offizielle Kernel-Image,<br />

doch es lässt sich relativ einfach anpassen. Sie benötigen dazu<br />

den Quellcode des Kernels sowie einen Compiler, um ein neues<br />

ausführbares Kernel-Image zu erzeugen.<br />

Ein Compiler generiert normalerweise ausführbaren Code für<br />

die CPU derselben Maschine, doch mithilfe eines Cross-Compilers<br />

ist es möglich, auch für den Prozessor eines anderen Geräts<br />

lauffähige Programme herzustellen. Der Cross-Compiler erlaubt<br />

es, die leistungsstärkere x86-<strong>Hardware</strong> zum Kompilieren<br />

des Codes für den ARM-Chip des <strong>Raspberry</strong> <strong>Pi</strong> zu benutzen,<br />

was deutlich schneller geht, als wenn man dies direkt auf dem<br />

<strong>Pi</strong> tun würde.<br />

Der normale Compiler trägt den Namen gcc, während der<br />

Cross-Compiler für ARM-<strong>Hardware</strong> arm-linux-gnueabi-gcc heißt.<br />

Letzterer befindet sich nicht in den Repositorys, aber man kann<br />

ihn mithilfe von yaourt leicht zusammenstellen:<br />

yaourt -S arm-linux-gnueabi-gcc<br />

Bei yaourt müssen Sie mehrere Eingabeaufforderungen beantworten.<br />

Wählen Sie „no“ bei der Frage, ob Sie das<br />

PKGBUILD editieren möchten, und „yes“, wenn das Tool wissen<br />

möchte, ob Sie ein Paket bauen oder installieren möchten.<br />

Hello world!<br />

Bevor wir weitermachen, sollten wir kurz den Cross-Compiler<br />

checken. Legen Sie eine neue Datei namens hello.c an:<br />

#include <br />

int main ()<br />

{<br />

printf(“Hello world!\n”);<br />

return 0;<br />

}<br />

Nun kompilieren Sie die Datei für die ARM-Architektur, und<br />

überprüfen Sie den Typus:<br />

$ arm-linux-gnueabi-gcc -o hello hello.c<br />

$ file hello<br />

hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV),<br />

dynamically linked (uses shared libs), for GNU/Linux 2.6.27,<br />

not stripped<br />

Wenn Sie die Datei auf Ihren <strong>Raspberry</strong> <strong>Pi</strong> verschieben, sollte<br />

sie sich ausführen lassen:<br />

$ ./hello<br />

Hello world!<br />

Wird diese Ausgabe angezeigt, dann wissen Sie, dass der<br />

Cross-Compiler funktioniert. Wenden wir uns also wieder dem<br />

Kernel zu:<br />

$ git clone --depth 1 git://github.com/raspberrypi/linux.git<br />

68


Projekte<br />

$ cd linux<br />

$ ssh root@alarmpi zcat /proc/config.gz > .config<br />

$ make -j 8 ARCH=arm CROSS_COMPILE=<br />

arm-linux-gnueabi- menuconfig -k<br />

Wir laden den Quellcode des Kernels von github herunter,<br />

wobei - -depth dafür sorgt, dass nur die neueste Version und<br />

keine vorherigen Varianten geholt werden. Danach kopieren Sie<br />

die aktuelle Kernel-Konfiguration des <strong>Raspberry</strong> <strong>Pi</strong> in eine Datei<br />

namens .config, öffnen diese im Kernel-Editor menuconfig, nehmen<br />

die gewünschten Änderungen vor und speichern die Datei.<br />

Sie sind nun in der Lage, den Kernel und dessen Module zu<br />

bauen:<br />

$ make -j 8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -k<br />

$ mkdir -p modules<br />

$ make -j 8 -k ARCH=arm CROSS_COMPILE=<br />

arm-linux-gnueabi-modules_install INSTALL_MOD_<br />

PATH=modules<br />

Wir haben außerdem ein neues Unterverzeichnis dafür angelegt.<br />

Nachdem das neue Image des Kernels und der Module<br />

erstellt worden ist, können Sie es auf den <strong>Pi</strong> überspielen und<br />

diesen dann neu booten (zuvor sollten Sie aber ein Backup des<br />

alten Kernels und der Module machen):<br />

$ scp arch/arm/boot/Image root@alarmpi:/boot/kernel.img<br />

$ cd modules/lib/modules<br />

$ tar cJf - * | ssh root@alarmpi ‘(cd /usr/lib/modules; tar xjf -)’<br />

$ ssh root@alarmpi reboot<br />

Alternativ können Sie alles auch in Ihrem archroot-Verzeichnis<br />

installieren, bevor Sie das Image erstellen. Kopieren Sie<br />

arch/arm/boot/Image nach archroot/boot/kernel.img sowie<br />

modules/lib/modules nach archroot/usr/lib.<br />

Emulator und Cross-Compiler<br />

Es ist ebenfalls möglich, das Image in einem ARM-Emulator<br />

laufen zu lassen und dadurch einen virtuellen <strong>Raspberry</strong> <strong>Pi</strong> auf<br />

Ihrem x86-<strong>PC</strong> zu betreiben. QEMU ist ein Prozessor-Emulator,<br />

der ARM-Code auf einem <strong>PC</strong> mit x86-Architektur interpretieren<br />

kann. Sie installieren QEMU mit pacman -S qemu. Erstellen Sie<br />

ein Verzeichnis und kopieren Sie das Image dorthin. Sie benötigen<br />

überdies ein Kernel-Image speziell für den Emulator: Verwenden<br />

Sie kernel-qemu – welches Sie in den Archiven finden<br />

–, und speichern Sie es am selben Ort wie Ihr Image. Nun können<br />

Sie den Emulator mit folgendem Kommando ausführen:<br />

qemu-system-arm -machine versatilepb -cpu arm1176 -m 256 \<br />

-no-reboot -serial stdio -kernel kernel-qemu \<br />

-append “root=/dev/sda2 panic=1” -hda myimage<br />

Mithilfe des Emulators kann man sogar ARM-Code direkt aus<br />

der Befehlszeile eines x86-Rechners ausführen. Hierbei macht<br />

das Programm sich ein Kernel-Feature namens binfmt_misc<br />

zunutze. Dazu sind jedoch Vorbereitungen nötig:<br />

# mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc<br />

<strong>Das</strong> ARM-Binärformat muss dem Kernel angegeben werden,<br />

damit dieser weiß, was er zu tun hat. Die Erkennung basiert auf<br />

Musterübereinstimmung am Anfang der Datei. Geben Sie ein:<br />

echo ‘:arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\<br />

x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\<br />

xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\<br />

xff:/usr/bin/qemuarm-static:’ > /proc/sys/fs/binfmt_misc/<br />

register<br />

Im Folgenden wird jeder Versuch, ARM-Binärcode auszuführen,<br />

stattdessen zur Ausführung von /usr/bin/qemu-arm-static<br />

führen, wobei der Pfad des Codes in Form eines Parameters<br />

weitergeleitet wird.<br />

Image auf dem <strong>PC</strong> erstellen<br />

Mithilfe eines Emulators können Sie das<br />

archroot-Unterverzeichnis auch auf Ihrem<br />

<strong>PC</strong> anlegen statt auf dem <strong>Raspberry</strong> <strong>Pi</strong>.<br />

Dazu müssen Sie den Paketmanager so<br />

konfigurieren, dass er ARM-Pakete herunterlädt<br />

und das mkarchroot-Skript so<br />

einstellen, dass es qemu-arm-static im<br />

archroot-Verzeichnis installiert, während<br />

dieses erzeugt wird. Nachdem Sie diese<br />

letzten Puzzleteile eingefügt haben,<br />

sind Sie in der Lage, auf Ihrem <strong>PC</strong> ein<br />

vollständiges Image für Ihren <strong>Raspberry</strong><br />

<strong>Pi</strong> samt maßgeschneidertem Kernel<br />

und zusätzlichen Paketen aufzubauen.<br />

So weit, so gut. Was allerdings schwierig ist, ist die<br />

Erstellung von Paketen, da hierbei Abhängigkeiten (dependencies)<br />

ins Spiel kommen und auf einem x86-Computer keine<br />

ARM-Abhängigkeiten installiert werden können. Sie können<br />

das Problem jedoch halbwegs umgehen, indem Sie das anfangs<br />

erwähnte Tool distcc einsetzen. Damit können Sie die<br />

Paketerstellung auf Ihrem <strong>Pi</strong> erledigen, jedoch die Kompilierungsarbeit<br />

per Cross-Compiling an Ihren <strong>PC</strong> auslagern.<br />

Um distcc verwenden zu können, müssen Sie es sowohl auf<br />

dem <strong>Raspberry</strong> <strong>Pi</strong> als auch auf dem <strong>PC</strong> installieren, in beiden<br />

Fällen mit dem Befehl pacman -S distcc. Der <strong>Pi</strong> fungiert als Client<br />

und kontrolliert die Erstellung der Pakete mittels makepkg,<br />

das Sie noch für die Benutzung von distcc konfigurieren müssen,<br />

und zwar durch Angabe der Details Ihres distcc-Servers.<br />

Ändern Sie hierzu /etc/makepkg.conf wie folgt:<br />

BUILDENV=(fakeroot distcc color !ccache)<br />

DISTCC_HOSTS=“10.0.200.12”<br />

MAKEFLAGS=“-j8”<br />

Als Server fungiert Ihr <strong>PC</strong>, er kompiliert den Code. In der Konfigurationsdatei<br />

/etc/conf.d/distccd muss angegeben werden,<br />

welche Hosts sich verbinden dürfen. Dabei sollte der Server als<br />

Daemon gestartet werden:<br />

/etc/rc.d/distccd start<br />

Sind Client und Server konfiguriert, kann makepkg auf dem <strong>Pi</strong><br />

und das Kompilieren auf dem <strong>PC</strong> ausgeführt werden. Allerdings<br />

muss noch der korrekte Compiler in der Datei distccd eingetragen<br />

werden: Standardmäßig ist dort gcc eingestellt, wir benutzen<br />

jedoch stattdessen den Compiler arm-linux-gnueabi-gcc.<br />

Modifizieren Sie daher den Pfad wie folgt:<br />

# ln -s /usr/bin/arm-linux-gnueabi/gcc /use/bin/<br />

arm-linux-gnueabi-gcc<br />

# sed -i -e ‘/^PID=/iPATH=/usr/bin/arm-linux-gnueabi:\<br />

$PATH’ /etc/rc.d/distcc<br />

Root-Partition verschieben<br />

Falls Sie Ihr Root-Dateisystem nicht auf der SD-Karte haben<br />

möchten, sondern beispielsweise auf einer USB-Festplatte, können<br />

Sie die Root-Partition auch dorthin verschieben. Dies geht<br />

ganz einfach, indem Sie das bestehende Root-Dateisystem von<br />

der SD-Karte in eine Partition der USB-Festplatte kopieren.<br />

Eventuell müssen Sie die Größe anpassen.<br />

# dd if=/dev/mmcblk0p2 of=/dev/sda1 bs=4M<br />

# fsck /dev/sda1<br />

# resize2fs /dev/sda1<br />

Ändern Sie dann in der Datei /boot/cmdline.txt die Position<br />

der Root-Partition im Bootkommando, indem Sie root=/dev/<br />

mmcblk0p2 durch root=/dev/sda1 ersetzen. Nach einem Neustart<br />

befindet sich die Root-Partition auf der Festplatte. Die benötigten<br />

USB-Treiber sind normalerweise bereits im Kernel<br />

vorhanden.<br />

Quick-<br />

Tipp<br />

Sollte beim Bau<br />

des Kernels der<br />

Arbeitsschritt<br />

modules_install<br />

zu der Fehlermeldung<br />

No rule to make<br />

target ‘modules/<br />

lib/firmware/./’<br />

führen, wiederholen<br />

Sie den Schritt<br />

einfach – dann sollte<br />

es klappen.<br />

69


Projekte<br />

XBMC enthüllt<br />

„XBMC hat sich zu einer fantastischen Lösung für Ihre<br />

Medienbibliothek gemausert.“<br />

Aus einem Linux-Rechner ein Media-<br />

Center zu machen war schon immer<br />

beliebt. Möglicherweise liegt es daran,<br />

dass Sie so viele Linux-Versionen<br />

einrichten können wie Sie wollen, ohne einen<br />

Cent zu zahlen, oder es liegt an der System-<br />

Stabilität, die garantiert, dass Sie<br />

stets Ihre Lieblingsserien aufnehmen<br />

können.<br />

Die Einrichtung eines Media-<br />

Centers war stets mit viel Arbeit verbunden,<br />

denn für lange Zeit galt<br />

MythTV als einzig sinnvolle Lösung<br />

für ein Media-Center mit<br />

TV-Anbindung. MythTV ist eine monumentale<br />

Suite von Clients und Servern, die alles kann:<br />

vom Steuern Ihrer Vorhänge bis hin zu komplexen<br />

Suchfunktionen für Ihre Lieblingsaufnahmen.<br />

MythTV ist wundervoll, aber<br />

schwierig aufzusetzen. Sie brauchen ein Back-<br />

End für die Aufnahmen und ein Front-End, um<br />

Ihre Inhalte ansehen zu können – beides ist<br />

nicht leicht einzurichten. Im Januar 2013 wurde<br />

Version 12 einer der besten MythTV-<br />

„XBMC hat sich zu einer<br />

fantastischen Lösung für Ihre<br />

Medienbibliothek gemausert.“<br />

Alternativen veröffentlicht: XBMC. XBMC wurde<br />

schnell zu einem idealen Ersatz für jene, die<br />

sich an der Installation von MythTV schwertaten.<br />

XBMC hat sich mittlerweile zu einer fantastischen<br />

Lösung für Ihre Medienbibliothek<br />

gemausert. Deswegen haben wir XBMC in<br />

unserem Test die höchsten Empfehlungen ausgesprochen.<br />

XBMC ist das Pendant zum Front-End von<br />

MythTV, mit der Ausnahme, dass es die gleichen<br />

Aufgaben mit einer angenehmeren<br />

und geradlinigeren Oberfläche<br />

verbindet. Eine OpenGL-<br />

Beschleunigung sorgt für eine<br />

flüssigere Darstellung sowohl des<br />

Menüs als auch der Inhalte auf<br />

HD-Fernsehern. <strong>Das</strong> Interface ist<br />

zudem für Einsteiger deutlich<br />

zugänglicher und einfacher zu bedienen.<br />

Deswegen haben wir uns entschieden, uns auf<br />

den folgenden Seiten XBMC etwas genauer zu<br />

widmen.<br />

70


Projekte<br />

Was ist XBMC?<br />

Es dauerte über zehn Jahre bis zum Status quo, aber es begann sehr aufregend.<br />

<strong>Das</strong> X in XBMC stand einst für Xbox – ja,<br />

genau wie die Microsoft-Konsole. Frühe<br />

Versionen von XBMC machten die erste<br />

Xbox zu einem Media Player, der direkt mit<br />

dem AV-Receiver und dem Fernseher verbunden<br />

war. Die beiden Entwickler mit den Namen<br />

„d7o3g4q“ und „RUNTiME“ gründeten das<br />

Projekt 2002. Beide arbeiteten an ihren eigenen<br />

geschlossenen Komponenten, bevor sie<br />

sich mit Frodo zusammenschlossen, dem<br />

Gründer von YAMP – Yet Another Media<br />

Player. <strong>Das</strong> neue Projekt bekam den Namen<br />

Xbox Media Player 2.0, welches Ende 2002<br />

veröffentlicht wurde. Ein Jahr später war das<br />

Xbox Media Center geboren, mit einer<br />

Namensänderung, die den Fokus des neuen<br />

Projekts besser betonte und die bis heute<br />

Bestand hat. <strong>Das</strong> erste stabile Release von<br />

XBMC erschien im Juni 2004, zwei Jahre später<br />

folgte Version 2.0. 2007 schließlich löste<br />

sich das Projekt von der Xbox, Entwickler wurden<br />

gesucht, um das Programm auf Linux<br />

umzuziehen und um von Microsofts DirectX-<br />

Plattform auf SDL und OpenGL zu wechseln.<br />

Installation<br />

Nach zehn Jahren ist XBMC bei Version 12 –<br />

Codename Frodo. Es entwickelte sich zu einer<br />

der ausgereiftesten Multiplattform-Media-<br />

Center, mit mehr Potenzial als nur einem<br />

Ersatz für fast alle bestehenden Media-Front-<br />

End-Lösungen. Die neue Version unterstützt<br />

Android und <strong>Raspberry</strong> <strong>Pi</strong> inklusive HD-Audiound<br />

HD-Video-Playback sowie umfassende<br />

Digital-Video-Recorder-Funktionen. XBMC läuft<br />

auf fast allen Plattformen und lässt sich sowohl<br />

als Front-End-Client für das Wohzimmer als<br />

auch als Back-End-Server für die Medienbibliothek<br />

nutzen. Es ist ein großartiger Ersatz<br />

für das brillante MythTV und bringt sogar eine<br />

bessere Oberfläche und eine niedrigere Lernkurve<br />

mit, auch wenn es nicht so individualisierbar<br />

oder leistungsstark wie MythTV ist.<br />

Sie können XBMC auf allen beliebten Linux-<br />

Distributionen via Package-Manager installieren.<br />

Soll XBMC auf einem <strong>Raspberry</strong> <strong>Pi</strong> laufen, benutzen<br />

Sie die OpenELEC-Distribution. Dazu brauchen<br />

Sie entweder<br />

Arch oder – unsere<br />

Empfehlung – ein jüngeres<br />

Release, falls<br />

Sie XBMC 12 nutzen<br />

wollen. Haben Sie<br />

noch einen Windowsoder<br />

OS-X-Rechner,<br />

nutzen Sie entsprechende<br />

Binaries, die<br />

den gesamten<br />

Desktop einnehmen.<br />

So genießen Sie das<br />

Gefühl, weiterhin mit<br />

einem Linux-System<br />

zu arbeiten.<br />

XBMC ist eine der<br />

besten Möglichkeiten, um überschüssige<br />

Rechner wieder zum Leben zu erwecken. Mit<br />

einem Klick auf „Quit“ haben Sie das verwendete<br />

System wieder auf Originalzustand gesetzt. Es<br />

gibt auch Extra-Pakete, um die Videobeschleunigung<br />

mit Nvidia- oder Grafikkarten zu verbessern.<br />

Die „vdpau“- für Nvidia-<strong>Hardware</strong> und die<br />

„xvba“-Bibliothek für AMD hilft Ihrem System,<br />

hochauflösende Video-Streams zu decodieren.<br />

Wenn Sie den Media Player mit einem Recorder<br />

wie dem auf dem <strong>Raspberry</strong> <strong>Pi</strong> one basierenden<br />

TVheadend kombinieren möchten, dann brauchen<br />

Sie das „xbmc-pvr-addons“-Package. Viele<br />

Distributionen haben dieses Package auch standardmäßig<br />

integriert.<br />

Drive: <strong>Das</strong> Thema von 23 Prozent aller Diskussionen auf LXFTowers.<br />

Schritt für Schritt: XBMC einrichten<br />

1 Installation<br />

Nutzen Sie unbedingt XBMC 12 und nicht das<br />

Release in Ihrer Linux-Distribution. Für<br />

Ubuntu-Nutzer empfehlen wir als Ergänzung<br />

das offizielle PPA (https://launchpad.<br />

net/~team-xbmc/+archive/ppa). Spezielle<br />

XBMC-Distros wie etwa XBMCbuntu sind eine<br />

gute Option, wenn Sie in eine Live-Client-<br />

Oberfläche booten möchten.<br />

2 XMBC starten<br />

XBMC startet im Vollbild. Dies können Sie<br />

lediglich in den Einstellungen des Programms<br />

ändern: „System > Video Output > Display<br />

Mode“. Zudem brauchen Sie OpenGL, damit<br />

das funktioniert. Intel-, AMD- und Nvidia-<br />

<strong>Hardware</strong> funktioniert von Haus aus, für die<br />

beste Performance schauen Sie nach<br />

proprietären Treibern.<br />

3 Inhalte hinzufügen<br />

Für alle Hauptmenü-Optionen wie Bilder,<br />

Videos oder Musik lassen sich einzeln Quellen<br />

festlegen, <strong>Das</strong> kann auf einem lokalen<br />

Datenträger oder im Netzwerk (UPNP, NFS<br />

und Samba) sein. Der integrierte Datei-<br />

Explorer macht das Auffinden Ihrer Medien<br />

spielend einfach.<br />

71


Projekte<br />

XBMC: Die besten Features<br />

Sechs Gründe, warum XBMC das beste Media-Center ist.<br />

1 Foto-Management<br />

Es gibt viele Werkzeuge, um Ihre Fotosammlung<br />

zu organisieren. Dank der Unterstützung verschiedener<br />

Quellen, Listen, Thumbnails und<br />

Ansichten haben wir das Gefühl, das XBMC die<br />

Balance richtig hinbekommt. Unglücklicherweise<br />

kann XBMC nichts an der Bildqualität ändern, wie<br />

der obige Screenshot schmerzhaft demonstriert.<br />

Daher empfehlen wir Ihnen, einen Mentor oder<br />

einen Kurs aufzusuchen, um sich in die Kunst der<br />

Bildbearbeitung einführen zu lassen.<br />

2 Inhalte optimieren<br />

Wenn Sie eine Video-Quelle hinzugefügt<br />

haben, dann können Sie die Filmdatenbank<br />

nach Bildern und weiterführenden<br />

Informationen durchsuchen. Cover für Ihre<br />

Inhalte machen die Suche in Ihrer Bibliothek<br />

deutlich einfacher und intuitiver. Wenn Dateien<br />

auf einer externen Quelle liegen, dann ist es<br />

den Aufwand wert. Lassen Sie den Prozess zur<br />

Not über Nacht laufen.<br />

3 Erweiterungen<br />

Mit Erweiterungen, die sich unter „Get<br />

More“ für Bilder, Videos und Musik finden<br />

lassen, haben Sie zusätzliche Quellen für<br />

Ihre Medienbibliothek. Es gibt viele Online-<br />

Streaming-Dienste, wie beispielsweise den<br />

Nachrichtensender Al Jazeera unter Video-Addons.<br />

Dazu kommt unter anderem auch eine<br />

iTunes Podcast Bibliothek unter Musik. <strong>Das</strong> ist<br />

nun übrigens ein guter Moment, den TuxRadar<br />

Podcast zu erwähnen. <strong>Das</strong> ist der beste, ehrlich!<br />

4 PVR Video-Recorder<br />

Wenn Sie TVheadend installiert haben, dann<br />

können Sie das PVR-Plugin unter „Settings ><br />

Add-ons > Disabled Add-ons > PVR clients“<br />

aktivieren. Anschließend (und ggf. nach<br />

Änderung der IP-Adresse) sehen Sie die „Live<br />

TV“-Option im Menü. Dort können Sie TV<br />

schauen und Aufnahmen timen und den EPG<br />

durchsuchen. Sie können unseren Erfahrungen<br />

nach live über das Netzwerk streamen und<br />

gleichzeitig einige HD-Sender schauen. Um über<br />

das Netzwerk zu streamen, leiten Sie den Port<br />

9982 des Tvheadend Server durch Ihre Firewall<br />

an den XMBC. Beachten Sie, dass der Upload<br />

ausreichend Bandbreite bieten muss.<br />

5 Programme<br />

XBMC bietet eine fantastische Architektur für<br />

Erweiterungen. Über das Programme-Menü<br />

können Sie sehr viele Funktionen hinzufügen.<br />

Es gibt einen Gmail-Checker, Emulatoren und<br />

sogar ein Filmquiz. Sie können auch eigene<br />

Programme entwickeln. Der Text am unteren<br />

Bildschirmrand hält Sie dabei über den Status<br />

verschiedener Plugins auf dem Laufenden.<br />

Aktualisierungen können Sie auch über das<br />

Menü des jeweiligen Programms herunterladen.<br />

Im Sidebar-Menü können Sie automatische<br />

Updates ein- bzw. ausschalten. .<br />

6 Interface-Skins<br />

Der XBMC-Skin heißt Confluence, Dieser bringt<br />

einen modernen Look, den Sie mit weiteren<br />

Skins nach Belieben ändern können. Unter<br />

„Settings > Appearance > Skin“ finden Sie unter<br />

„Get More“ weitere Skins. Unser Favorit ist der<br />

„Aeon“-Skin, der mit heruntergeladenen Movie-<br />

Covern sehr professionell aussieht. Der „Back<br />

Row“-Skin erinnert an Geräte eines Herstellers<br />

mit dem Logo einer angebissenen Frucht. Der<br />

„Rapier“-Skin bringt Minimalismus mit einer<br />

Oberfläche, die nicht von zu vielen Bildern<br />

dominiert wird. Und falls Ihnen der Rest nicht<br />

zusagt, gibt es genügend Möglichkeiten, Skins<br />

zu modifizieren.<br />

Tastatur-Shortcuts<br />

Die Bedienung von XBMC kann kryptisch sein, hier ist eine Liste<br />

mit Shortcuts für die wichtigsten Funktionen.<br />

[E] EPG anzeigen<br />

[B] Aufnahmen timen<br />

[H] TV-Kanäle anzeigen<br />

[F] Vorspulen<br />

[R] Zurückspulen<br />

[P] Play<br />

[Leertaste] Play/Pause<br />

[X] Stop<br />

[M] On-Screen-Steuerung<br />

[S] Herunterfahren-Menü<br />

[Links] Vorherigen Titel 30 Sekunden zurückspulen<br />

[Rechts] Nächsten Titel 30 Sekunden vorspulen<br />

[Hoch] Nächster Kanal, zehn Minuten<br />

vorspulen, nächstes Kapitel<br />

[Runter] Vorheriger Kanal, zehn Minuten<br />

zurückspulen, vorheriges Kapitel<br />

[Esc] Vollbild deaktivieren<br />

[.] (Punkt) Nächster Titel<br />

[,] (Komma) Titel überspringen<br />

[+] or [=] Lautstärke hoch<br />

[-] Lautstärke runter<br />

[Ctrl]+[End] XBMC beenden<br />

72


Projekte<br />

XBMC <strong>Hardware</strong><br />

Von <strong>Raspberry</strong> <strong>Pi</strong> bis Apple TV, XBMC läuft überall.<br />

Die Multiplattform-Tauglichkeit ist eine<br />

der besten Features von XBMC. Es gibt<br />

nicht nur Versionen für Windows, OS X<br />

und Linux, sondern mit Version 12.0 auch eine<br />

Version für Android. Dazu kommen Versionen<br />

für die ersten beiden Generationen von Apple<br />

TV und für iOS-Geräte mit Jailbreak. Der<br />

Android-Port mag noch am Beginn seiner<br />

Entwicklung stehen, doch es handelt sich um<br />

einen vollständigen Port mit allen Features der<br />

Desktop-Version. Da dies eine erste Version ist,<br />

ist der <strong>Hardware</strong>-Decoding-Support noch<br />

beschränkt. <strong>Das</strong> heißt, dass die meisten Geräte<br />

Software-Decoding nutzen müssen. Doch es ist<br />

nur eine Frage der Zeit, bis die Entwickler die<br />

Möglichkeiten der <strong>Hardware</strong> in Smartphones<br />

und Tablets mit Android effizient ausnutzen<br />

können. Bereits jetzt können Android-Geräte<br />

wie etwa der Media-Player MiniX Neo X5<br />

Berichten zufolge 1080p-Inhalte mit HD-Sound<br />

problemlos wiedergeben. Android-Geräte sind<br />

also schon eine gute Plattform für XBMC, auch<br />

wenn die Software noch nicht ausgereift ist. Die<br />

Systemanforderungen umfassen Tegra-3-<br />

Unterstützung und Android 4.0 – womöglich<br />

funktionieren auch die Vorgänger. Sowohl das<br />

Nexus 7 als auch das Nexus 10 sollen mit<br />

XBMC funktionieren, genau wie die US-Version<br />

des Samsung Galaxy S III.<br />

Umso näher Ihre <strong>Hardware</strong> an die<br />

Hauptplattform der „XBMC für Android“-<br />

Entwickler kommt, desto besser wird XBMC<br />

funktionieren. <strong>Das</strong> offizielle Haupt-Gerät ist der<br />

<strong>Pi</strong>vos XIOS DS von AMLogic. Er besitzt einen<br />

ARM Cortex A9 Prozessor, eine Mali 400 3D<br />

GPU und einen HDMI-Ausgang. Dazu kommt<br />

Die Entwickler von XBMC für Android arbeiten hauptsächlich mit dem Media Player <strong>Pi</strong>vos<br />

XIOS DS. Deshalb sollten alle neuen Features dort zuerst rauskommen.<br />

eine Fernbedienung. <strong>Das</strong> System könnte zwar<br />

keinen Low-End-<strong>PC</strong> ersetzen, stellt jedoch eine<br />

gute Lösung dar, um ihr Setup zu erweitern.<br />

<strong>Das</strong> Gerät ist winzig, es ist gerade einmal 15<br />

Millimeter hoch. Sie könnten den Media Player<br />

ganz einfach an die Rückseite eines durchschnittlich<br />

dimensionierten Fernsehers montieren,<br />

ihn via WLAN mit dem Internet verbinden<br />

und ihn Inhalte auf Abruf liefern lassen.<br />

<strong>Raspberry</strong> <strong>Pi</strong><br />

Eine andere großartige, neue Plattform für XBMC<br />

ist der <strong>Raspberry</strong> <strong>Pi</strong>. In Sachen Specs siedelt der<br />

<strong>Pi</strong> niedriger an als viele Android-Geräte. Doch die<br />

Entwickler tun alles, damit eine bestmögliche<br />

Performance möglich ist – bei einem unschlagbaren<br />

Preis. HD-Videos laufen fehlerfrei über den<br />

eingebauten HDMI-Ausgang. OpenELEC (Open<br />

Embedded Linux Entertainment Center) ist dabei<br />

die beste Möglichkeit, XBMC auf Ihr <strong>Raspberry</strong> <strong>Pi</strong><br />

zu bekommen. Die aktuelle Version ist der<br />

Release Candidate 3 der Version 3.0. Der<br />

Download kommt als „tar.bz2“-Datei. Entpacken<br />

Sie das Paket mit einem Doppelklick auf dem<br />

Desktop. Alternativ tippen Sie „tar xvf OpenELEC-<br />

R<strong>Pi</strong>.arm.tar.bz2“ in die Kommandozeile.<br />

Schließen Sie einen Kartenleser mit eingelegter<br />

SD-Karte an Ihre Linux-Maschine. Via „dmesg“<br />

finden Sie den richtigen Pfad zum Gerät, in der<br />

Regel sieht er etwa so aus: „/dev/sdc“. Doch Sie<br />

müssen sich sicher sein. Wenn Sie einen Fehler<br />

machen, dann könnten Sie wichtige Daten verlieren.<br />

Wenn Sie den Namen des Gerätes herausgefunden<br />

haben, dann tippen Sie im Ordner, den Sie<br />

zuvor entpackt haben „sudo ./create_sdcard/<br />

dev/sdX“ ein, passen Sie den Pfad an Ihr eigenes<br />

Gerät an. Anschließend haben Sie ein funktionsfähiges<br />

XBMC, in das Ihr <strong>Raspberry</strong> <strong>Pi</strong> direkt bootet.<br />

Fernbedienung<br />

Eine Fernbedienung ist essenziell,<br />

wenn Sie ein XBMC-Gerät mit dem<br />

Fernseher verbinden. Unter Linux<br />

gibt es so viele unterschiedliche<br />

Lösungen wie Distributionen. Sie<br />

können beispielsweise Infrarot-<br />

Empfänger und -Sender konfigurieren<br />

oder Geräte kaufen, die nach<br />

einer Programmierung Tastaturbefehle<br />

senden. Am einfachsten ist<br />

es jedoch, ein Smartphone zu verwenden.<br />

Es gibt offizielle Apps für<br />

Apple und Android, die Sie kostenlos<br />

herunterladen können. Die Apps<br />

senden Befehle via Netzwerk, Sie<br />

müssen sich keine Sorgen um eine<br />

ausreichend starke Infrarot-Verbindung<br />

oder eine freie Sicht zwischen<br />

Sender und Empfänger machen.<br />

Damit die Android-Fernbedienung<br />

funktioniert, müssen Sie in den<br />

Einstellungen von XBMC „Allow<br />

control of XBMC via HTTP“ unter<br />

„Settings > Services > Webserver“<br />

aktivieren. Dies startet einen<br />

Webserver auf der XBMC-Plattform,<br />

auf die Sie via entsprechender<br />

IP-Adresse und Port 8080 mit<br />

Ihrem Smartphone Zugriff haben.<br />

Ist die App auf dem Android-<br />

Gerät installiert, müssen Sie den<br />

„Add Host“-Button drücken. Dort<br />

können Sie den XBMC-Server konfigurieren.<br />

Es sieht einschüchternd<br />

aus, ist aber sehr einfach. Geben Sie<br />

einfach eine Beschreibung und die<br />

IP-Adresse des XBMC-Rechners<br />

ein. Sie finden die IP-Adresse entweder<br />

über das Netzwerk-Applet des<br />

Rechners heraus oder via „ifconfig“-Befehl<br />

in der Kommandozeile.<br />

Stellen Sie sicher, dass die Ports<br />

8080 und 9090 eingestellt und freigegeben<br />

sind. Speichern Sie. Nun<br />

sollten Sie in der Lage sein, Ihr<br />

XBMC fernsteuern zu können.<br />

Unserer Meinung nach ist die<br />

„Remote Control“-Option aus dem<br />

Hauptmenü die nützlichste Option.<br />

Diese Funktion wandelt ihr Smartphone<br />

in eine physikalische Fernbedienung,<br />

während die anderen<br />

Optionen genutzt werden können,<br />

um Ihre Medien zu organisieren.<br />

Nutzen Sie ein Apple- oder<br />

Android-Smartphone<br />

und machen Sie sich<br />

nie mehr Sorgen um die<br />

Infrarot-Verbindung.<br />

73


Projekte<br />

Auto-Backups per<br />

Sind Sie es leid, ständig manuell Ihre Daten zu sichern? Wir zeigen Ihnen, wie<br />

Sie schnell und einfach Bash-Skripte für automatische Backups schreiben.<br />

Die Möglichkeit<br />

zur einfachen<br />

Kombination<br />

leistungsfähiger<br />

GNU-Tools<br />

macht das<br />

Schreiben<br />

von Skripten<br />

mit Bash zum<br />

Vergnügen.<br />

In der Theorie weiß jeder, wie wichtig es ist, regelmäßig die<br />

Daten auf seinem Computer zu sichern. Doch in der Praxis<br />

bleibt es oft beim guten Vorsatz, denn das Anfertigen von<br />

Backups ist langweilig und lästig, und so wendet man sich im<br />

Zweifelsfall lieber interessanteren Dingen zu. Es gibt eine<br />

Fülle von Routineaufgaben, denen sich ein Systemadministrator<br />

widmen muss: alte Backups löschen, den Zustand der<br />

Server überprüfen, neue Server installieren und konfigurieren<br />

und vieles mehr.<br />

Linux gibt Ihnen jedoch ein Werkzeug an die Hand, mit<br />

dem Sie sich viele dieser langweiligen und repetitiven Aufgaben<br />

vom Hals schaffen können – die leistungsfähige Shellund<br />

Skriptsprache Bash. In diesem Artikel stellen wir Ihnen<br />

Bash vor und legen den Fokus dabei auf Skriptfunktionen,<br />

mit denen Sie fast jede Aufgabe automatisieren können.<br />

Was ist Bash?<br />

Bash steht für Bourne Again Shell und ist 1989 als Ersatz für<br />

Bourne Shell entstanden. Eine Shell ist ein Befehlsinterpreter,<br />

der Ihnen die direkte Kommunikation mit dem Computer ermöglicht.<br />

Die Shell übersetzt Ihre Befehle in eine für den<br />

Computer verständliche Sprache und sorgt für deren Ausführung<br />

durch das Betriebssystem. Jede Information, die als<br />

Folge dieses Prozesses entsteht, wird wiederum zurückinterpretiert<br />

und in der Shell in einer für Sie verständlichen Form<br />

dargestellt. In diesem Artikel verwenden wir Bash und Shell<br />

synonym.<br />

Wenn Sie die Shell bisher nicht verwendet haben, ist dies<br />

nun die Gelegenheit. Auf modernen Linux-Systemen werden<br />

Shells für gewöhnlich über eine Desktop-Anwendung gestartet.<br />

Suchen Sie unter Fedora und Ubuntu nach der Anwendung<br />

„Terminal“ und starten Sie sie.<br />

Die Grundlagen von Bash<br />

Nach Programmstart erscheint ein Fenster mit einer Eingabeaufforderung<br />

in der oberen linken Ecke des Bildschirms.<br />

Immer wenn Sie einen blinkenden Cursor sehen, wartet die<br />

Shell auf eine Eingabe Ihrerseits. Versuchen Sie sich an<br />

einem Befehl, indem Sie ls eingeben und mit der Eingabetaste<br />

(Enter) bestätigen. Nun erscheint eine Liste mit Verzeichnissen<br />

und Dateien des gewählten Datenträgers, gefolgt von<br />

einer weiteren Eingabeaufforderung. ls ist der Name eines<br />

Shell-Befehls, der die Dateien in Ihrem momentan gewählten<br />

Verzeichnis auflistet. Indem Sie den Namen eines Befehls<br />

eingeben und Enter drücken, veranlassen Sie die Ausführung<br />

durch die Shell.<br />

Sie können die Art der Ausführung durch das Hinzufügen<br />

von Parametern anpassen, meist in der Form -x, also durch<br />

einen Gedankenstrich gefolgt von einem Buchstaben. Im obigen<br />

Beispiel könnten wir den Befehl ls durch -l ergänzen, was<br />

eine detailliertere Übersicht zur Folge hätte.<br />

Andere Befehle werden durch sogenannte Argumente<br />

näher spezifiziert. Der Befehl cp zum Kopieren einer Datei<br />

beispielsweise benötigt zwei Ortsangaben als Argumente,<br />

nämlich Quelldatei und Zieldatei:<br />

cp hello.txt world.txt<br />

Dieser Befehl kopiert die Datei hello.txt in das momentan gewählte<br />

Verzeichnis und gibt der Kopie den Namen world.txt.<br />

Wenn letztere Datei noch nicht existiert, wird sie erstellt;<br />

wenn sie bereits existiert, wird sie überschrieben – es ist also<br />

Vorsicht geboten!<br />

74


Projekte<br />

Bash-Skript<br />

Wenn Sie ein Verzeichnis wechseln wollen, benutzen Sie<br />

den Befehl cd. Ein Beispiel: cd / führt Sie in das Stammverzeichnis,<br />

welches in der Verzeichnishierarchie ganz oben<br />

steht; cd /usr/bin führt hingegen in das Unterverzeichnis<br />

bin des Verzeichnisses usr, welches wiederum ein Unterverzeichnis<br />

des Stammverzeichnisses ist.<br />

Pfade können auch ortsrelativ sein. Wenn Sie sich im<br />

Stammverzeichnis befinden und in das Unterverzeichnis Documents<br />

wechseln möchten, so geben Sie cd Documents<br />

ein, und die Shell sucht im momentan gewählten Verzeichnis<br />

nach einem entsprechenden Unterverzeichnis und wechselt<br />

an diese Stelle.<br />

Pfade dienen auch dazu, Dateien zu benennen, die das Ziel<br />

eines Befehls darstellen sollen. Um beispielsweise die Datei<br />

hello.txt nach world.txt zu kopieren, während sich world.txt<br />

in Ihrem Dokumentenverzeichnis und hello.txt in Ihrem<br />

Testverzeichnis befindet, geben Sie folgendes ein:<br />

cp test/hello.txt /home/jon/Documents/world.txt<br />

So können Sie relative und absolute Pfade kombinieren und<br />

in Einklang bringen.<br />

Hallo Welt<br />

Kommen wir nun zu den interessanten Dingen: den Skriptbefehlen<br />

für Bash. Lassen Sie uns einer bewährten Tradition bei<br />

Programmier-Tutorials folgen und mit einem Programm beginnen,<br />

das „Hello World“ auf Ihrem Monitor darstellen soll.<br />

Schreiben Sie Folgendes in eine Datei und speichern Sie<br />

diese:<br />

#!/bin/bash<br />

echo ”Hello World”<br />

Danach wandeln Sie die Textdatei zu einer ausführbaren<br />

Datei, indem Sie<br />

chmod +x <br />

eingeben und aus der Shell heraus starten:<br />

./.<br />

Nun sollten Sie die beiden magischen Wörter auf dem Bildschirm<br />

sehen. Die erste Zeile ist die sogenannte „Shebang“-<br />

Zeile. Diese wird vom Betriebssystem genutzt, um<br />

Sie können die Skriptbefehle nicht nur in Dateien, sondern<br />

auch direkt in die Konsole eingeben.<br />

Immer wissen, wo man ist<br />

Wenn Sie die Shell benutzen, sollten<br />

Sie stets Ihr momentan gewähltes<br />

Verzeichnis im Auge behalten. Wie<br />

bereits im Artikel beschrieben, startet<br />

die Shell für gewöhnlich immer im<br />

Stammverzeichnis. <strong>Das</strong> hört sich vielleicht<br />

nach einem unwichtigen Detail<br />

an, ist tatsächlich jedoch überaus<br />

wichtig. Solange Sie keinen absoluten<br />

Pfad angeben, verhalten sich alle<br />

Dateien und Verzeichnispfade relativ<br />

zu Ihrem momentan gewählten Verzeichnis.<br />

Wenn Sie einen Befehl von<br />

einem falschen Verzeichnis aus veranlassen,<br />

können Sie die seltsamsten<br />

Resultate erhalten – das schließt auch<br />

„Nun sollten Sie die beiden<br />

magischen Wörter auf dem<br />

Bildschirm sehen.“<br />

versehentliches Löschen von Dateien<br />

mit ein. Bestimmte Vorgänge wie das<br />

Unmounting eines Verzeichnisses<br />

werden fehlschlagen, wenn noch Operationen<br />

im betreffenden Verzeichnis<br />

stattfinden. Wenn Sie die Shell in<br />

diesem Moment interaktiv steuern,<br />

stellt dies kein großes Problem dar.<br />

Wenn Sie aber ein Skript laufen lassen,<br />

das versucht, in ein Verzeichnis<br />

zu gelangen, das bereits gelöscht<br />

wurde, bricht das Skript ab – und Sie<br />

werden die Ursache erst ermitteln<br />

müssen. Sie können das momentan<br />

gewählte Verzeichnis jederzeit<br />

mit dem Befehl pwd überprüfen.<br />

festzulegen, mit welchem Programm der Inhalt des Skripts<br />

auszuführen ist, in diesem Falle Bash. Es muss dabei immer<br />

der absolute Pfad angegeben werden. Die zweite Zeile stellt<br />

einen Standardbefehl der Shell dar. In diesem Beispiel handelt<br />

es sich um den Befehl echo, der das ihm folgende Argument<br />

auf dem Monitor ausgibt.<br />

Natürlich gibt es außer echo noch viele andere Befehle, die<br />

an dieser Stelle direkt ausgeführt werden können, und genau<br />

das macht das Skripten mithilfe der Shell zu einem so mächtigen<br />

Instrument. Mit dem Kommando man können Sie sich<br />

die Verwendungsmöglichkeiten für jeden einzelnen Befehl<br />

anzeigen lassen. Tippen Sie dazu beispielsweise man echo<br />

ein. Sogar man man ist möglich, wenn Sie mehr über den<br />

man-Befehl selbst wissen möchten.<br />

Sie können entweder direkt aus der großen Bandbreite<br />

von Befehlen schöpfen, die Bash zu bieten hat, oder Sie nutzen<br />

Funktionen wie Redirection und <strong>Pi</strong>pes, um Befehle zu<br />

verknüpfen. Sie können aber auch Skripte mit bedingten Anweisungen<br />

und Verzweigungen für Schleifen und Subroutinen<br />

schreiben.<br />

Im Zusammenhang mit unserem ersten Skript sind noch<br />

zwei Dinge erwähnenswert: Zum einen mussten wir die Datei<br />

in eine ausführbare umwandeln, denn sonst hätte das Betriebssystem<br />

sie nicht laufen lassen können. Zum anderen<br />

konnten wir den Namen der Datei nicht wie einen Befehl einfach<br />

eintippen, sondern wir mussten ein ./ voranstellen. Der<br />

Punkt ist dabei Kurzschrift für den momentan gewählten Dateipfad,<br />

und der Schrägstrich ist die übliche Trennung von Dateien<br />

und Pfaden (siehe auch Kasten „$PATH“ auf Seite 76).<br />

75


Projekte<br />

Unter Bash<br />

stehen Ihnen<br />

vielfältige Mittel<br />

zur Zuordnung<br />

von Dateien zur<br />

Verfügung, die<br />

Verwendung von<br />

absoluten und<br />

relativen Pfaden<br />

eingeschlossen.<br />

Variablen<br />

Sie können unser Skript auf vielfältige und einfache Weise erweitern:<br />

Fügen Sie einfach in neuen Zeilen weitere Befehle<br />

hinzu:<br />

#!/bin/bash<br />

„Um komplexere Skripte<br />

erstellen zu können,<br />

benötigen wir Bindeglieder.“<br />

echo ”hello world”<br />

echo ”These files are in my current directory:”<br />

ls<br />

Mit den in Bash verfügbaren Befehlen bekommen Sie auf<br />

simple Art und Weise schon jetzt viele Möglichkeiten an die<br />

Hand. Um komplexere Skripte erstellen zu können, benötigen<br />

wir jedoch Bindeglieder, die wir uns aus anderen Programmierspra-<br />

chen entleihen.<br />

Diese ermöglichen<br />

uns, intelligentere<br />

und flexiblere<br />

Skripte<br />

zu schreiben.<br />

Lassen Sie uns mit Variablen beginnen, mit denen wir Werten<br />

bestimmte Namen zuordnen können. Ein Beispiel:<br />

#!/bin/bash<br />

name=Jon<br />

echo ”Hello ${name}”<br />

echo ”${name}, that’s a nice name.”<br />

Die erste Zeile nach unserem Shebang weist der Variablen<br />

den Text-String Jon zu. Danach können wir uns an jeder Stelle<br />

des Skripts auf diese Variable beziehen, indem wir den<br />

Namen der Variablen wie oben in eine geschweifte Klammer<br />

setzen und ein Dollarzeichen voranstellen, also ${}. Wenn wir<br />

das Skript dann ausführen, durchsucht Bash es und ersetzt<br />

den Wert name an jeder Stelle durch ${name}, also den Inhalt<br />

der Variablen.<br />

Allein dies ist schon oft nützlich, aber Bash hat noch mehr<br />

auf Lager: Überaus praktisch ist beispielsweise die Zuweisung<br />

einer Ausgabe zu einer Variablen, indem wir sie mit<br />

Backticks/Gravis (`) einfassen:<br />

date=`date +%Y-%m-%d`<br />

So wird die Ausgabe des Befehls date zu einer Variablen namens<br />

date zur späteren Verwendung innerhalb des Skripts.<br />

Noch geschickter ist die Verknüpfung der Ausgabe von Befehlen<br />

durch den Gebrauch von Strings, indem wir die Konstruktion<br />

$() verwenden:<br />

echo “Today’s date is $(date +%Y-%m-%d)”<br />

An dieser Stelle schlagen wir den Bogen zu den Backups, da<br />

wir so Dateien mit dem jeweils aktuellen Datum erstellen<br />

können.<br />

Die Steuerung des Datenflusses<br />

Ein weiteres Bindeglied, das Bash zur Verknüpfung unserer<br />

Befehle zur Verfügung stellt (und welches üblicherweise auch<br />

Bestandteil anderer Programmiersprachen ist), stellt die<br />

Kontrolle des Programmablaufs dar. Bislang nämlich waren<br />

wir ausschließlich in der Lage, Bash die Befehle in exakt der<br />

Reihenfolge abarbeiten zu lassen, wie wir sie im Skript niedergeschrieben<br />

haben. Mittels bestimmter Befehle zur Datenfluss-Steuerung<br />

sehen wir uns aber in der Lage, den Ablauf<br />

des Skripts zu manipulieren.<br />

<strong>Das</strong> erste Werkzeug aus der Familie der Datenfluss-Steuerung<br />

sind Bedingungen wie if ... then („wenn ... dann“). Der<br />

Gedanke dahinter ist folgender: Ein Befehlsinterpreter prüft,<br />

ob eine Bedingung zutrifft, etwa ob eine bestimmte Datei vorhanden<br />

ist. Und nur wenn diese Bedingung zutrifft, wird<br />

nachfolgender Code auch ausgeführt:<br />

#!/bin/bash<br />

if [ 2 > 1 ]; then<br />

echo ”True”<br />

fi<br />

Dies ist jetzt nur ein simples Beispiel, da die Ausgabe stets<br />

True („wahr“) lauten wird. Trotzdem wird hier die Syntax<br />

deutlich. In Bash werden if-Ausdrücke immer wie folgt konstruiert:<br />

Zunächst steht das Schlüsselwort if, gefolgt von einer<br />

Anweisung, die in eckigen Klammern steht. Darauf folgt das<br />

Schlüsselwort then, welches vor der Anweisung steht, die<br />

dann ausgeführt wird, wenn die Bedingung erfüllt wird.<br />

$PATH<br />

Es ist überhaupt nichts Geheimnisvolles am Ausführen von<br />

Befehlen in Bash. Wenn Sie einen Namen angeben, findet<br />

die Shell den Binary oder das Skript, auf den sich dieser<br />

Name bezieht. In der Folge wird der Befehl als gewöhnliches<br />

Skript oder Programm ausgeführt, wie zum Beispiel<br />

bei ./hello.bash. Aber wie findet die Shell die Datei, wenn<br />

Sie den absoluten Pfad gar nicht angeben müssen?<br />

Die Antwort darauf ist die Variable $PATH. In der Shell steht<br />

Ihnen eine ganze Palette an Umgebungsvariablen zur Verfügung,<br />

die die Art, wie Programme ausgeführt und Befehle<br />

interpretiert werden, beeinflussen. Eine dieser Variablen trägt<br />

den Namen PATH und enthält eine Liste von Verzeichnissen,<br />

wo Befehle oder Skripte zur Ausführung liegen. Wann<br />

immer Sie den Namen eines Befehls eingeben, durchsucht<br />

die Shell diese Liste von Verzeichnissen von links nach rechts,<br />

bis eine Datei mit demselben Namen wie der von Ihnen<br />

ausgeführte Befehl gefunden wird. Falls keine Übereinstimmung<br />

gefunden wird, gibt die Shell folgenden Fehler aus:<br />

-bash: foo: command not found<br />

Sie können die Inhalte der $PATH-Variablen wie bei jeder<br />

anderen stets durch sogenanntes Echoing anzeigen lassen,<br />

der Befehl lautet echo ${PATH}. Und genau wie bei einer<br />

beliebigen anderen Variablen können Sie auch diese modifizieren.<br />

Wenn Sie die geänderten Einstellungen beim Abschluss<br />

einer Sitzung für die nächste erhalten wollen, müssen Sie<br />

die Bash- Konfigurationsdateien .bashrc oder .bash_profile<br />

ändern. Welche Datei infrage kommt, ist abhängig davon, ob<br />

Sie die Login-Shells, Subshells oder beide ändern möchten.<br />

76


Projekte<br />

Abgeschlossen wird der Block mit dem Schlüsselwort fi.<br />

Bash ist von Haus aus in der Lage, vielfältige und nützliche<br />

Tests durchzuführen. So wird mittels des Parameters -f geprüft,<br />

ob eine Datei existiert, oder mithilfe von -nt, ob eine<br />

Datei neuer als eine andere ist:<br />

if [ -f /var/run/backup.lock ]; then<br />

exit 1<br />

else<br />

touch /var/run/backup.lock<br />

tar -czf /mnt/backup-$(date +%Y-%m-%d).tgz /<br />

home/jon<br />

rm /var/run/backup.lock<br />

fi<br />

In diesem Beispiel prüft Bash, ob eine .lock-Datei existiert.<br />

Falls ja, brauchen wir kein neues Backup zu starten, da wir annehmen,<br />

dass bereits ein älteres Backup läuft. Wenn die Datei<br />

jedoch nicht existiert, nutzen wir else, um eine Datei zu erstellen,<br />

lassen das Backup laufen und entfernen die .lock-Datei.<br />

Nehmen Sie sich ein wenig Zeit für die man-Seite von<br />

Bash, um sich mit anderen Tests vertraut zu machen.<br />

Lassen Sie uns noch kurz den Bash-Befehl exit anschauen.<br />

Immer wenn ein Bash-Programm oder Befehl endet, wird<br />

ein numerischer Wert ausgegeben. Eine 0 bedeutet dabei,<br />

dass alles erfolgreich abgeschlossen wurde. Ein anderer Wert<br />

deutet jedoch darauf hin, dass irgendetwas schief gelaufen<br />

ist. <strong>Das</strong> ist besonders in Kombination mit der Variablen ?<br />

nützlich, welche den sogenannten Exit Code des Programms<br />

speichert. Dies erlaubt die Kontrolle der Ausführung Ihres<br />

Programms in der Hinsicht, dass sie als Indikator für die korrekte<br />

oder inkorrekte Ausführung verschiedener Programmteile<br />

dient.<br />

for-Schleifen<br />

Ein anderes nützliches Bindeglied in praktisch jeder Programmiersprache<br />

ist die for-Schleife. Sie dient zur Wiederholung<br />

einer Gruppe von Objekten, sodass wir einen bestimmten<br />

Codeblock auf jedes Objekt in gleicher Weise<br />

anwenden können. In Bash funktioniert das ähnlich wie die<br />

if-Anweisung:<br />

for file in $(ls); do<br />

echo ${file}<br />

done<br />

Nur ein weiteres äußerst simples Beispiel, aber auch hier soll<br />

ja nur die Syntax verdeutlicht werden. Nach dem Schlüsselwort<br />

for kommt immer eine Platzhalter-Variable, welche auf<br />

jeden Wert in dem Ausdruck nach dem Schlüsselwort in angewendet<br />

wird.<br />

Bringen Sie Ordnung in Ihre Projekte, indem Sie Ihren<br />

Programmcode in kleine Häppchen aufteilen und jedes in<br />

einer eigenen Datei ablegen.<br />

Redirections und <strong>Pi</strong>pes<br />

Bei allen vorangegangenen Beispielen<br />

wurden die Ausgaben auf dem Monitor<br />

dargestellt, und zwar in der Shell-<br />

Sitzung, die gerade auf Ihrem Terminal<br />

ausgeführt wurde. Sie können die<br />

Ausgabe aber auch „redirecten“, sprich<br />

umleiten.<br />

Programme senden ihre Ausgabe zu<br />

einer „<strong>Pi</strong>pe“ namens stdout. Diese <strong>Pi</strong>pe<br />

hat zwei Enden: Eine ist mit dem Programm<br />

verbunden, das für die Ausgabe<br />

verantwortlich ist, das andere Ende mit<br />

der Stelle, die die Ausgabe erhält und<br />

weiterleitet. In der Voreinstellung ist dies<br />

der Monitor, aber das ist nur eine der<br />

Möglichkeiten.<br />

Diese <strong>Pi</strong>pe können Sie auf zwei Arten<br />

manipulieren. Zum einen können Sie<br />

das Ausgabe-Ende neu verbinden,<br />

sodass die Ausgabe in eine Datei<br />

Eines haben alle guten Programmiersprachen gemeinsam:<br />

Funktionen. Diese sind auch unter Bash verfügbar und sind<br />

für Ihre Skripte praktisch unabdingbar. Die Erstellung und<br />

das Abrufen von Funktionen sind dabei denkbar einfach: Um<br />

eine neue Funktion zu definieren, geben wir ihr einen Namen,<br />

gefolgt von zwei runden Klammern, und stellen den zugehörigen<br />

Code in geschweifte Klammern:<br />

func () {<br />

echo ”My first function.”<br />

echo $1<br />

}<br />

func ”hello”<br />

Wie man an diesem Beispiel sehen kann, geschieht der Aufruf<br />

einer Funktion analog zu jedem anderen Bash-Code: Wir<br />

geben den Namen ein, gefolgt von einem beliebigen Argument.<br />

Diese Argumente können dann als numerische Variablen<br />

ausgeführt werden: $1 ist das erste Argument, $2 das<br />

zweite und so weiter.<br />

Derselbe Satz von Variablen gewährt uns auch Zugriff auf<br />

Argumente der Befehlszeilen des Skripts, sodass wir Programme<br />

schreiben können, die nur auf bestimmte Dateien<br />

angewendet werden oder sich nach benutzerdefinierten Präferenzen<br />

verhalten. Stellen wir uns vor, die folgende Datei sei<br />

als name.bash abgelegt:<br />

#!/bin/bash<br />

echo $1<br />

jon@adam ~$ ./name Jon<br />

Jon<br />

umgeleitet wird:<br />

echo ”Hello world” > hello.txt<br />

Die Umleitung geschieht dabei durch<br />

das Größer-Zeichen.<br />

Zum anderen verfügen Sie über die <strong>Pi</strong>pe<br />

stdin. Diese <strong>Pi</strong>pe wird zur Kontrolle<br />

einer Eingabequelle für ein Programm<br />

genutzt. Eine der leistungs fähigsten<br />

Funktionen von Bash ist die Möglichkeit,<br />

die stdout-<strong>Pi</strong>pe eines Programms<br />

mit der stdin-<strong>Pi</strong>pe eines anderen zu<br />

koppeln:<br />

ls | grep *.txt<br />

<strong>Das</strong> Verkettungszeichen | verbindet die<br />

Ausgabe des ls-Befehls mit der Eingabe<br />

des grep-Befehls, der in diesem Beispiel<br />

alle Ergebnisse bis auf jene ausfiltert, die<br />

auf .txt enden. Auf diese Art können Sie<br />

beliebig viele Programme miteinander<br />

verknüpfen.<br />

Nun sind Sie an der Reihe<br />

Aufbauend auf diesen Grundlagen können Sie mithilfe eigener<br />

Skripte alle möglichen Aufgaben auf Ihrem Linux-System<br />

automatisieren. Falls Sie an eine schwierige Stelle kommen,<br />

ziehen Sie bereits vorhandene Programme zur Unterstützung<br />

heran oder koppeln Sie mehrere einfachere Programme<br />

zur Lösung einer komplexen Aufgabe zusammen.<br />

77


Projekte<br />

dnsmasq: DNS<br />

Mit dnsmasq können Sie leicht einen DNS-Server (Domain Name<br />

System) aufsetzen.<br />

Vor nicht allzu langer Zeit war es noch ziemlich cool,<br />

wenn man überhaupt nur einen Computer zu Hause<br />

stehen hatte. Dann trat das Internet seinen Siegeszug<br />

an, und der eine Computer kommunizierte auf einmal mit der<br />

Welt. Kam noch ein zweiter Rechner hinzu, so verband man<br />

beide Maschinen ohne großen Aufwand miteinander, vergab<br />

statische IP-Adressen, und den Rest erledigten das Modem<br />

und der Internetprovider.<br />

Heute haben wir mehrere vernetzte Geräte, und einige<br />

davon klinken sich von verschiedenen Orten aus ein. <strong>Das</strong><br />

heißt, dass eine automatische Konfiguration notwendig ist,<br />

um Adressen zu organisieren, sie Geräten zuzuordnen und<br />

anderen Geräten mitzuteilen, unter welcher Adresse sie ein<br />

weiteres Gerät erreichen können. Zwei Protokolle sind hierbei<br />

wichtig. DNS (Domain Name System) ist quasi das Telefonbuch<br />

des Internets, es findet die IP-Adresse des Computers,<br />

mit dem Sie kommunizieren möchten, egal ob es die IP-Adresse<br />

des <strong>PC</strong>s im Nachbarzimmer ist oder eine große Suchmaschine.<br />

DHCP (Dynamic Host Configuration Protocol) ist<br />

das Protokoll, mit dem sich ein neues Netzwerkgerät anmeldet,<br />

um eine IP-Adresse zu erhalten. Dazu kommen weitere<br />

nützliche Dienste wie Netzwerk-Routing-Informationen und<br />

die Adressen von DNS-Servern.<br />

Domain Name System<br />

Normalerweise stellen Internetprovider oder große öffentliche<br />

Server DNS-Server bereit. Doch diese haben nur Informationen<br />

über öffentliche Adressen. Wie aber läuft das<br />

Ganze im Heimnetzwerk ab? In der Vergangenheit wurde<br />

dies mithilfe statischer Adressen und einer Liste aller Geräte<br />

in der Datei /etc/hosts für jeden angeschlossenen Rechner<br />

gelöst. Heutzutage ist das unpraktikabel, bedingt nicht nur<br />

durch die wachsende Anzahl von Geräten, sondern auch dadurch,<br />

dass die Vergabe statischer Adressen für mobile Geräte<br />

in der Praxis schwierig bis unmöglich ist.<br />

dnsmasq ist ein lokaler DNS-Server, der sich dem Management<br />

von Heimnetzwerken widmet. <strong>Das</strong> Tool hat einige Vorteile<br />

gegenüber Servern, die online arbeiten. Der erste Vorteil<br />

ist, dass Sie dnsmasq alle nötigen Informationen zum Netzwerk<br />

mitteilen können, dann löst das Tool Hostnamen für alle<br />

Geräte auf. Der zweite Vorteil liegt im Caching, das dnsmasq<br />

dnsmasq in Routern<br />

Wir haben dnsmasq als Dienst auf einem<br />

Computer beschrieben, doch einige<br />

Router haben bereits dnsmasq, um DHCP-<br />

Dienste und DNS-Caching bereitzustellen.<br />

Fast alles, was wir beschrieben haben,<br />

können Sie auch mit einer integrierten<br />

Installation von dnsmasq umsetzen. Voraussetzung<br />

ist, dass der Router Zugang<br />

zu seinen Konfigurationsdateien gewährt.<br />

<strong>Das</strong> geschieht über das Web-Interface<br />

des Routers, wo Sie die Einstellungen<br />

hineinkopieren können, die Sie normalerweise<br />

in eine Konfigurations-Textdatei<br />

tippen. Wenn ihr Router DD-WRT oder<br />

OpenWRT unterstützt, dann können Sie<br />

auch via SSH auf den Router zugreifen.<br />

<strong>Das</strong> Speichern von Einstellungen für jedes Gerät macht<br />

das Management eines dnsmasq-Setups einfacher.<br />

anbietet. Wenn ein Hostname nicht in der Liste der hosts-<br />

Datei gelistet ist, fragt das Tool die nötigen Informationen von<br />

einem öffentlichen DNS-Server ab. dnsmasq merkt sich die<br />

Antwort, sodass die Informationen bereitstehen, wenn sich<br />

ein zweiter Computer danach erkundigt.<br />

Sie können sich den Quellcode von dnsmasq von<br />

www.thekelleys.org.uk/dnsmasq herunterladen oder das<br />

Tool wie gewöhnlich mithilfe des Paketmanagers Ihrer Linux-<br />

Distribution installieren. Es ist keine spezielle Konfiguration<br />

nötig, damit Sie das Tool als DNS-Server für Ihr Heimnetzwerk<br />

nutzen können. Wenn der Rechner, auf dem Sie dnsmasq<br />

installieren möchten, Zugang zum Internet hat, können<br />

Sie es direkt starten. <strong>Das</strong> funktioniert ohne Umschweife,<br />

wenn Sie die Datei /etc/resolv.conf (mit den Adressen und<br />

Name-Servern, die Sie verwenden möchten) und Ihr Netzwerk<br />

bereits korrekt eingerichtet haben. Standardmäßig<br />

schaut dnsmasq zuerst in /etc/hosts und dann in /etc/<br />

resolv.conf nach, um Adressen aufzulösen. Die anderen<br />

Computer im Netzwerk brauchen nur die IP-Adresse des<br />

Rechners, auf dem dnsmasq eingerichtet ist, als primären<br />

DNS-Server. Unter Linux hieße das, dass die Datei /etc/<br />

resolv.conf die Information<br />

nameserver 192.168.1.1<br />

enthalten muss, wobei Sie die hier angegebene IP-Adresse<br />

mit der IP des entsprechenden dnsmasq-Rechners in Ihrem<br />

Heimnetzwerk ersetzen. Wenn Ihr Computer die Verbindungsinformationen<br />

via DHCP vom Router erhält, dann benötigen<br />

Sie die erwähnte IP-Adresse im Router-Interface.<br />

Dann verwendet jedes angeschlossene Gerät dnsmasq anstatt<br />

des entsprechenden Dienstes des Routers.<br />

Ein lokaler Name-Server ist nützlich, wenn alle Geräte mit<br />

einer statischen IP-Adresse ausgestattet sind. Dennoch erwarten<br />

die meisten Geräte eine dynamische Konfiguration via<br />

DHCP. Wie kann dnsmasq also die Adressen für jene Geräte<br />

wissen? Die einfache Antwort: dnsmasq besitzt einen integrierten<br />

DHCP-Server.<br />

Da der DHCP-Server die IP-Adressen verteilt, kennt er alle<br />

78


Projekte<br />

Server<br />

Adressen der im Netzwerk angeschlossenen Geräte. Es ergibt<br />

also Sinn, die zwei Prozesse zu kombinieren, so wie dnsmasq<br />

es tut. Wir müssen die Konfigurationsdatei anpassen,<br />

um dnsmasq als DHCP-Server arbeiten zu lassen. Die Datei<br />

befindet sich unter /etc/dnsmasq.conf. Sie enthält alle<br />

Standardeinstellungen. Im Falle eines Updates besteht die<br />

Gefahr, dass die Informationen überschrieben werden. Legen<br />

Sie also eine separate Datei /etc/dnsmasq.d/ an, und kommentieren<br />

Sie dann folgende Zeile am Ende der Datei /etc/<br />

dnsmasq.conf aus:<br />

conf-dir=/etc/dnsmasq.d<br />

Sie müssen aber noch die Einstellung der dhcp-range vornehmen,<br />

um den Server zu aktivieren. In der Standarddatei<br />

dnsmasq.conf lautet die entsprechende Zeile:<br />

#dhcp-range=192.168.0.50,192.168.0.150,12h<br />

Kopieren Sie diese Zeile in die lokale Konfigurationsdatei, entfernen<br />

Sie den Kommentar und passen Sie die beiden Adressen<br />

mit den Informationen Ihres Heimnetzwerks an. Es handelt<br />

sich um den Anfang und das Ende des Adressbereichs,<br />

aus dem sich dnsmasq bedienen kann. Die dritte Option stellt<br />

die Standardzeit für die Reservierung einer IP ein. Wenn Ihr<br />

Router DHCP-Fähigkeiten hat, schalten Sie diese aus, denn<br />

zwei DHCP-Server in einem Netzwerk können zu Verwirrungen<br />

führen. Nach jeder Änderung der Konfigurationsdatei<br />

von dnsmasq müssen Sie den Dienst neu starten. Alternativ<br />

senden Sie ein SIGHUP-Signal, um die Einstellungen neu zu<br />

laden. <strong>Das</strong> geht mit folgendem Befehl:<br />

killall -HUP dnsmasq<br />

Internet umleiten<br />

Ab diesem Zeitpunkt bekommt jedes im Netzwerk angeschlossene<br />

Gerät von dnsmasq eine IP-Adresse. Ins Internet<br />

kommen diese jedoch wahrscheinlich noch nicht. <strong>Das</strong> liegt an<br />

einer dritten Information, die ein DHCP-Server liefert: das<br />

Standard-Gateway. Wenn Sie dnsmasq die Information vorenthalten,<br />

dann geht das Tool davon aus, dass es sich um<br />

dieselbe IP wie die des Computers handelt, auf dem es installiert<br />

ist. Wenn Sie dnsmasq auf einem Router betreiben, dann<br />

funktioniert das. Ansonsten fügen Sie die folgende Zeile in die<br />

Konfigurationsdatei ein:<br />

dhcp-option=option:router,192.168.1.2<br />

Manchmal brauchen Sie eine statische Adresse, etwa für<br />

einen Dateiserver. Ein solches Setup ließe sich manuell per<br />

statischer Konfiguration einrichten, Sie müssen dnsmasq die<br />

Details jedoch stets mitteilen, damit das Tool den Hostnamen<br />

auflösen kann. Einfacher ist es, eine automatische Netzwerkkonfiguration<br />

einzustellen und dem Tool zu sagen, dass<br />

es eine bestimmte IP immer gleich vergeben soll. Hier erweist<br />

sich eine zweite Konfigurationsdatei als nützlich. Sie können<br />

eine allgemeine und für jeden Host eine spezielle Datei einrichten.<br />

Ein Beispiel:<br />

dhcp-host=B8:27:EB:8B:6F:CF,192.168.1.11,jeltz<br />

txt-record=jeltz,”<strong>Raspberry</strong> <strong>Pi</strong> file server”<br />

dnsmasq ist nicht BIND<br />

Womöglich haben Sie beim Thema<br />

DNS schon von BIND gehört. BIND<br />

ist die Standardsoftware auf großen<br />

DNS-Servern. Wenn Sie einen<br />

für das Internet geöffneten DNS-<br />

Server nutzen möchten, um Ihre<br />

Domains zu organisieren, dann ist<br />

BIND sinnvoll. dnsmasq arbeitet<br />

anders, es ist für kleine private<br />

Netzwerke gedacht. Es hat weder<br />

die Leistungsfähigkeit noch die<br />

Komplexität, die BIND mitbringt.<br />

Die dhcp-host-Einstellungen haben Vorrang, sie enthalten<br />

alle drei Informationen, getrennt durch Kommata: MAC-Adresse,<br />

IP-Adresse und Hostname. Die zweite Zeile verknüpft<br />

einen Computer mit einer einfachen Beschreibung. Sie wird<br />

angezeigt, wenn Sie<br />

dig +short hostname txt<br />

eintippen. <strong>Das</strong> ist nützlich, sobald das Netzwerk größer wird<br />

und andernfalls die Übersicht verloren geht. Wenn alle Netzwerkeinstellungen<br />

unter einem Dach sind, dann sind Management<br />

und Backups deutlich einfacher. Da alle Geräte im<br />

Normalfall für eine automatische Einrichtung eingestellt sind,<br />

müssen Sie keinerlei Einstellungen vornehmen.<br />

Bei einem Laptop mit Kabel- und WLAN-Verbindung sind<br />

zwei MAC-Adressen im Spiel. Wenn Sie wollen, dass sich der<br />

Laptop stets mit derselben Adresse verbindet, dann müssen<br />

Sie einfach beide MAC-Adressen spezifizieren, getrennt<br />

durch Kommata:<br />

dhcp-host=20:68:9d:bc:08:f5,50:46:5d:32:e2:51,192.168.1.8,<br />

hostname<br />

Haben Sie dies eingetragen, sollten Sie nicht probieren,<br />

beide Verbindungen aufzubauen, da es sonst zu Problemen<br />

kommen wird.<br />

Die Informationen auf diesen Seiten kratzen nur an der<br />

Oberfläche der Möglichkeiten, die dnsmasq bietet. Ist das<br />

Tool einmal eingerichtet, lesen Sie sich die Kommentare in<br />

der Standardkonfiguration sowie das FAQ auf der Projekt-<br />

Website durch. So werden Sie neue Anwendungsgebiete für<br />

das Tool kennenlernen und weitere Ideen sammeln.<br />

Wenn Ihr<br />

Router dnsmasq<br />

verwendet, dann<br />

können Sie die<br />

gewünschten<br />

Einstellungen<br />

einfach in das<br />

Web-Interface<br />

kopieren.<br />

79


Projekte<br />

Syslog: Loggen per<br />

System-Logger sind leistungsfähige Programme zur Überwachung – wir<br />

erklären Ihnen, wie Sie den Datenwust filtern und nützliche Infos an Ihr E-Mail-<br />

Konto senden.<br />

Logwatch zeigt<br />

Ihnen übersichtlich,<br />

was in 24<br />

Stunden auf<br />

Ihrem Computer<br />

passiert ist.<br />

<strong>Das</strong> Programm syslog, ein System-Logger, läuft auf<br />

Ihrem Computer im Hintergrund. Es sammelt Informationen<br />

über andere Programme, die Sie auf Ihrem<br />

Rechner ausführen – es weiß sogar mehr über Ihr System als<br />

Google oder Facebook.<br />

Programme müssen mit dem Anwender kommunizieren.<br />

Ein Programm mit einer interaktiven grafischen Benutzeroberfläche<br />

kann Ihnen beispielsweise direkt per Benachrichtigungsfenster<br />

mitteilen, wenn es die ihm gestellte Aufgabe<br />

ausgeführt hat oder wenn ein Fehler aufgetreten ist. Bei Hintergrundprogrammen<br />

geht dies jedoch nicht. Jedes Programm<br />

könnte zwar seine eigenen Log-Dateien anlegen, das<br />

würde aber bedeuten, dass sich diese Dateien über den ganzen<br />

Computer verteilen. Oder jedes Programm bräuchte eine<br />

Root-Berechtigung, um Log-Daten an einem zentralen Sammelpunkt<br />

abzulegen. Der syslog-Dämon schafft Abhilfe: Ein<br />

Programm übermittelt Informationen an syslog, und syslog<br />

schreibt die Informationen in eine Log-Datei. So benötigt nur<br />

syslog tiefere Zugriffsrechte, nicht jedoch die anderen Programme.<br />

Sie können alle Mitteilungen in einer einzigen Datei<br />

sammeln und müssen sich dabei keine Gedanken über etwaige<br />

Konflikte zwischen Programmen machen, die gleichzeitig<br />

in diese Datei schreiben wollen – syslog organisiert dies einfach<br />

im Hintergrund.<br />

Wie meistens bei Linux gibt es eine Auswahl verschiedener<br />

System-Logger – die wichtigsten Implementierungen sind<br />

syslog-ng, rsyslog, sysklogd und metalog. Jeder Logger hat<br />

spezifische Vor- und Nachteile, doch alle verfügen über die<br />

gleiche Schnittstelle zum Rest des Systems. Der Hauptunterschied<br />

betrifft den Ort des Mail-System-Logs. Dieses befindet<br />

sich zwar immer in /var/log, aber je nach verwendeter<br />

Distribution kann es messages, current oder syslog heißen.<br />

Wir verwenden /var/log/messages in unseren Beispielen,<br />

Sie müssen dies gegebenenfalls durch den entsprechenden<br />

Begriff Ihres Systems ersetzen. <strong>Das</strong> Format des System-<br />

Logs bleibt mit jeweils einem Eintrag pro Zeile immer gleich.<br />

Jun 25 15:34:34 hactar sudo: nelz : TTY=pts/2 ; PWD=/<br />

home/nelz ; USER=root ; COMMAND=/sbin/fdisk /dev/sda<br />

Die beiden ersten Items – Datum und Zeit – sind offensichtlich,<br />

es folgt der Hostname. System-Logger können auch<br />

Nachrichten an andere Computer schicken, an dieser Stelle<br />

wird der Hostname wichtig. <strong>Das</strong> nächste Item ist das Programm,<br />

dass den Log-Eintrag vornimmt, in diesem Falle<br />

sudo, und der Rest ist die Nachricht von sudo. Im Beispiel<br />

wird Aufschluss darüber gegeben, welcher User von welcher<br />

Stelle aus etwas ausgeführt hat.<br />

Bleiben Sie auf dem Laufenden<br />

Sie haben nun also eine Datei in /var/log, die sich mit allerlei<br />

Informationen darüber füllt, was in Ihrem System vor sich<br />

geht. Welchen Nutzen haben Sie davon? Zum einen dient die<br />

Datei als Diagnose-Tool und hilft Ihnen herauszufinden,<br />

woran es liegt, wenn etwas nicht wie erwartet funktioniert.<br />

Zum anderen können Sie damit Ihr System auf verdächtige<br />

Aktivitäten hin beobachten, wie zum Beispiel wiederholte<br />

fehlgeschlagene Log-in-Versuche von immer derselben<br />

Internetadresse.<br />

Die einfachste Möglichkeit, die Diagnosefunktion zu nutzen,<br />

ist, die Log-Datei mit einem Terminal-Pager wie less einzulesen<br />

oder sie mit grep zu durchsuchen. Wenn Sie den<br />

Namen des Programms kennen, ist es recht einfach, die relevanten<br />

Zeilen aufzuspüren. Sie können die Datei aber auch<br />

mittels tail interaktiv überwachen:<br />

tail -f /var/log/messages<br />

zeigt die letzten zehn Zeilen des Logs und dann jede neue<br />

Nachricht, die hinzugefügt wird. Wenn Sie dies vor einer<br />

80


Projekte<br />

E-Mail<br />

Aktion ausführen, bekommen Sie sogleich das Resultat der<br />

Aktion angezeigt. Beispielsweise sehen Sie nach Einstecken<br />

eines USB-Datenträgers:<br />

Jun 25 15:38:34 hactar kernel: sd 9:0:0:0: Attached scsi<br />

generic sg9 type 0<br />

Jun 25 15:38:34 hactar kernel: sd 9:0:0:0: [sdi] 3893248 512-<br />

byte logical blocks: (1.99 GB/1.85 GiB)<br />

Hier ist der Kernel das Programm, welches die Nachrichten<br />

sendet, und Sie können das Gerät sehen, das dem Datenträger<br />

zugewiesen ist. Damit sind Sie auf der sicheren Seite,<br />

wenn Sie mittels dd auf das Gerät schreiben möchten.<br />

Logwatch und Logcheck<br />

Eine Log-Datei öffnen Sie in der Regel nur dann, wenn Sie ein<br />

Problem lösen müssen, und eher selten aus Spaß an der<br />

Freud. Allerdings können wichtige Nachrichten geloggt werden,<br />

während Sie nicht hinschauen. Es gibt eine ganze Anzahl<br />

von Programmen, mit denen Sie Log-Dateien überwachen<br />

können, etwa Logwatch (www.logwatch.org). Dieses Programm<br />

liest Ihr System-Log einmal täglich aus, fasst ungewöhnliche<br />

und verdächtige Einträge zusammen und sendet<br />

Ihnen das Ganze in Form einer E-Mail zu. Die Standard-Konfigurationsdatei<br />

befindet sich in /usr/share/logwatch/<br />

default.conf/logwatch.conf, da diese jedoch bei einem Update<br />

überschrieben wird, sollten Sie etwaige Änderungen<br />

lieber in /etc/logwatch/conf/logwatch.conf vornehmen –<br />

Letztere hat Vorrang vor Ersterer. Sie können die neue Konfigurationsdatei<br />

selber von Grund auf erstellen oder einfach<br />

die Standard-Datei kopieren und bearbeiten. Zuletzt müssen<br />

Sie MailTo auf die E-Mail-Adresse setzen, zu der die Reports<br />

geschickt werden sollen. Mithilfe eines entsprechenden<br />

MailFrom-Eintrags erleichtern Sie das Filtern dieser E-Mails.<br />

Weitere Schlüsseleinstellungen sind Detail (die Menge an<br />

Informationen in den Mails), Range (der Zeitraum, den eine<br />

Mail abdeckt) und Service (welches die auszuführenden<br />

Scans festlegt). Die Grundeinstellungen für Service ist „All“,<br />

aber Sie können einzelne Dienste mittels<br />

Service = -foo<br />

ausschließen (hier würde zum Beispiel foo ausgeschlossen).<br />

Die Dienste werden in /usr/share/logwatch/scripts/<br />

services festgelegt, mit einem Skript für jeden Dienst mit<br />

einem beschreibenden Kommentar. Sie werden mit den betreffenden<br />

Dateien in /usr/share/logwatch/default.conf/<br />

services konfiguriert. Wie auch die Standard-Konfigurationsdatei<br />

können alle diese Dateien in das entsprechende Verzeichnis<br />

/etc/logwatch kopiert und dort Ihren Wünschen<br />

entsprechend angepasst werden. Sie können dabei den Detailgrad<br />

der Nachrichten für jeden Dienst unabhängig von der<br />

Grundeinstellung wählen.<br />

Falls Sie sich etwas Unmittelbareres wünschen als Logwatch,<br />

dann schauen Sie sich in diesem Falle einmal Logcheck<br />

an (http://packages.debian.org/sid/logcheck).<br />

Dies ist zwar eine Debian-Seite, aber das Programm ist für<br />

die meisten Distributionen verfügbar. Es arbeitet ähnlich wie<br />

Logwatch, wurde aber entwickelt, um häufiger ausgeführt zu<br />

werden; in der Voreinstellung genau einmal pro Stunde. Die<br />

Reports sind nicht so detailliert wie bei Logwatch, beinhalten<br />

dafür aber eine stündliche Zusammenfassung über<br />

„interessante“ Einträge. Darüber hinaus merkt sich das Programm<br />

den letzten Zugriff auf ein Log, sodass unabhängig<br />

vom Intervall nur neue Einträge dargestellt werden. Die „interessanten“<br />

Einträge sind dabei diejenigen, die übrig bleiben,<br />

nachdem alle harmlosen Einträge – die stets einen großen<br />

Teil eines System-Logs ausmachen – herausgefiltert wurden.<br />

Nach der Installation von Logcheck können Sie zwei Konfigurationsdateien<br />

editieren: In /etc/logcheck/logcheck.<br />

conf setzen Sie das Reportlevel auf Workstation (für Desktopsysteme),<br />

Server oder Paranoid. Sendmailto ist selbsterklärend,<br />

muss aber eingeschaltet werden, während Syslogsummary<br />

auf Einstellung 1 eine Übersicht über die Log-<br />

Ereignisse anstelle einer bloßen Liste gibt (dafür müssen Sie<br />

das Paket syslog-summary installieren). Die andere Datei ist<br />

/etc/logcheck/log.logfiles, welche eine Liste der zu überprüfenden<br />

Dateien enthält – bei syslog-ng ist dies /var/log/<br />

messages.<br />

Nun erhalten Sie stündlich E-Mails mit neuen Einträgen<br />

Ihres System-Logs. Wenn Ihnen diese Mails zu ausführlich<br />

sind, können Sie eine Liste bemühen, die harmlose Einträge<br />

schlicht ignoriert. Diese geht allerdings auf Nummer sicher,<br />

sodass Sie vermutlich nachjustieren möchten, insbesondere<br />

wenn Sie öfters Cronjobs ausführen. Wenn Sie einen Blick in<br />

/etc/logcheck/ignore.d.workstation (oder server, je nach<br />

Profil) werfen, sehen Sie Dateien, die zu ignorierende Ausdrücke<br />

enthalten. Editieren Sie diese Dateien nicht, sondern erstellen<br />

Sie stattdessen selbst eine, beispielsweise mit dem<br />

Namen local. Jede Zeile dieser Datei ist ein regulärer Ausdruck<br />

zum Ignorieren. <strong>Das</strong> folgende Beispiel ignoriert das Anschließen<br />

eines USB-Datenträgers:<br />

Jun 25 15:38:34 hactar kernel: sd 9:0:0:0: Attached scsi<br />

generic sg9 type 0<br />

Sie können dafür folgenden regulären Ausdruck benutzen:<br />

^\w{3} [ :0-9]{11} [._[:alnum:]-]+ kernel: sd .* Attached scsi<br />

generic .*<br />

Lassen Sie sich von der Syntax nicht beeindrucken, sie folgt<br />

dem üblichen Format. Der erste Teil zeigt Zeit, Datum und<br />

Hostnamen auf. Danach sucht das Programm nach „Kernel“,<br />

gefolgt von einem String, der „Attached scsi generic“ enthält.<br />

Sie sollten diese Ausdrücke so spezifisch wie möglich machen,<br />

um falsche Übereinstimmungen auszuschließen. Sie<br />

können die Ausdrücke mit egrep in einer Datei testen:<br />

egrep -f /etc/logcheck/ignore.d.workstation/local /var/log/<br />

messages<br />

Dieser Code gibt alle übereinstimmenden Zeilen aus, die<br />

Sie nicht im Report von Logcheck wünschen.<br />

Logcheck liefert<br />

stündliche Reports,<br />

benötigt aber<br />

Filtereinstellungen,<br />

um Sie nicht<br />

mit belanglosen<br />

Ereignissen zu<br />

belasten.<br />

81


Projekte<br />

Desktop: Eigene<br />

Ja, Sie können Ihre eigene, hochgradig angepasste, genügsame<br />

Desktopumgebung bauen, ohne dafür eine einzige Zeile Code schreiben zu<br />

müssen. Wir verraten Ihnen, wie.<br />

Titelleisten und Schnellzugriffe, Panels und Benachrichtigungsbereiche<br />

sowie nicht zuletzt Desktophintergründe<br />

sind allesamt Dinge,<br />

Auswahl des Fenstermanagers<br />

die wir von einer modernen Desktopumgebung erwarten.<br />

Normalerweise werden diese Funktionen von unterschiedlichen<br />

Einzelprogrammen zu Verfügung gestellt. Wenn Sie<br />

also Xfce nutzen und ps ax in ein Terminal eingeben, so wird<br />

xfwm als Fenstermanager genutzt, xfce4-panel für Panels –<br />

und so weiter. Wenn Sie diese Programme beenden, werden<br />

Teile Ihrer Desktopumgebung vom Bildschirm verschwinden.<br />

KDE und Gnome funktionieren ganz ähnlich.<br />

Schön und gut, aber wir sind schließlich Linux-Geeks. Die<br />

Grundkonfiguration macht einen ordentlichen Job, aber wir<br />

nutzen dieses Betriebssystem, um es unseren Bedürfnissen<br />

anzupassen, um jene Teile herauszureißen, welche uns keinen<br />

Spaß machen, und um die inneren Funktionsabläufe des<br />

Systems zu verstehen. Sie können jedes dieser Programme<br />

für sich genommen ersetzen, Sie können aber auch Ihre eigene<br />

Kombination aus Fenstermanager, Panels, Desktop-Switcher<br />

und so weiter anlegen.<br />

Es gibt zahlreiche leichtgewichtige Fenstermanager, die<br />

nur das unbedingt nötige Minimum an Funktionalität besitzen,<br />

weshalb andere Entwickler die restlichen Teile geschrieben<br />

haben, die man für eine voll funktionsfähige Desktopumgebung<br />

braucht. Wir sehen uns die möglichen Optionen an<br />

und zeigen Ihnen, wie Sie sie zu einem personalisierten Desktop<br />

zusammensetzen. Falls Sie KDE, Gnome oder Xfce nutzen,<br />

werden Sie feststellen, dass das Resultat ein wesentlich<br />

flotterer und speichersparenderer Rechner sein wird.<br />

Wenn Sie einen<br />

Fenstermanager<br />

über die Paketverwaltung<br />

hinzufügen,<br />

sollte<br />

auch eine entsprechende<br />

Session<br />

erzeugt werden.<br />

Wir zeigen<br />

Ihnen aber auch,<br />

wie das manuell<br />

funktioniert.<br />

Der Fenstermanager ist die weitaus wichtigste Komponente<br />

einer Desktopumgebung. Ein Fenster ist im Normalfall mit<br />

einer Titelleiste ausgestattet, sodass Sie es auf dem Bildschirm<br />

umherschieben können, sowie mit Buttons zum Maximieren,<br />

Schließen und so weiter. Der Fenstermanager ermöglicht<br />

auch das Vergrößern und Verkleinern eines<br />

Fensters an dessen Rändern. Ohne Fenstermanager würde<br />

eine Anwendung zwar auch funktionieren, doch Sie wären<br />

nicht in der Lage, sie zu verschieben oder zu skalieren. Es<br />

gibt einige neuartige Fenstermanager, die anders an die<br />

Sache herangehen, indem Sie beispielsweise die Programme<br />

in einem Gitter anordnen und somit keine Titelleisten<br />

nötig sind.<br />

In diesem Tutorial beschreiben wir die besten Vertreter<br />

und erklären, wie Sie sie benutzen.<br />

Wenn Sie die Fenstermanager über den<br />

Paketmanager installieren, sollte es<br />

möglich sein, dass Sie nach dem Ausund<br />

Wiedereinloggen zwischen den<br />

Fenstermanagern wählen können.<br />

Wenn Sie keinen Eintrag für Ihren Fenstermanager<br />

sehen, probieren Sie eine<br />

Fallback- oder Terminal-Option im Login-Bildschirm aus: Einige<br />

Distributionen bieten diese Möglichkeit an. Über das Terminal<br />

können Sie den Fenstermanager mithilfe der unten genannten<br />

Befehle starten. Falls Sie das neue Programm gar<br />

nicht starten können, brauchen Sie sich keine Sorgen zu machen.<br />

Wir zeigen Ihnen später, wie Sie sich selbst eine neue<br />

Login-Session erstellen können.<br />

Name: JWM<br />

Website: http://joewing.net/projects/jwm/<br />

Befehl zum Starten: jwm<br />

JWM ist sehr schlank, in C geschrieben und benötigt nur<br />

die Bibliotheken des X-Displayservers als Abhängigkeiten.<br />

Deshalb arbeitet er auch pfeilschnell. JWM hat ein brauchbares<br />

Standardpanel mit allerdings wenigen Features wie Programme-Menü,<br />

Desktop-Umschalter und Taskleiste. Standardmäßig<br />

enthält das Programme-Menü (das auch per<br />

Rechtsklick auf dem Desktop erreichbar ist) nur Einträge, die<br />

Ihnen das Starten eines Terminals sowie das Abmelden oder<br />

Sperren des Benutzerkontos erlauben. Sie editieren das<br />

Menü in der Datei /etc/jwm/system.jwmrc. Die XML-basierte<br />

Konfigurationsdatei ist leicht zu verstehen, über sie<br />

können Sie die Schriftart und Tastenkombinationen des<br />

82


Projekte<br />

Schreibtische<br />

Fenstermanagers anpassen.<br />

Name: Openbox<br />

Website: www.openbox.org<br />

Befehl zum Starten: openbox<br />

Openbox gehört – wie auch Fluxbox – zur „*box“-Familie<br />

der Fenstermanager, die sich auf den Stammvater Blackbox<br />

gründet. Openbox ist vermutlich der beliebteste Leichtgewicht-Fenstermanager<br />

und wird beim LXDE-Desktop verwendet.<br />

Die Standardkonfiguratuion von Obenbox ist so<br />

knapp wie möglich gehalten: Sobald Sie ihn starten, sehen<br />

Sie erstmal eines: nichts. Bis auf den Mauszeiger, der in der<br />

Mitte des Bildschirms verweilt. Mit einem Rechtsklick öffnet<br />

sich ein kleines Kontextmenü, über das Sie ein Terminal,<br />

einen Browser oder das Konfigurationswerkzeug aufrufen<br />

können. Genau dieses Tool ist der Grund dafür, dass Openbox<br />

unsere erste Wahl für Eigenbau-Desktops ist: Hier können<br />

wir nämlich fast alles konfigurieren, ohne in Textdateien<br />

herumstochern zu müssen. Zudem ist Openbox sehr standardkonform<br />

und arbeitet daher wunderbar mit anderen<br />

Werkzeugen zusammen. Die Tastenkombinationen sind wie<br />

gewohnt: Mit [Alt]+[Tab] wechseln Sie durch die Fenster,<br />

[Alt]+[F4] schließt Programme, und [Strg]+[Alt]+[Links/<br />

Rechts] wechselt die Desktops.<br />

Name: Ratpoison<br />

Website: http://ratpoison.wxcvbn.org<br />

Befehl zum Starten: ratpoison<br />

Hier haben wir eine sehr ungewöhnliche Art von Fenstermanager:<br />

Ratpoison wurde um ein „Tiling“ genanntes Konzept<br />

herum konstruiert. Anders als beim sonst üblichen Konzept<br />

verschiebbarer, sich überlappender Fenster belegen bei<br />

Ratpoison die Fenster eine bestimmte Fläche auf dem Bildschirm.<br />

Es dauert eine Weile, sich daran zu gewöhnen, aber<br />

sobald Sie sich die Tastenkombinationen für die Arbeit mit<br />

den Fenstern eingeprägt haben, sind Sie weniger von der<br />

Maus abhängig. Deshalb auch der Name „Rattengift“. Beim<br />

ersten Start ist Ratpoison fast komplett nackt, und Sie werden<br />

feststellen, dass die Maus keine Funktion erfüllt. Drücken<br />

Sie [Strg]+[t], gefolgt von [!], und es erscheint ein kleiner<br />

Kasten in der rechten oberen Ecke, in den Sie ein Kommando<br />

eingeben können (zum Beispiel xterm). Wenn Sie ein Programm<br />

starten, wird es standardmäßig im Vollbildmodus<br />

ausgeführt. Haben Sie mehrere Fenster geöffnet, schalten<br />

Sie mit [Strg]+[t], gefolgt von [n] und [p], zwischen ihnen<br />

Die gleiche Sprache sprechen<br />

Es ist kein Zufall, dass die genannten<br />

Tools so wunderbar zusammenarbeiten.<br />

Kritiker werfen Linux vor, ein Mischmasch<br />

aus alten und neuen Technologien zu<br />

sein, die kaum etwas zusammenhält, was<br />

allerdings nicht gerecht ist. Richtig, es<br />

gibt immer noch eine Menge alten Code<br />

zu finden, aber die Programme arbeiten<br />

dank Standards trotzdem zusammen.<br />

EWMH, die „Extended Window Manager<br />

Hints“-Spezifikation, legt die Interaktionsmöglichkeiten<br />

zwischen den Fenstermanagern,<br />

den Anwendungen und<br />

den Werkzeugen fest. Sie ermöglicht<br />

also den Komponenten, Informationen<br />

auszutauschen, um dem Nutzer eine<br />

Erfahrung aus einem Guss zu bieten. Ein<br />

gutes Beispiel sind Desktop-Umschalter:<br />

Diese bieten oft eine Miniaturansicht<br />

der Desktops und der gerade laufenden<br />

Programme. Normalerweise möchten Sie<br />

in diesen Voransichten nur die Anwendungsfenster<br />

sehen, nicht auch noch<br />

das ganze Desktop-Drumherum. Dank<br />

EWMH kann ein Panel oder ein Fenstermanager<br />

dem Desktop-Umschalter<br />

sagen, dass ein bestimmtes Fenster<br />

dort nicht sichtbar sein soll. Die vollständige<br />

Spezifikation finden Sie unter<br />

http://standards.freedesktop.org/<br />

wm-spec/wm-spec-latest.html. Sie<br />

ist lang, aber zwingend notwendig, sollten<br />

Sie den Ehrgeiz entwickeln, einen<br />

eigenen Fenstermanager zu schreiben.<br />

um. Geben Sie [Strg]+[t] [w] ein, um eine nummerierte Liste<br />

aller Fenster zu erhalten, [Strg]+[t], gefolgt von einer Ziffer,<br />

um auf das entsprechende Fenster umzuschalten. Der wirkliche<br />

Spass beginnt mit dem Tiling-Modus: Drücken Sie<br />

[Strg]+[t] [s] mit einem neu geöffneten Fenster, um den Bildschim<br />

horizontal in zwei Flächen zu teilen, Rahmen genannt.<br />

<strong>Das</strong> aktuelle Fenster wird im oberen Rahmen angezeigt, das<br />

vorherige darunter. <strong>Das</strong> Drücken von [Strg]+[t] [S] (Großbuchstabe)<br />

teilt den Bildschirm vertikal. <strong>Das</strong> ist besonders<br />

toll, wenn Sie einen großen Monitor mit einer hohen Auflösung<br />

benutzen, auf dem Sie beispielsweise einen großen<br />

Rahmen für den Webbrowser anlegen können, während Sie<br />

daneben mehrere kleine Rahmen für diverse Terminal-Sessions<br />

nutzen. Die Tastenkombination [Strg]+[t], gefolgt von<br />

einer der Cursor-Tasten, hilft Ihnen beim Umschalten zwischen<br />

den Rahmen. Sie können einen Rahmen auch wieder<br />

im Vollbild anzeigen, indem Sie [Strg]+[t] [Q] tippen. Eine<br />

Liste aller Tastenkombinationen erhalten Sie über die Eingabe<br />

von [Strg]+[t] [?]. Hier hilft auch das Ratpoison-Wiki unter<br />

http://tinyurl.com/obcarv5.<br />

Auch die folgenden Fenstermanager sind einen Blick wert:<br />

Sawfish (http:/sawfish.wikia.com/wiki/)<br />

WindowLab (http://nickgravgaard.com/windowlab/)<br />

Pekwm (www.pekwm.org)<br />

Auswahl des Panels<br />

Den Job der Fensterverwaltung haben wir nun also vergeben.<br />

Nun möchten wir ein Panel zum Starten von Programmen,<br />

zum Umschalten zwischen ihnen und den Desktop-Flächen,<br />

zum Anzeigen einer Uhr und so weiter. JWM beinhaltet ein<br />

einfaches Panel, aber wir hätten gerne ein paar zusätzliche<br />

Funktionen.<br />

Name: Docky<br />

Website: www.go-docky.com<br />

Befehl zum Starten: docky<br />

Docky ist ziemlich cool. Es ist ein umfangreiches Panel und<br />

hat viele Abhängigkeiten – falls Sie also planen, einen Desktop<br />

für Maschinen mit wenig Speicher zu entwerfen, sollten<br />

Sie lieber zu einer anderen Option greifen. Docky sollten Sie<br />

in den Repositorys der meisten Distributionen finden. Zur Installation<br />

reicht ein sudo apt-get install docky, sofern Sie<br />

mit einer Ubuntu-basierten Distribution arbeiten. Wenn Sie<br />

Docky starten, sehen Sie ein kleines schwarzes Panel am unteren<br />

Bildschirmrand. Es gibt ein einziges kleines Anker-Icon,<br />

83


Projekte<br />

welches den Einstellungsdialog öffnet. Hier aktivieren Sie den<br />

Panel-Modus, welcher Docky auf die gesamte Bildschirmbreite<br />

ausdehnt. Wechseln Sie zum Docklets-Tab des Einstellungsdialogs,<br />

um dem Panel weitere statische Items hinzuzufügen<br />

wie etwa eine Uhr, einen Umschalter für den Desktop<br />

oder eine Batterieanzeige. Docky bringt kein Hauptfenster<br />

mit, was eine gewisse Einschränkung darstellt. Starten Sie jedoch<br />

Programme über Ihren Fenstermanager, tauchen diese<br />

auf dem Panel auf. Rechtsklicken Sie die Icons und wählen<br />

Sie „<strong>Pi</strong>n to dock“, um sie im Panel anzuheften. Auf diese<br />

Weise füllen Sie das Panel mit den meistgenutzten Programmen,<br />

weshalb das Fehlen eines Hauptfensters dann doch<br />

kein so großer Nachteil ist.<br />

Name: Cairo-Dock<br />

Website: http://glx-dock.org<br />

Befehl zum Starten: cairo-dock<br />

Wenn Sie auf ein schönes Design Wert legen, ist Cairo-<br />

Dock vielleicht etwas für Sie. Sein Aussehen ähnelt stark dem<br />

von OS X, mit edlen Reflexions-Effekten und feinen Linien, die<br />

die verschiedenen Flächen voneinander trennen. Icons werden<br />

größer, wenn Sie den Mauszeiger darüber bewegen. Machen<br />

Sie dasselbe bei einem Ordner, zeigt dieser eine Voransicht<br />

seines Inhalts an. <strong>Das</strong> Programm ist wunderschön<br />

designt, nimmt aber auch Ihre Grafikkarte dementsprechend<br />

in Beschlag. Im Gegensatz zu Docky bringt Cairo-Dock ein<br />

Hauptfenster mit, basierend auf den Systemeinstellungen.<br />

Mit anderen Worten: Es zeigt jene Icons, die Sie auch unter<br />

anderen Fenstermanagern und Desktops sehen würden. Sie<br />

können jedes Bild rechtsklicken und konfigurieren. <strong>Das</strong> Panel<br />

selbst passen Sie unter Cairo-Dock > Configure an. Es ist<br />

wirklich sehr konfigurierbar, zudem gibt es viele aktivierbare<br />

Add-ons, anpassbare Tastenkombinationen sowie modifizierbare<br />

Größen- und Positionseinstellungen.<br />

Name: WBar<br />

Website: http://code.google.com/p/wbar/<br />

Befehl zum Starten: wbar<br />

Hierbei handelt es sich um das schlankste der hier vorgestellten<br />

Panels. Deshalb startet es auch fast ohne<br />

Openbox hat sein eigenes Konfigurationswerkzeug, was<br />

das Herumfummeln in Textdateien unnötig macht.<br />

Verzögerung. Es bietet einen durchsichtigen Hintergrund,<br />

animierte wachsende Icons, wenn Sie den Mauszeiger darüber<br />

bewegen, und nicht zuletzt ein grafisches Konfigurationswerkzeug<br />

(wbar-config; separat installieren). Standardmäßig<br />

wird WBar vertikal angezeigt, Sie können dies jedoch ändern,<br />

wenn Sie das oberste Icon anklicken. Über den Icons-Reiter<br />

fügen Sie weitere Start-Icons hinzu. Wenn Sie sich vom Panel<br />

wünschen, sich mehr wie eine Taskleiste zu verhalten, finden<br />

Sie eine Option dazu im Preferences-Tab. In der Effects-Registerkarte<br />

finden Sie die Einstellungen für die Zoomstufe, die<br />

Transparenz und die Abstände zwischen den Icons.<br />

Weitere Panels (teils jedoch etwas veraltet):<br />

tint2 (http://code.google.com/p/tint2/)<br />

PerlPanel (http://savannah.nongnu.org/projects/<br />

perlpanel)<br />

Avant Window Navigator (https://launchpad.net/awn)<br />

Hinzufügen von Extras<br />

Die meisten spärlich ausgestatteten Fenstermanager erlauben<br />

es nicht, selber ein Hintergrundbild auszuwählen. <strong>Das</strong><br />

bedeutet, dass Sie dafür ein separates Werkzeug benötigen.<br />

hsetroot ist ein kleines Programm, das als eigenständiges<br />

Paket auf fast jeder Distribution zur Verfügung steht oder<br />

manchmal als Teil der HackedBox (ein anderer schlanker<br />

Fenstermanager). Sobald Sie hsetroot installiert haben, ist<br />

es ganz einfach wie folgt zu verwenden:<br />

hsetroot -full /path/to/image.jpg<br />

Dieser Befehl bringt das komplette Bild auf den Bildschirm,<br />

ohne irgendwelche Anpassungen. Andere Optionen sind<br />

-center, -tile und -fill (um es zu strecken). Sie können auch<br />

PNG-Bilder und andere Formate verwenden.<br />

Falls Ihr Dock oder Panel keinen Umschalter für die<br />

Desktops mitbringt, brauchen Sie einen eigenständigen. In<br />

dieser Kategorie gibt es leider keine so große Auswahl, wir<br />

empfehlen allerdings den NetWMPager, der aufgrund seiner<br />

minimalen Abhängigkeiten fast überall funktioniert. Sie finden<br />

ihn unter http://sourceforge.net/projects/sfxpaint/files/netwmpager/.<br />

Laden Sie sich dort den aktuellsten<br />

Quellcode herunter, und kompilieren Sie ihn wie folgt:<br />

tar xfv netwmpager-2.04.tar.bz2<br />

cd netwmpager-2.04<br />

./configure<br />

make<br />

sudo make install<br />

Wenn Sie beim make-Schritt der Fehlermeldung „undefined<br />

reference to symbol XGetWindowAttributes“ begegnen,<br />

Sie möchten<br />

sich ein schicken<br />

Desktop wie bei<br />

OS X bauen?<br />

Greifen Sie zu<br />

Cairo-Dock!<br />

84


Projekte<br />

editieren Sie config.mk und ändern die Zeile XFT_LIBS wie<br />

folgt:<br />

XFT_LIBS = -lXft -lX11<br />

Speichern Sie die Datei und führen Sie die letzten beiden<br />

Schritte erneut aus. Nun können Sie das Programm mit<br />

netwmpager starten. Sie sehen, wie Ansichten der Desktops<br />

in der linken unteren Ecke des Bildschirms erscheinen. Standardmäßig<br />

sind diese sehr klein. Um dies zu ändern, müssen<br />

Sie die Datei /usr/local/share/netwmpager/<br />

config-example editieren, speziell die Zeilen geometry und<br />

auto_hide.<br />

Falls Sie einen Benachrichtungsbereich (System-Tray)<br />

benötigen, ist Stalonetray ein guter Tipp. Es gibt Stalonetray<br />

in den Paket-Archiven von Ubuntu wie auch als Quellcode<br />

unter http://stalonetray.sf.net. Falls Sie selbst kompilieren,<br />

führen Sie dabei die Schritte ./configure, make und<br />

sudo make install aus und starten Sie Stalonetray danach<br />

mit:<br />

stalonetray -geometry 5x1+50+20<br />

<strong>Das</strong> erstellt einen Nachrichtenbereich, der fünf Spalten breit<br />

und eine Zeile hoch ist und dabei von der oberen linken Ecke<br />

des Bildschirms 50 <strong>Pi</strong>xel nach rechts und 20 <strong>Pi</strong>xel nach<br />

unten entfernt liegt. Diese Parameter können Sie natürlich<br />

nach Belieben anpassen.<br />

Kombination der Komponenten<br />

Nun sind wir bereit, alle Komponenten zusammenzufügen,<br />

um daraus eine Desktopumgebung zu basteln. Sie können<br />

jede x-beliebige Kombination der zuvor genannten Programme<br />

verwenden, wir nutzen hier Openbox, Docky, hsetroot,<br />

NetWMPager und Stalonetray. Der erste Schritt ist das<br />

Schreiben eines Scripts, das alle Programme startet. Für unseren<br />

Eigenbau-Desktop legen wir es in den Ordner /usr/<br />

local/bin/mikedesk-start:<br />

#!/bin/bash<br />

docky &<br />

hsetroot -fill /usr/share/backgrounds/space-02.jpg &<br />

netwmpager &<br />

stalonetray -geometry 5x1+0+0 &<br />

openbox<br />

<strong>Das</strong> & hinter dem Befehl bedeutet, dass die Programme im<br />

Hintergrund laufen sollen, sodass sie alle zur selben Zeit laufen<br />

und aufgerufen werden können und nicht darauf warten,<br />

bis das vorhergehende Programm beendet ist. Es ist jedoch<br />

wichtig, dass der Fenstermanager in der letzten Zeile ohne<br />

ein & gestartet wird, weil die Sitzung ansonsten sofort beendet<br />

wird.<br />

Speichern Sie die Datei und machen Sie sie ausführbar<br />

(zum Beispiel mit sudo chmod +x mikedesk-start). Der<br />

nächste Schritt ist das Erzeugen einer Login-Screen-Sitzung.<br />

Legen Sie dazu eine neue Datei à la /usr/share/xsessions/<br />

mikedesk.session mit dem folgenden Inhalt an:<br />

[Desktop Entry]<br />

Name=MikeDesk<br />

Comment=Mike Desktop Environment<br />

Type=XSession<br />

Exec=/usr/local/bin/mikedesk-start<br />

TryExec=mikedesk-start<br />

Speichern Sie wieder, melden Sie sich mit Ihrer aktuellen Sitzung<br />

ab, und es sollte eine neue Starten, dieses Mal aber mit<br />

dem Login-Manager. Wählen Sie den Benutzernamen, loggen<br />

Sie sich ein und genießen Sie die Früchte ihrer Arbeit. Glückwunsch:<br />

Sie sind nun offiziell großartig.<br />

Hier sehen Sie<br />

das Ergebnis unserer<br />

Arbeit: Eine<br />

Desktopumgebung<br />

bestehend<br />

aus den von uns<br />

ausgesuchten<br />

Komponenten.<br />

Hilfe! Meine Gtk- und Qt-Programme sehen blöd aus!<br />

<strong>Das</strong> ist leider ein häufiges Problem<br />

beim Wechsel des Fenstermanagers.<br />

Sie richten alles perfekt ein, suchen<br />

sich einen atemberaubenden Desktop-<br />

Hintergrund aus... aber Ihre Gtk- und<br />

Qt-Anwendungen sehen aus, als entstammten<br />

sie den 1980er Jahren: flache<br />

Menüs, grob gezeichnete Widgets,<br />

dunkelgraue Hintergründe und hässliche<br />

Schriften. Qt und Gtk können nicht mehr<br />

ermitteln, welches Thema sie nutzen<br />

sollen, also verwenden sie die eingebauten<br />

Standardeinstellungen. Falls Sie<br />

Gnome oder Xfce verwenden, können<br />

Gtk-Anwendungen beim Desktop nachfragen,<br />

welches Thema genutzt werden<br />

soll. Mit einem eigenständigen Fenstermanager<br />

sind die Programme auf das<br />

angewiesen, was in ihren Konfigurationsdateien<br />

steht. Für Gtk gibt es einige<br />

Optionen, die sie ausprobieren können.<br />

gtk-chtheme lässt Sie das Thema einstellen,<br />

das von Gtk-2.x-Anwendungen<br />

verwendet werden soll, nicht allerdings<br />

für 3.0. Für Letzteres editieren Sie die<br />

Datei ~/.config/gtk-3.0/settings.ini,<br />

sodass sie den Namen des Themas<br />

angibt:<br />

[Settings]<br />

gtk-theme-name = Clearlooks<br />

gtk-fallback-icon-theme = gnome<br />

Falls keine dieser Vorgehensweise<br />

den erwünschten Effekt hat und Sie<br />

Gnome installiert haben, versuchen<br />

Sie, den Dienst gnome-settingsdaemon<br />

zu starten. Dieser wird die<br />

Gtk-Programme anweisen, Ihr neues<br />

Thema zu verwenden, aber auch Ihren<br />

Desktophintergrund zurücksetzen. Um<br />

Qt-Anwendungen zur Nutzung von Gtk-<br />

Themen zu verwenden, öffnen Sie die<br />

Datei ~/.config/Trolltech.conf und<br />

fügen Folgendes hinzu:<br />

style=GTK+<br />

Alternativ können Sie das Paket qt4-qtconfig installieren<br />

und es mit qtconfig ausführen.<br />

So sieht VirtualBox (eine Qt-Anwendung) mit dem<br />

Standard-Qt-Thema aus: Windows 95 lebt!<br />

85


Coding<br />

86


Coding<br />

Coding<br />

Coding ist das Handwerkszeug eines jeden Linux-<br />

Enthusiasten. Wir erklären Ihnen die<br />

grundlegenden Strukturen der höheren<br />

Programmierkunst und geben Ihnen auch<br />

Hilfestellungen zu Python.<br />

Generation CODE........................................................................................88<br />

<strong>Raspberry</strong> Jams...........................................................................................92<br />

Geany: Editor de luxe...............................................................................96<br />

Code-Konzepte: Datentypen...........................................................100<br />

Designkonzepte: Komplexe Typen.............................................102<br />

Designkonzepte: Abstraktion.........................................................104<br />

Designkonzepte: Dateien und Module...................................106<br />

Python: So fangen Sie an.................................................................108<br />

Designkonzepte: Eine IDE nutzen...............................................112<br />

Designkonzepte: Ein Unix-Tool.......................................................114<br />

Designkonzepte: Ein echter Klon................................................116<br />

Designkonzepte: Klassenobjekte.............................................. 118<br />

Designkonzepte: Module...................................................................120<br />

Designkonzepte: Massenspeicher.............................................122<br />

Designkonzepte: Datenorganisation........................................124<br />

GUI-Code: Mit Clutter hantieren...................................................126<br />

Python: Clutter-Animationen...........................................................130<br />

87


Coding<br />

Generation: CODE<br />

Ein Blick auf einige Initiativen, die der jungen Generation<br />

das Programmieren nahebringen möchten.<br />

Präsentationen erstellt. Doch nun ist die<br />

IT-Ausbildung Chefsache bei den Schulbehörden<br />

und wird zusehends entstaubt.<br />

Beispielsweise hat die britische Regierung<br />

angekündigt, dass ab September 2014 im<br />

Lehrplan anstelle besagter Büroausbildung<br />

wieder ein echter Kurs der Computerwissenschaften<br />

stehen wird.<br />

Dabei wurde schnell erkannt, dass die<br />

Ausrüstung der meisten Schulen nicht mehr<br />

zeitgemäß ist und dass die Lehrer der oberen<br />

Schulklassen oftmals weniger über die Materie<br />

Lehrer, Regierungen und Industrie versuchen<br />

seit geraumer Zeit, den praxisnahen<br />

Umgang mit Computern im<br />

Schulunterricht zu verankern. Die<br />

Anfänge dieses Unterfangens liegen in den<br />

80er-Jahren und konnten bestenfalls diejenigen<br />

begeistern, die später unter dem Begriff<br />

Nerds belacht und anschließend erfolgreiche<br />

Unternehmer wurden. Anschließend<br />

beschränkte sich der Unterricht auf den<br />

Umgang mit Microsoft Office, wie man damit<br />

Briefe schreibt oder PowerPointwissen<br />

als ihre Schüler. Die notwendigen<br />

Investitionen in Technik und Weiterbildung<br />

dürften so manche Schule überfordern.<br />

Erfreulicherweise haben sich im<br />

Vereinigten Königreich längst einige gemeinnützige<br />

Organisationen der Sache angenommen<br />

und bieten – oftmals von Eltern und<br />

Gemeinden unterstützt – ihre Hilfe an.<br />

Beispielsweise rüsten sie die Schulen mit<br />

moderner Technik aus oder bieten kostenlosen<br />

Nachmittagsunterricht in eigenen<br />

Räumen an.<br />

88


Coding<br />

Neben gemeinnützigen Organisationen entstehen derzeit<br />

auch immer neue Webseiten mit dem gleichen Ziel:<br />

Sie wollen Schülern das Programmieren näherbringen. Unter<br />

www.codeavengers.com oder www.codeacademy.com sind<br />

die zwei derzeit erfolgreichsten kostenlosen Unterrichtsseiten<br />

zu erreichen, Letztere übersetzt ihre Kurse momentan<br />

sogar Stück für Stück ins Deutsche. Diese und andere Seiten<br />

helfen Kindern und Erwachsenen dabei, eine Programmiersprache<br />

auf strukturierte, interaktive und kontrollierte Weise<br />

zu erlernen.<br />

Weltweit haben es sich Programmierclubs mittlerweile<br />

zur Aufgabe gemacht, dass der Schulunterricht eine vergleichbare<br />

Qualität bekommt. In diesem Bericht befragen wir<br />

zwei dieser Vereinigungen nach ihrer Herkunft, ihren Zielen<br />

und ihren bisherigen Erfolgen: der ausschließlich aus<br />

Jugendlichen bestehende Club Young Rewired State, der auf<br />

der ganzen Welt Programmierfestivals veranstaltet, und der<br />

von britischen Schulen unterstützte Code Club, der außerhalb<br />

des normalen Unterrichts wöchentliche Seminare<br />

abhält.<br />

Young Rewired State<br />

Young Rewired State, die Jugendorganisation von Rewired<br />

State, ist momentan in Großbritannien, den Vereinigten<br />

Staaten und mittlerweile auch in Deutschland vertreten.<br />

Unter eigener Regie und auch zusammen mit lokalen<br />

Organisationen veranstaltet YRS in diesen Ländern<br />

Clubtreffen und Wettbewerbe, auf denen Kinder und<br />

Jugendliche im Team die Grundlagen des Zeit- und<br />

Projektmanagements erlernen und nebenbei erfahren, was<br />

eine Deadline bedeutet.<br />

Jedem Team ist mindestens ein Mentor zugeordnet, der<br />

als Unterstützer und gegebenenfalls als Leiter die Gruppe<br />

durch die Veranstaltung führt, dem Team aber ansonsten<br />

keine Arbeit abnimmt. Auf den bis zu sieben Tage dauernden<br />

Treffen versammeln sich bis zu 500 Schüler, die auf dem<br />

abschließenden Wettbewerb ihre Projekte einer Jury vorstellen.<br />

Zwar gibt es den Konkurrenzkampf um Finalteilnahme<br />

und Gesamtsieg, im Vordergrund der Veranstaltungen stehen<br />

für die Teilnehmer aber der erlebte Teamgeist und die<br />

Chance, neue Programmiertechniken zu erlernen.<br />

Wir sprachen mit Thom Brooks, PR- und<br />

Kommunikationsspezialist von Young Rewired State.<br />

<strong>PC</strong> <strong>Games</strong> <strong>Hardware</strong>: Hi Thom! Can you tell me what Rewired<br />

State is, and what its goals are?<br />

Thom Brooks: Rewired State und Young Rewired State wurden<br />

beide von Emma MulQueeny gegründet, die auf Twitter unter<br />

@hubmam bekannt ist.<br />

Rewired State veranstaltet<br />

Hack-Events, auf<br />

denen Kreative,<br />

Entwickler und<br />

Industrieexperten<br />

gemeinsam ausgeschriebene<br />

Real-World-<br />

Probleme lösen.<br />

Unsere Kunden sind<br />

Körperschaften des<br />

Öffentlichen Rechts,<br />

Industriegiganten,<br />

YRS veranstaltet das<br />

jährliche Festival of<br />

Code für Jugendliche.<br />

Messen und gemeinnützige Organisationen. Die erste „Hack“<br />

genannte Veranstaltung fand im Jahr 2009 statt und war mit<br />

über 100 Entwicklern die Geburtsstätte für die mittlerweile<br />

legendäre Reihe „National Hack the Government Day“.<br />

Damals wurde der Grundstein für die Website http://data.<br />

gov.uk gelegt und das hat dazu beigetragen, dass sich die<br />

britische Regierung nun offenen Standards verschrieben<br />

hat..<br />

<strong>PC</strong>GH: Was war die Idee für das Projekt Young Rewired<br />

State? Wie lief das Projekt an?<br />

TB: Noch im Jahr 2009 beschlossen wir, unter dem Namen<br />

Young Rewired State eine Veranstaltung speziell für<br />

Jugendliche zu organisieren. In der Londoner Niederlassung<br />

von Google wollten wir ein Wochenende lang über die freie<br />

Verfügbarkeit öffentlicher Regierungsdaten sprechen und<br />

was jugendliche Programmierer mit diesen Daten anfangen<br />

können. Da die Google-Büros nur eine begrenzte Kapazität<br />

haben, erwarteten wir überfüllte Räume … aber es erschienen<br />

gerade einmal<br />

drei Jugendliche.<br />

Anrufe in den<br />

benachbarten<br />

Schulen und eine<br />

kurze Recherche<br />

im Internet offenbarte<br />

uns die<br />

Ursache dieses vermeintlichen<br />

Desinteresses: Es gab im Land einfach nicht<br />

genügend Programmierer. Und die wenigen, die es gab,<br />

haben sich daheim im stillen Kämmerlein das<br />

Programmieren selber beigebracht und sich damit selbst<br />

zum Außenseiter abgestempelt – sogar die meisten Eltern<br />

vermuteten hinter dieser anspruchsvollen Beschäftigung<br />

eine kindliche Entwicklungsstörung. Und an vielen Schulen<br />

war der Programmierunterricht längst abgeschafft.<br />

Daraufhin suchten wir drei Monate lang nach 50 geeigneten<br />

Kandidaten und veranstalteten für diese ein Wochenende.<br />

Mit großer Begeisterung sahen wir, wie sie unter Aufsicht von<br />

Mentoren und Datenexperten in kurzer Zeit Apps und<br />

Webseiten erstellten, die öffentliche Regierungsdaten auswerteten.<br />

Vor unseren Augen hat sich eine längst überfällige<br />

Gemeinschaft gebildet. Junge Genies, die sich nie mehr alleine<br />

fühlen müssen und sich mithilfe von erfahrenen Beratern<br />

zu Programmierern ausbilden.<br />

<strong>PC</strong>GH: Welches Ziel verfolgt Young Rewired State?<br />

TB: <strong>Das</strong> Ziel ist ein weltweites und unabhängiges Netzwerk<br />

Der Höhepunkt<br />

des Festival of<br />

Code ist das<br />

Wochenende<br />

in der Custard<br />

Factory in<br />

Birmingham.<br />

„Wir erwarteten überfüllte<br />

Räume … aber es erschienen<br />

gerade einmal drei<br />

Jugendliche.“<br />

89


Coding<br />

junger Programmierer, die sich gegenseitig unterrichten und<br />

bei der Lösung ausgeschriebener Aufgaben unterstützen.<br />

<strong>PC</strong>GH: Wie hat sich Young Rewired State in den vergangenen<br />

Jahren weiterentwickelt?<br />

TB: Im Jahr 2009 fingen wir mit 50 Jugendlichen an, mittlerweile<br />

besteht die Gemeinschaft aus über 1.000 Jugendlichen.<br />

Seit 2013 sind wir auch in anderen Ländern aktiv. Unsere erste<br />

internationale Veranstaltung war das „Everywhere“-Event<br />

in New York, im September waren wir in Berlin und dann in<br />

Johannesburg und San Francisco. In all diesen Gegenden<br />

verfolgen wir den gleichen Plan wie damals in England: Wir<br />

fangen mit 50 Jugendlichen an und wachsen dann. Bisher<br />

haben wir diese 50 immer erfreulich schnell gefunden.<br />

Auf dem jährlichen Festival of Code in Birmingham trafen<br />

sich letzten August über 500 Leute, die an insgesamt 125<br />

Projekten arbeiteten. Im Jahr zuvor waren es nur 100.<br />

Für die Musik<br />

auf dem Festival<br />

of Code war<br />

unter anderem<br />

Theremin Hero an<br />

der Laser-Harfe<br />

zuständig<br />

<strong>PC</strong>GH: Wie läuft die Gründung dieser lokalen Zentren ab?<br />

TB: Die Community steht immer an erster Stelle. Es ist die<br />

Gemeinschaft aus jugendlichen Programmierern und<br />

Mentoren, die aus Young Rewired State etwas Besonderes<br />

macht. Also wollen wir die Leute an einem Ort versammeln<br />

– Young Rewired State stellt dabei nur eine Vorlage für die<br />

Organisation eines Wochenendes zur Verfügung, die<br />

Gemeinden setzen sie dann um. Lokale Firmen,<br />

Medienzentren, Schulen und andere Einrichtungen stellen<br />

dafür ihre Räume zur Verfügung und nur bei Bedarf senden<br />

wir unsere Mentoren für Rat und Tat vor Ort.<br />

Der Erfolg nährt sich selbst: Im Jahr 2013 hatten wir alleine in<br />

Großbritannien 40 aktive Zentren und 160 Mentoren, die wiederum<br />

die Organisation und Unterstützung weiterer Zentren<br />

übernehmen. Es hat sich längst herumgesprochen, dass<br />

Programmierer dringend gebraucht werden, und die<br />

Arbeitgeber fragen sich mittlerweile, wie man deren<br />

Ausbildung unterstützen kann.<br />

Da bieten sich die Unterstützung<br />

der Zentren und die<br />

Veranstaltung der Events natürlich<br />

an.<br />

Botschafter der Mathematik<br />

<strong>PC</strong>GH: Young Rewired State hat<br />

schon viel erreicht. Welches<br />

war das wichtigste Erlebnis<br />

auf diesem Weg?<br />

TB: Nur eins? Für mich ist das<br />

aufregendste Erlebnis die<br />

Erkenntnis, dass es funktioniert.<br />

Hinter den Kulissen<br />

arbeitet ein kleines Team, das<br />

Clare Sutcliffe, Mitbegründerin von Code Club: „Wir<br />

haben mittlerweile über 1000 Clubs.“<br />

mit einem Twitter-Hype den Grundstein gelegt hat, aber mittlerweile<br />

wächst YRS ganz von alleine. Für die Teilnehmer sollte<br />

das größte Erlebnis der Sonntagabend sein, wenn sie auf<br />

die letzten Tage zurückblicken und sich sagen „Ich war Teil<br />

von etwas ganz Besonderem.“<br />

<strong>PC</strong>GH: Welches sind die Ziele für die nächsten zwölf<br />

Monate?<br />

TB: Nach dem letztjährigen Erfolg wiederholen wir<br />

„Everywhere“ in New York im Jahr 2014. Wir wollen dort fünf<br />

Zentren aufbauen. Außerdem werden wir die Community<br />

weiter vergrößern, die Gemeinschaftsidee propagieren und<br />

auf die Bedeutung öffentlicher Daten hinweisen. Und bei all<br />

dem wollen wir Spaß haben. Wenn die Leser uns dabei unterstützen<br />

möchten: Auf unserer Website<br />

https://youngrewiredstate.org kann man alles über<br />

Zentren und Gruppen erfahren. .<br />

Code Club<br />

Nicht weniger einflussreich als YRS, aber mit einem völlig<br />

anderen Ansatz angetreten, ist Code Club. Der Club veranstaltet<br />

wöchentliche Treffen, auf denen die Kinder und<br />

Jugendlichen nach einem echten Lehrplan das<br />

Programmieren lernen. Dieser Lehrplan wird von Code Club<br />

und von freiwilligen Helfern ausgearbeitet und beinhaltet die<br />

Grundlagen der Programmierung, Scratch, moderne Web-<br />

Technologien und jedes andere Wissen, welches die Helfer<br />

im Klassenzimmer vermitteln wollen.<br />

Wir sprachen mit Clare Sutcliffe, die im April 2012 zusammen<br />

mit Linda Sandvik den Code Club gründete. Clare<br />

erzählte uns mehr über das Projekt und wie Interessenten<br />

der Initiative beitreten können.<br />

Um Naturwissenschaften eine<br />

größere Präsenz an britischen<br />

Schulen zu verschaffen, wurde 1996<br />

STEMNET gegründet. Die Non-Profit-<br />

Organisation finanziert sich aus<br />

Regierungsgeldern und unterstützt<br />

Lehrer, Schüler und<br />

Ausbildungsbetriebe bei der<br />

außerschulischen Beschäftigung mit<br />

diesen Themen. Die sogenannten<br />

Ambassadors (Botschafter)<br />

betätigen sich dabei als Ratgeber<br />

oder als Lehrer und werden laufend<br />

von STEMNET überwacht und auch<br />

weitergebildet. Meist handelt es sich<br />

bei den Helfern um aktive<br />

Wissenschaftler, die ihre Freizeit dem<br />

Gemeinwohl widmen möchten.<br />

Weitere Details finden Sie auf der<br />

Webseite www.stemnet.org.uk.<br />

<strong>PC</strong> <strong>Games</strong> <strong>Hardware</strong>: Hallo Clare! Wer oder was ist Code<br />

Club?<br />

Clare Sutcliffe: Code Club wurde von Linda Sandvik, einer<br />

Schnittstellen-Designerin, und mir, einer Grafik-Designerin<br />

gegründet. Die treibende Kraft im Code Club sind aber all die<br />

Freiwilligen, die für das Projekt ihre Zeit opfern<br />

<strong>PC</strong>GH: Was hat euch dazu bewogen, den Code Club zu<br />

gründen?<br />

CS: Linda und ich saßen in einer Kneipe und stellten nach ein<br />

paar Drinks fest, dass es an den Schulen keinen<br />

90


Coding<br />

Programmierunterricht mehr gibt. Also hatten wir die Idee<br />

eines Hack Days, auf dem Kinder im Programmieren unterrichtet<br />

werden. Nach dem nächsten Drink stand fest, dass<br />

dies keine einmalige Veranstaltung sein darf, sondern ein<br />

Club mit fortlaufenden Terminen. Wir hatten Glück, dass viele<br />

unserer Freunde Programmierer sind und sich sofort<br />

bereit erklärt hatten, uns bei dieser Idee zu helfen. Wir haben<br />

den Code Club im Jahr 2012 gegründet und seitdem über<br />

1.000 Clubs bei deren Gründung begleitet.<br />

<strong>PC</strong>GH: Wer sind die freiwilligen Helfer?<br />

Welche Anforderengen müssen sie erfüllen?<br />

CS: <strong>Das</strong> ist ein bunter Querschnitt der Bevölkerung. Die größte<br />

Gruppe sind die Lehrer derjenigen Schulen, in denen die<br />

Clubs sich treffen. Der Rest sind Freiberufler, Eltern und<br />

Programmierer im Ruhestand. Wer im Code Club unterrichten<br />

möchte, der braucht ein polizeiliches Führungszeugnis.<br />

Außerdem empfehlen wir allen Freiwilligen, sich als Science,<br />

Technology, Engineering and Mathematics (STEM)<br />

Ambassador zu registrieren. Diese Botschafter arbeiten mit<br />

Schulen bei allen naturwissenschaftlichen Fragen zusammen<br />

und unterstützen die Lehrer bei ihrer Arbeit. Für die meisten<br />

Botschafter ist diese Aufgabe einfach eine gut organisierte<br />

Möglichkeit, der Gesellschaft etwas zurückzugeben.<br />

LXF: Wie sieht ein typischer Tag im Code Club aus?<br />

CS: Ein Code Club trifft sich einmal pro Woche für eine<br />

Stunde. Der Unterricht ist in Semester aufgeteilt, die jeweils<br />

ein bestimmtes Ziel verfolgen. In Semester 1 lernen wir<br />

Scratch. In Semester 2 lernen wir die tiefsten Tiefen von<br />

Scratch und gehen dabei wirklich bis an die Leistungsgrenze<br />

von Schülern und Lehrern. In Semester 3 behandeln wir<br />

HTML und CSS, außerdem erklären wir die Funktionsweise<br />

des Internets. In Semester 4 lernen wir dann Python. Mehr<br />

Details sowie Unterrichtsmaterial zu den einzelnen<br />

Abschnitten gibt es auf www.codeclub.org.uk/start-a-club/<br />

volunteers unter „Term Outlines“.<br />

Wir verlangen von unseren Lehrern, dass sie mit dem<br />

Programmcode, den Beispielen, dem Unterrichtsmaterial,<br />

den Handzetteln und dem Ziel einer Unterrichtsstunde bestens<br />

vertraut sind. Jedes Code-Club-Projekt wurde mit einem<br />

bestimmten Ziel entworfen und kann problemlos innerhalb<br />

einer Stunde behandelt werden. Da aber jeder Club anders<br />

ist, kann und soll die Unterrichtsstruktur von den Helfern entsprechend<br />

angepasst werden.<br />

<strong>PC</strong>GH: Was ist der bisher größte Erfolg?<br />

CS: Für mich ist unser Wachstum der vergangenen zwölf<br />

Monate der größte Erfolg: Dank unseres großen Netzwerks<br />

von Freiwilligen haben wir über 1.000 Clubs und es werden<br />

immer mehr.<br />

Hilfsmittel für den Unterricht<br />

Scratch Die derzeit wichtigste<br />

Programmiersprache für Kinder ab 6<br />

Jahren. Sie verwendet Befehls-<br />

Bausteine, die visuell zu Programmen<br />

zusammengesetzt werden.<br />

http://scratch.mit.edu<br />

Hackasaurus Eines von vielen<br />

Einsteiger-Tools für JavaScript.<br />

Hackasaurus nistet sich in Browser-<br />

Bookmarks ein und ermöglicht die<br />

lokale Bearbeitung fremder Websites.<br />

Man besucht eine beliebige Webseite,<br />

klickt auf das Bookmark und kann<br />

sofort mit dem Programmieren<br />

starten.<br />

http://hackasaurus.org/en-US<br />

<strong>PC</strong>GH: Wie kann ein Lehrer oder ein freiwilliger<br />

Helfer einen Code Club gründen?<br />

CS: Ein Schullehrer muss nur unsere<br />

Webseite besuchen und seine Schule eintragen<br />

– natürlich sollte er dies mit seinem<br />

Chef und der Schulbehörde besprechen.<br />

Freiwillige Helfer müssen sich zuerst mit<br />

dem Rektor der jeweiligen Schule absprechen.<br />

Die Schule registriert sich dann auf<br />

unserer Webseite. Anschließend organisieren<br />

beide gemeinsam die Räume für den<br />

Unterricht.<br />

Die Zukunft<br />

Großbritannien hat gezeigt, dass es die aktuellen<br />

Herausforderungen<br />

erkannt hat, und<br />

Code Academy Ein kostenloses,<br />

webbasiertes Unterrichtssystem mit<br />

Kursen für JavaScript, PHP, Python<br />

und Ruby. Die Kurse sind kurz und<br />

praxisnah.<br />

www.codecademy.com/learn<br />

Blender<br />

Als Profiwerkzeug und<br />

Unterrichtsmittel in einem bringt<br />

Blender Kindern und Erwachsenen<br />

Mathematik, Physik und Spieldesign<br />

näher. Da Blender auch einen Python-<br />

Interpreter enthält, kann man<br />

gleichzeitig das Programmieren<br />

lernen.<br />

www.blender.org<br />

„Wer unterrichten möchte,<br />

braucht ein Führungszeugnis.“<br />

scheint bereit, diese<br />

anzugehen. Aber<br />

ebenso wie in<br />

Deutschland, wo<br />

der Schulunterricht Sache der einzelnen Länder ist, werden<br />

nicht Gesetze und Lehrpläne, sondern die Finanzen der einzelnen<br />

Schulen darüber entscheiden, ob ein zeitgemäßer<br />

IT-Unterricht möglich sein wird.<br />

Umso wichtiger sind die privaten Initiativen von Lehrern,<br />

Eltern und anderen Freiwilligen, den Nachwuchs in diesem<br />

Bereich zu unterstützen. Wenn dabei Großunternehmen mit<br />

Sachspenden und Expertenwissen ihre Hilfe<br />

anbieten, dann ist dies nicht unbedingt eine<br />

böswillige Werbemaßnahme: Schließlich sind es<br />

genau diese Unternehmen, die derzeit unter<br />

dem von unserem Bildungswesen verursachten<br />

Fachkräftemangel leiden und nun auch unkonventionelle<br />

Maßnahmen ergreifen, um in<br />

zukünftige Arbeitneh mer zu investieren.<br />

91


Coding<br />

<strong>Raspberry</strong> Jams<br />

Ein Erfolgsrezept<br />

<strong>Das</strong> weltweite Netzwerk von R<strong>Pi</strong>-Treffen wächst stetig.<br />

Es bringt Fans aller Altersgruppen zusammen.<br />

Seit Anfang 2012 ist der <strong>Raspberry</strong><br />

<strong>Pi</strong> auf dem Markt. Bei<br />

seiner Einführung wurde er<br />

enthusiastisch begrüßt. Doch<br />

nach dem ersten Ansturm stellte sich die<br />

Frage, wie man denn nun das Potenzial<br />

des Rechners voll ausschöpfen könne.<br />

In den letzten Jahren fanden deshalb in<br />

Großbritannien mehrere Treffen rund um<br />

den <strong>Raspberry</strong> <strong>Pi</strong> statt, die sogenannten<br />

<strong>Raspberry</strong> Jams. <strong>Das</strong> Konzept wurde von<br />

dem IT-Lehrer Alan O’Donohoe entwickelt.<br />

Er setzt sich schon lange für die<br />

Verbesserung des Computerunterrichts an<br />

Schulen ein und hält Vorträge zu dem Thema.<br />

Durch seinen unermüdlichen Einsatz ist er fast<br />

„Nach dem ersten Ansturm<br />

stellte sich die Frage, wie man<br />

das Potenzial des Rechners<br />

ausschöpfen könne.“<br />

so etwas wie ein Botschafter für die Jams geworden,<br />

ein Jambassador. Er steht in Kontakt<br />

mit Gruppen auf der ganzen Welt, um<br />

bessere Computerlehrgänge für Kinder zu<br />

entwickeln. Alan arbeitet eng mit der <strong>Raspberry</strong><br />

<strong>Pi</strong> Foundation, Mozilla<br />

und Google zusammen, mit<br />

dem Ziel, dass Kinder und<br />

Erwachsene mehr über<br />

Computer lernen können.<br />

Wir haben Alan und einige<br />

Jam-Organisatoren interviewt,<br />

weil wir mehr über das<br />

weltweite Netzwerk der <strong>Raspberry</strong> Jams erfahren<br />

wollten.<br />

92


Coding<br />

Frage: Würden Sie uns ein bisschen über sich erzählen –<br />

für die Leser, die Sie noch nicht kennen?<br />

Alan O’Donohoe: Ich bin der Fachbereichsleiter für Informations-<br />

und Kommunikationstechnologie an der Our Lady’s<br />

High School in Preston im Nordosten Englands. Dort unterrichte<br />

ich seit zwanzig Jahren. Als Kind ist meine Familie von<br />

Irland nach England gezogen, und als ich elf war, habe ich<br />

meinen ersten Computer gesehen, einen BBC Micro.<br />

Während meiner Schulzeit wussten die Lehrer nicht viel über<br />

Computer. Als ich fragte, ob ich einen benutzen dürfte, wurde<br />

mir gesagt, ich solle in der Pause wiederkommen, weil nur sehr<br />

wenige Computer zur Verfügung standen. Mithilfe von Büchern<br />

und Zeitschriften habe ich mir selbst das Programmieren<br />

in BBC Basic beigebracht. Mir gefiel daran, dass ich einen<br />

Computer dazu bringen konnte, das zu tun, was ich wollte.<br />

Frage: Wie sind Sie auf die Idee mit den Jams<br />

gekommen?<br />

AO: Vor ein paar Jahren ist mir klar geworden, dass wir den<br />

Computerunterricht an den Schulen ändern müssen. Ich wollte<br />

die Informatik ins Klassenzimmer bringen. Weil ich selbst<br />

keine Informatik studiert hatte, habe ich mich erst mal in das<br />

Thema eingelesen und mich nach Ressourcen und Hilfsmitteln<br />

umgeschaut. Eines der Probleme war, dass ich wegen<br />

der starken Nutzungsbeschränkungen die nötige Software<br />

nicht auf den Schulrechnern installieren konnte. Zur selben<br />

Zeit hörte ich von diesem neuen Computer, diesem <strong>Raspberry</strong><br />

<strong>Pi</strong>. Mir wurde klar, dass ich mit dem <strong>Pi</strong> meinen Schülern<br />

Programmieren beibringen konnte, weil die Nutzung nicht so<br />

restriktiv war wie bei den Systemen, die wir in der Schule<br />

benutzten.<br />

Also startete ich an meiner Schule einen Programmier-Dojo.<br />

So ein Dojo ähnelt einer Karate-Schule, die Schüler lernen Programmieren<br />

mit kleinen Übungen, so wie Karateschüler mit<br />

Katas Karate lernen. Die Übungen heißen auch Programmier-<br />

Katas. Aus dem Dojo entwickelte sich eine viel größere Veranstaltung,<br />

„Hack to the Future“, eine Unkonferenz für Kinder. Bei<br />

dieser Veranstaltung saßen Macher, Hacker und Leute aus der<br />

IT-Industrie mit den Kindern zusammen, die dabei sehr viel<br />

übers Programmieren lernten. Und ich lernte bei „Hack to the<br />

Future“ einiges über die Organisation solcher Events.<br />

An dem Tag, als der <strong>Raspberry</strong> <strong>Pi</strong> auf den Markt kam,<br />

stand ich, wie viele Leute, schon früh auf, um sofort meinen<br />

<strong>Pi</strong> zu bestellen. Wegen der riesigen Nachfrage bekam ich<br />

aber keinen. Aber, so dachte ich, wenn ich schon keinen <strong>Pi</strong><br />

bekommen hatte, dann würde ich sicher Leute treffen, die<br />

einen hatten. Aber ich fand niemanden, der einen <strong>Pi</strong> besaß.<br />

Da kam ich auf die Idee eines Treffens, auf dem sich Leute<br />

gegenseitig zeigten, was sie mit ihren <strong>Raspberry</strong> <strong>Pi</strong>s alles<br />

anstellten.<br />

Mehr Jams, überall<br />

Jeder, der möchte, kann sein eigenes <strong>Raspberry</strong> Jam<br />

veranstalten. Es gibt keine vorgeschriebene Struktur<br />

– Sie können einfach das Format ausprobieren, das<br />

Ihnen am sinnvollsten erscheint. In Manchester zum<br />

Beispiel findet jeden Monat ein <strong>Raspberry</strong> Jam statt,<br />

das sehr informell abläuft: der Raum und WLAN<br />

werden gestellt, aber die Ideen kommen von den<br />

Teilnehmern selbst. Für die Veranstalter funktioniert<br />

das sehr gut, die Gruppe ist sehr aktiv. <strong>Das</strong> Preston<br />

<strong>Raspberry</strong> Jam hingegen hat ein konventionelleres<br />

Lehrformat, mit Vorträgen und Präsentationen.<br />

Ein Jam initiieren Sie, indem Sie erst einmal<br />

Ich war überzeugt, dass es zwei Arten von <strong>Pi</strong>-Besitzern gab<br />

– solche, die tolle Projekte damit machten, und solche, die<br />

ein bisschen herumprogrammierten und den <strong>Pi</strong> dann wieder<br />

weglegten. Diese Leute wollte ich zusammenbringen. Mein<br />

Event brauchte einen Namen, und meine Frau schlug <strong>Raspberry</strong><br />

Jam vor, wobei wir das Wort „Jam“ in dem Sinn benutzten<br />

wie Musiker: ein Treffen, bei dem eine lose Gruppe<br />

zusammen spielt.<br />

<strong>Das</strong> erste <strong>Raspberry</strong> Jam fand in Räumlichkeiten meiner<br />

Schule statt. Eine halbe Stunde, nachdem ich den Termin auf<br />

Twitter gepostet hatte, waren alle 30 verfügbaren Plätze<br />

vergeben. Als der Tag der Veranstaltung näherkam, erhielt<br />

ich eine Anfrage aus Australien von einer Gruppe, die ein<br />

<strong>Raspberry</strong> Jam in Melbourne veranstalten wollte. Ein paar<br />

Tage später fragte Ben Nuttall, ob er ein Jam in Manchester<br />

durchführen könne. Ich sagte natürlich Ja.<br />

Frage: Welche Art von Unterstützung war wichtig für<br />

Sie?<br />

AO: Am Anfang hat mir Martin Bateman von der University of<br />

Central Lancashire (UCLAN) sehr weitergeholfen. Er bot mir<br />

einen größeren Raum an, in dem ich das Preston <strong>Raspberry</strong><br />

Jam abhalten konnte. Ich nahm sein Angebot begeistert an,<br />

und beim nächsten Jam hatten wir 80 Tickets, die ebenfalls<br />

sehr schnell ausverkauft waren. Mir wurde klar, dass die<br />

Leute selbst für die Ausstattung sorgen mussten, damit die<br />

Jams funktionierten. Also bat ich die Teilnehmer, ihre Projekte<br />

mitzubringen und dazu überzählige Tastaturen, Bildschirme<br />

und so weiter.<br />

testen, ob in Ihrer Gegend überhaupt Interesse an<br />

so einer Veranstaltung besteht. Fragen Sie einfach<br />

Ihre Freunde, Kollegen und Familienmitglieder, ob<br />

sie Lust hätten, an einem Jam teilzunehmen.<br />

Als Nächstes brauchen Sie einen geeigneten Veranstaltungsort.<br />

Der Ort sollte barrierefrei sein und,<br />

wenn möglich, einen Internetzugang haben – vielleicht<br />

stellt Ihnen eine Schule, ein Jugend- oder ein<br />

Gemeindezentrum Räumlichkeiten zur Verfügung.<br />

Machen Sie Ihr Event publik, posten Sie<br />

auf Social-Media-Plattformen, versenden Sie<br />

E-Mails und erstellen Sie, falls möglich, eine<br />

Bilder vom<br />

<strong>Raspberry</strong> Jam in<br />

Manchester.<br />

Website. Auf http://raspberryjam.org gibt es<br />

eine Registrierungsseite, auf der Sie der Welt<br />

mitteilen können, dass Ihr Jam stattfindet.<br />

Fragen Sie zu Beginn des Events die Teilnehmer,<br />

was sie tun möchten. Bringen Sie Leute, die Fragen<br />

haben, mit Leuten, die diesen weiterhelfen,<br />

zusammen. Als Einstieg eignen sich Scratch,<br />

eine visuelle Programmier-Software für Kinder,<br />

oder Infos über die GPIO-Schnittstellen. Jams<br />

sind Orte zum Lernen und zum Austausch,<br />

und einige spannende <strong>Raspberry</strong>-<strong>Pi</strong>-Projekte<br />

sind bereits aus Jams hervorgegangen.<br />

93


Coding<br />

Eindrücke vom<br />

sehr beliebten<br />

<strong>Raspberry</strong> Jam in<br />

Cambridge.<br />

Es ist toll, wenn man endlich die nötigen Mittel hat, um ein<br />

Jam zu organisieren. Aber die Interaktion innerhalb einer<br />

Gruppe zu fördern und dabei zu helfen, dass Ideen Gestalt<br />

annehmen – das ist noch viel besser. Allein für diese persönlichen<br />

Begegnungen lohnt sich die Organisation der Jams.<br />

Frage: Was hält die <strong>Raspberry</strong> <strong>Pi</strong> Foundation von dem<br />

Jam-Phänomen?<br />

AO: Die Leute dort unterstützen mich und meine Anliegen<br />

voll, und so wie ich das sehe, profitieren alle von den Jams:<br />

Sie tragen dazu bei, das Ziel der Foundation zu fördern, nämlich,<br />

dass Kinder auf der ganzen Welt mit geringen Mitteln<br />

programmieren lernen können.<br />

Frage: Wie sehen Sie die zukünftige Rolle der Jams?<br />

AO: Ich fände es gut, wenn mehr <strong>Raspberry</strong> Jams in den<br />

Ferien oder an Wochenenden stattfänden. Dann könnten<br />

mehr Kinder an den Events teilnehmen. Ich wünsche mir,<br />

dass Leute, die normalerweise nicht zu einer Computerveranstaltung<br />

gehen, mitkommen und es ausprobieren. <strong>Das</strong>s in<br />

der ganzen Welt mehr Jams stattfinden, auch in ländlichen<br />

Gegenden. Wenn es bei Ihnen noch kein Jam gibt, dann starten<br />

Sie eins! Jeder kann ein Jam organisieren, sogar Kinder,<br />

wobei die aber ihre Eltern oder einen Lehrer um Unterstützung<br />

bitten sollten, damit alles problemlos abläuft. Die Jams<br />

können jedes mögliche Format haben – von der kleinen<br />

Hacker-Runde bis zu einer großen Konferenz.<br />

Jedes Jam ist anders<br />

Wir haben an einigen Jams in Großbritannien teilgenommen,<br />

und zwar in Cambridge, Manchester und York. Alle<br />

sind sehr unterschiedlich abgelaufen. <strong>Das</strong> Cambridge<br />

Jam im Juli 2012 war eine sehr formelle Veranstaltung.<br />

Es fand in einem Hörsaal statt, und Leute von der <strong>Raspberry</strong><br />

<strong>Pi</strong> Foundation hielten Vorträge. Die Veranstalter<br />

der drei populärsten Jams haben wir interviewt: Michael<br />

Horne aus Cambridge, Ben Nuttall aus Manchester und<br />

Jack Wearden vom Birmingham <strong>Raspberry</strong> Jam.<br />

Frage: Wer kommt zu Ihrem <strong>Raspberry</strong> Jam?<br />

Ben Nuttall: Eine ganze Bandbreite von Leuten nehmen an<br />

den Jams teil, Eltern, Kinder, Lehrer, Hobbyelektroniker mittleren<br />

Alters und Technikfreaks zwischen 20 und 40. Manche<br />

Leute bringen ihre Kinder mit, damit diese etwas über Computer<br />

erfahren, weil ihnen das, was sie darüber in der Schule<br />

lernen, nichts bringt. Und die Kinder kommen dann oft wieder<br />

mit Freunden oder dem Rest der Familie.<br />

Jack Wearden: Bei uns waren schon alle möglichen Leute,<br />

von Eltern und Kindern bis zu Linux-Profis und einmal sogar<br />

ein Herzchirurg.<br />

Michael Horne: Bei dem letzten Jam haben vor allem<br />

Erwachsene teilgenommen, aber altersmäßig war das sehr<br />

gemischt, von Studenten bis zu älteren Leuten, die sich hobbymäßig<br />

für Computer interessieren.<br />

Frage: Was waren Ihre Beweggründe, Ihr erstes Jam zu<br />

veranstalten?<br />

BN: Ich habe mir sofort einen <strong>Raspberry</strong> <strong>Pi</strong> bestellt, gleich<br />

morgens an dem Tag, als er offiziell auf den Markt kam. Und<br />

ich habe bei MadLab angefragt, ob es eine Gruppe für <strong>Raspberry</strong>-<strong>Pi</strong>-User<br />

gebe. Dort hat man mir vorgeschlagen, doch<br />

selber eine zu gründen – und das habe ich gemacht. <strong>Das</strong><br />

erste Jam war eigentlich als einmaliges Event geplant, aber<br />

die Leute wollten weitermachen, und da habe ich noch ein<br />

Jam organisiert. Die Treffen kamen gut an, also erklärte ich<br />

mich bereit, weiter welche zu organisieren, solange genug<br />

Leute kommen. Bis jetzt hat das Interesse nicht<br />

nachgelassen.<br />

JW: Ich wollte vor allem das Gemeinschaftsgefühl der <strong>Raspberry</strong>-<strong>Pi</strong>-User<br />

in ein akademisches Umfeld holen. Und den<br />

jüngeren Teilnehmern sollte das Jam Einblicke in das Programmieren<br />

auf Uni-Niveau geben.<br />

MH: Ich war beim Milton Keynes Jam dabei und wollte unbedingt<br />

eines näher an meinem Wohnort organisieren. Cambridge<br />

war der logische Ort dafür, weil dort der <strong>Pi</strong> ja sozusagen<br />

auf die Welt gekommen ist.<br />

Frage: Wie häufig treffen Sie sich?<br />

BN: Wir treffen uns monatlich, gewöhnlich an einem Samstag.<br />

Der genaue Termin hängt davon ab, ob die Räume im<br />

MadLab verfügbar sind, vor allem seit wir wegen der großen<br />

Ressourcen für Ihr <strong>Raspberry</strong> Jam<br />

Es gibt eine ganze Menge Ressourcen, die Sie<br />

bei der Organisation eines Jams nutzen können.<br />

Allerdings sollte sich das Format der Veranstaltung<br />

nach den Bedürfnissen der Teilnehmer<br />

richten, und richtig sinnvoll ist ein Jam nur dann,<br />

wenn die Leute ihre Kenntnisse untereinander<br />

austauschen können. Hier eine Auswahl relevanter<br />

Websites:<br />

http://raspberryjam.org Hier können Sie Ihr<br />

<strong>Raspberry</strong> Jam registrieren, Ihre eigene Webseite<br />

für das Jam erstellen, und Sie er halten News von<br />

anderen Gruppen weltweit.<br />

http://www.raspberrypi.org/forums Interessant<br />

für Sie sind die Bereiche User Groups und<br />

Events. Hier finden Sie jede Menge Infos über<br />

Events auf der ganzen Welt, mit vielen Kommentaren<br />

und Ideen.<br />

http://learn.adafruit.com Eine großartige<br />

Seite übers <strong>Hardware</strong>-Hacken, mit Arduinound<br />

<strong>Raspberry</strong>-<strong>Pi</strong>-Projekten und Übungen zu<br />

Elektronik-Grundkenntnissen.<br />

http://codecademy.com/tracks/python<br />

Auf dieser Seite finden Sie einige sehr gute<br />

Python-Übungen, mit denen aus einer Gruppe<br />

von Anfängern Experten werden können.<br />

http://scratch.mit.edu Scratch ist ein<br />

geniales Programm zur Einführung ins Programmieren<br />

für Anfänger und Kinder.<br />

http://raspberrycenter.de Eine deutschsprachige<br />

Seite für <strong>Pi</strong>-Fans.<br />

94


Coding<br />

Nachfrage beide Stockwerke belegen!<br />

JW: Wir haben uns einmal getroffen, und ein zweites Jam ist<br />

geplant – die zeitliche Organisation um die Uni-Veranstaltungen<br />

herum ist nicht ganz einfach. Aber wir hoffen, dass wir<br />

Anfang des nächsten Semesters wieder ein Jam abhalten<br />

können.<br />

MH: <strong>Das</strong> Jam im Mai 2013 war das erste, das ich organisiert<br />

habe und das erste in Cambridge nach über einem Jahr. Wir<br />

haben uns noch nicht für einen festen Veranstaltungsort entschieden.<br />

Ich hoffe, wir können die Jams immer auf Samstagnachmittage<br />

legen, denn für die meisten Leute und vor<br />

allem für Familien ist das die beste Zeit.<br />

Vortrag über die Portierung von KI-Software für den <strong>Raspberry</strong><br />

<strong>Pi</strong>. Es ging darum, wie Software, die Künstliche Intelligenz<br />

nutzt, auf verschiedenen Plattformen funktioniert –<br />

oder auch nicht funktioniert.<br />

MH: Mein erstes Projekt war der Versuch, einen Tricorder<br />

(ein Gerät aus Star Trek) zu bauen. Im Grunde besteht er aus<br />

ein paar Sensoren, die der <strong>Pi</strong> und ein Arduino auslesen, und<br />

das Ergebnis wird in einem zweizeiligen LCD-Display angezeigt.<br />

Die zweite Version ist eine Weiterentwicklung ohne<br />

den Arduino, ein reiner <strong>Pi</strong>corder. Und mein zweites Projekt ist<br />

ein Schwenk- und Neigemechanismus für die offizielle Kameraplatine,<br />

der über ein Browser-Interface gesteuert wird.<br />

<strong>Das</strong> <strong>Raspberry</strong><br />

Jamboree ist<br />

ein großes,<br />

jährlich stattfindendes<br />

Event,<br />

auf dem es um<br />

den Einsatz des<br />

<strong>Raspberry</strong> <strong>Pi</strong> im<br />

Schulunterricht<br />

geht.<br />

Frage: Welches Format hat Ihr Jam?<br />

BN: <strong>Das</strong> ist in der Regel nicht vorgegeben, aber meistens<br />

wollen die Leute hacken, weshalb wir auf dem Jam dann<br />

genau das tun. Ein paar Neueinsteiger tauchen immer auf,<br />

und da ist es wichtig, dass alle mit einbezogen werden. Es<br />

finden immer irgendwelche Projekte statt, und Neuankömmlinge<br />

können auch in ein Projekt einsteigen, an dem<br />

eine Gruppe bereits arbeitet. Bei unserem großen Jubiläums-<br />

Jam habe ich für die beiden Tage Vorträge und Vorführungen<br />

organisiert, die im oberen Stockwerk standfanden – Scratchund<br />

Python-Workshops, Robotik-Sessions, Kameramodul-<br />

Einführungen sowie kurze Vorträge über Raspbian, Wetterstationen<br />

und eine Einführung in Linux.<br />

JW: Wir stellen zwei Räume zur Verfügung, einen Raum fürs<br />

<strong>Hardware</strong>-Hacken und einen für Vorträge. Nach einem Einführungsvortrag<br />

können die Teilnehmer entweder hacken,<br />

oder sie stellen ihre <strong>Raspberry</strong>-<strong>Pi</strong>-Projekte in Referaten und<br />

Vorführungen vor.<br />

MH: Unser letztes Jam war in vier Sitzungen aufgeteilt. Zwei<br />

Sitzungen waren Vorträge und Vorführungen vorbehalten,<br />

die beiden anderen lockeren Präsentationen, bei denen sich<br />

die Teilnehmer kennenlernen und ihre mitgebrachten Projekte<br />

zeigen konnten.<br />

Frage: Welche Projekte haben Sie oder Ihr Jam<br />

entwickelt?<br />

BN: Zuerst habe ich meinen <strong>Raspberry</strong> <strong>Pi</strong> nur als Medienzentrum<br />

verwendet und um Python zu unterrichten, aber vor<br />

Kurzem habe ich eine Wetterstation für die BBC gebaut. Ein<br />

bisschen experimentiere ich mit dem Kameramodul herum,<br />

und ich erkläre den Kids mit dem <strong>Pi</strong>, wie Webserver funktionieren.<br />

Bei mir auf der Arbeit haben wir einen <strong>Raspberry</strong> <strong>Pi</strong> als<br />

Fileserver und als gemeinsam genutzten Datenbankserver.<br />

Als eines meiner nächsten Projekte will ich mir auf dem <strong>Pi</strong><br />

eine Offline-Bitcoin-Wallet einrichten. Und ich möchte in<br />

Zukunft mehr mit GPIO machen.<br />

JW: Ein Informatik-Professor hielt bei uns einen spannenden<br />

„Ich bin wahnsinnig gerne<br />

auf einem Jam. Da herrscht<br />

eine tolle Atmosphäre.“<br />

Frage: Was würde Sie gerne auf den nächsten Jams<br />

machen?<br />

BN: <strong>Das</strong>, was wir jetzt machen! Ich bin wahnsinnig gerne auf<br />

einem Jam. Da herrscht eine tolle Atmosphäre, die Leute<br />

haben Spaß, egal wie alt sie sind oder wie viel Erfahrung sie<br />

mit dem <strong>Pi</strong> haben. Auf den ersten Events war es schwierig,<br />

Vorträge zu organisieren, weil alles noch so neu war, für alle.<br />

Aber jetzt gibt es so viele Projekte, die man vorstellen kann.<br />

Bei unserem Jubiläums-Jam sind die Vorträge gut angekommen,<br />

deshalb organisiere ich vielleicht für die nächsten Jams<br />

etwas ähnliches – vielleicht<br />

abwechselnd nur<br />

Vorträge und nur Zeit zum<br />

Hacken.<br />

JW: Beim nächsten Jam<br />

wollen wir uns mit Ressourcen<br />

für Schulen beschäftigen.<br />

Wir hoffen, dass wir geeignetes Material zusammenstellen<br />

können, das es Lehrern leichter macht, die<br />

Möglichkeiten des <strong>Pi</strong> im Unterricht zu nutzen.<br />

MH: Ich möchte einmal ein richtig großes Jam in Cambridge<br />

veranstalten, so wie das Manchester Jamboree, das vor<br />

kurzem stattfand – mit Praxis-Workshops für junge Programmierer,<br />

die an diesem Tag an ihren Projekten arbeiten.<br />

Die Zukunft der <strong>Raspberry</strong> Jams<br />

Die Jams sind nicht mehr aus der <strong>Raspberry</strong>-<strong>Pi</strong>-Welt wegzudenken.<br />

Sie sind eine Institution geworden, ähnlich wie die<br />

Linux-Usergruppen. <strong>Das</strong> offene Format der Events schafft<br />

eine großartige Lernatmosphäre, und der Erfahrungsschatz,<br />

der bei den Jams zusammenkommt, ist<br />

unbezahlbar.<br />

Auch im deutschsprachigen Raum haben bereits<br />

erste <strong>Raspberry</strong> Jams stattgefunden, wenngleich der<br />

Schwerpunkt bisher deutlich auf den englischsprachigen<br />

Ländern liegt. Termine und Informationen sind auf<br />

http://raspberryjam.org zu finden.<br />

95


Coding<br />

Geany: Editor de<br />

<strong>Das</strong> perfekte Schreibprogramm für Programmierer: Jahrelang haben wir<br />

danach gesucht, jetzt sind wir endlich fündig geworden.<br />

Code schreiben ist eine sehr persönliche Sache. Jeder<br />

hat seine Lieblingsprogramme und seine bevorzugten<br />

Techniken und Herangehensweisen, wie man einen<br />

Code schreibt, der gut funktioniert. Code schreiben ist fast so<br />

etwas wie Zen-Meditation, und Hunderte von Büchern sind<br />

darüber verfasst worden. Deshalb werden wir uns davor<br />

hüten, Ihnen weismachen zu wollen, unsere Herangehensweise<br />

wäre die beste.<br />

Doch eigentlich geht es bei allen Debatten darum, ob als<br />

Fenster, in dem der Code geschrieben wird, eine IDE, also<br />

eine integrierte Entwicklungsumgebung, oder ein Editor verwendet<br />

wird. Es ist interessant, dass neue Programmierer,<br />

die gerade erst anfangen, sich oft für die IDEs aussprechen.<br />

Sie halten IDEs vor allem deshalb für unverzichtbar, weil<br />

damit mehr Leute neue Apps schreiben können. Viele erfahrene<br />

Hacker dagegen bevorzugen Editoren, die überflüssigen<br />

Programmcode vermeiden und mit denen sie sich direkt der<br />

eigentlichen Programmierung widmen können. Wir sehen<br />

Vorteile und Nachteile in beiden Argumenten. Es ist eine persönliche<br />

Entscheidung, und keine der beiden Seiten hat letztendlich<br />

recht.<br />

Doch wir wollen Ihnen zumindest einen Editor vorstellen,<br />

für den Sie sich mit vollster Überzeugung entscheiden können,<br />

und dieser Editor heißt Geany. Er braucht so wenig<br />

Strom und Speicherplatz, dass Sie ihn direkt auf Ihrem <strong>Raspberry</strong><br />

<strong>Pi</strong> laufen lassen können. Meistens ist er schon auf dem<br />

Gerät vorinstalliert, und er sollte in allen Paketmanagern enthalten<br />

sein.<br />

Einfach und leistungsstark<br />

Im Grunde ist Geany ein Texteditor, den man aufgebockt und<br />

hochfrisiert hat mit all den schönen Dingen, von denen Programmierer<br />

schwärmen. Geany ist weder eine IDE noch ein<br />

normaler Texteditor – er ist ein Editor, der alle wichtigen<br />

Funktionen hat, die man sich von einer IDE wünscht. Geany<br />

versucht gar nicht erst, all die Assistenten, Einsteiger-Templates<br />

und anderen Elemente einzubinden, die man für gewöhnlich<br />

in einer IDE findet. Aber er bietet die Hauptfunktionen,<br />

die man braucht, um Apps zu schreiben, darunter einen<br />

guten Editor, einen Klassen-Navigator und Code-Folding.<br />

Damit ist Geany die zurzeit beste Wahl für alle Hobby- und<br />

Profiprogrammierer, die Apps in Linux schreiben.<br />

Geany wurde mit dem GTK-Widget-Set geschrieben, deshalb<br />

lässt er sich problemlos in die meisten Desktop-Umgebungen<br />

integrieren, wenn Sie mit dem <strong>Pi</strong> selbst programmieren.<br />

Software-Pakete sind im Ubuntu Software Centre<br />

erhältlich, im Everything-Repository von Fedora. Für Debian,<br />

Gentoo, OpenSUSE, Arch Linux, Centos, RHEL, ALT Linux,<br />

SourceMage und Crux können Pakete hier heruntergeladen<br />

werden: www.geany.org/Download/ThirdPartyPackages.<br />

Integrierter Support existiert für alle möglichen Programmiersprachen,<br />

darunter (O)Caml, Ada, Assembler, C, C#,<br />

C++, COBOL, Cython, D, Fortran, FreeBasic, Genie, GLSL,<br />

Haskell, Haxe, Java, Objective C, Pascal, Scala, Vala, VHDL<br />

und Verilog. Und Geany unterstützt auch Skript- und Auszeichnungssprachen<br />

wie ActionScript, CMake, Erlang, Ferite,<br />

Forth, Javascript, LISP, Lua, Makefile, Matlab, NSIS, Perl,<br />

PHP, Python, R, Ruby, Shell, Tcl, CSS, DocBook, HTML,<br />

LaTeX, Markdown, reStructuredText, Txt2Tags und XML. Als<br />

zusätzliches Extra gibt es auch einen guten Support für Abc-,<br />

Config-, Diff-, Gettext-, SQL-, und YAML-Dateien. Andere Programmiersprachen<br />

können ebenfalls mit Geany verwendet<br />

werden, allerdings ohne automatische Syntaxhervorhebung<br />

und andere Funktionen.<br />

In diesem Artikel nehmen wir Sie mit auf eine Tour durch<br />

Geany und schauen uns viele seiner Funktionen genauer an.<br />

Zu Illustrationszwecken erstellen wir ein neues Projekt, für<br />

das wir Code schreiben und an dem wir Ihnen beispielhaft<br />

zeigen, wie Sie die verschiedenen Anwendungen und Konfigurationsoptionen<br />

je nach Programmiererfahrung an Ihre Bedürfnisse<br />

anpassen können.<br />

Wir schreiben die Code-Beispiele in Python, aber Sie<br />

können jede Sprache verwenden, die Sie wollen. Und jetzt<br />

geht’s los.<br />

<strong>Das</strong> Interface<br />

Starten Sie Geany. Es erscheint ein Interface ähnlich wie in<br />

Abb. 1. <strong>Das</strong> Interface besteht aus drei Hauptfenstern. Links<br />

ist der Browser. Hier können Sie schnell die verschiedenen<br />

Dateien, Klassen, Funktionen sowie andere Symbole finden,<br />

die zu Ihrem Projekt gehören. Wir werden uns später, wenn<br />

96


Coding<br />

luxe<br />

wir unseren Code schreiben, genauer damit befassen.<br />

Rechts ist der Haupt-Texteditor. Hier werden Sie die meiste<br />

Zeit verbringen. Ähnlich wie bei anderen modernen Texteditoren<br />

können Sie mehrere Dateien gleichzeitig öffnen und<br />

sie über die zugehörigen Registerkarten aufrufen.<br />

Unterhalb des Texteditors ist das Meldungsfenster. Hier<br />

finden Sie den Output Ihres Compilers/Interpreters, Fehlermeldungen<br />

und andere nützliche Funktionen, etwa für Notizen,<br />

und eine Anzeige der Schritte, die Sie bei Ihrem Projekt<br />

noch durchführen müssen.<br />

Am oberen Rand des Monitors sehen Sie die Menüleiste<br />

(bei Ubuntu fügt sich das Menü wie bei den meisten anderen<br />

Programmen in das obere Feld ein), dort finden Sie auch<br />

Symbolleisten mit den gebräuchlichsten Funktionen des<br />

Texteditors. Die Symbolleisten können Sie ebenfalls nach<br />

Ihren Wünschen anpassen. Um sie zu ändern, klicken Sie mit<br />

der rechten Maustaste auf die Symbolleiste und wählen Sie<br />

„Toolbar Preferences“. Klicken Sie dann auf den „Customize<br />

Toolbar“-Button, worauf der Symbolleisten-Editor erscheint.<br />

Wählen Sie einfach die Funktionen links aus und klicken Sie<br />

auf den Pfeil rechts, um sie zur Symbolleiste hinzuzufügen.<br />

Code schreiben<br />

Und damit sind wir soweit und können endlich ein neues Projekt<br />

erstellen. Klicken Sie auf Project > New. Es öffnet sich ein<br />

Dialogfenster. Geben Sie einen Namen für Ihr Projekt ein und<br />

klicken Sie dann auf Create. Jetzt können wir ein paar Einstellungen<br />

für das Projekt vornehmen. Klicken Sie dazu auf Project<br />

> Properties. Die Registerkarte Indentation („Einrückung“)<br />

ist ein guter Anfang. Hier können Sie einstellen, wie<br />

Tabs/Leerstellen verwendet werden. <strong>Das</strong> ist besonders praktisch<br />

für Python-Entwickler, die sowohl an Projekten arbeiten,<br />

bei denen Tabs benutzt werden, als auch an Projekten, die<br />

Leerstellen benutzen.<br />

Wenn Sie an einem Projekt arbeiten, das einen Compiler<br />

benötigt (wie etwa eine C/C++-App), können Sie auch über<br />

die Registerkarte Build die Befehle einstellen, um das Projekt<br />

zu erstellen. Dabei geben Sie einfach die Befehle und Ihr<br />

Die Top Ten der Geany-Funktionen<br />

Zehn Gründe, warum Sie Geany auf<br />

jeden Fall ausprobieren sollten:<br />

1 Einfache Handhabung Geany ist<br />

einfach zu bedienen und fügt sich gut<br />

in alle Programmier-Projekte ein.<br />

2 Code-Navigation Funktionen<br />

und Klassen in einem Code-Netz<br />

sind mit dem Klassen- und Datei-<br />

Browser leicht zu finden.<br />

3 Sprachen-Support und Syntaxhervorhebung<br />

Geany unterstützt<br />

viele Programmiersprachen, darunter<br />

C, C++, Python, PHP, Perl, Ada,<br />

Java, Ruby, Tcl, HTML und CSS.<br />

4 Auto-Vervollständigung von<br />

Symbolnamen Sie erinnern sich<br />

nicht an die Funktion, die Sie<br />

brauchen? Geany schlägt Ihnen<br />

Funktionen vor, mitsamt der<br />

Argumente, die sie enthalten.<br />

5 Automatisches Schließen von<br />

XML- und HTML-Tags Wenn Sie HTML<br />

und XML schreiben, macht die Vervollständigungsfunktion<br />

von Endtags es<br />

einfacher, Text fehlerfrei auszuzeichnen.<br />

6 Code-Folding Code-Absätze,<br />

an denen Sie nicht arbeiten, blenden<br />

Sie mit dieser einfach zu<br />

bedienenden Funktion aus und ein.<br />

7 Plug-ins Es gibt etliche Komponenten<br />

aktuelles Verzeichnis für die Programmierung ein. Wir gehen<br />

so allerdings nicht vor, weil wir für dieses Beispiel Python<br />

verwenden.<br />

Wahrscheinlich ist Ihnen inzwischen schon aufgefallen,<br />

dass beim Klicken auf Create Project kein Assistent erschienen<br />

ist, der Ihnen Optionen anbietet, um Ihre App zu entwickeln<br />

und darzustellen. Wie schon gesagt, Geany ist nicht<br />

wirklich eine IDE, und deshalb gibt es hier auch keinen Assistenten.<br />

Um Ihre App zu erstellen, müssen Sie ein anderes<br />

Programmierwerkzeug verwenden, beispielsweise Quickly,<br />

und dann kopieren Sie die Dateien in das Projektverzeichnis<br />

von Geany.<br />

Für unser Projekt erstellen Sie eine neue Datei, indem Sie<br />

auf File > New (with Template) > main.py klicken. Dadurch<br />

wird eine Python-Datei erstellt, die bereits Code enthält, darunter<br />

einen Kommentar mit der mitgelieferten Lizenz sowie<br />

den Standardcode, um die main()-Python-Funktion zu instanziieren.<br />

Klicken Sie jetzt auf File > Save As, und speichern<br />

Sie die Datei als app.py. Nun fügen wir das berühmte „Hello<br />

World!“ in main() ein, damit wir etwas drucken können, wenn<br />

wir das Programm ausführen.<br />

print “Hello World!”<br />

Speichern Sie die Datei und führen Sie sie aus. Sie können<br />

die Programmdatei in Geany laufen lassen, indem Sie zuerst<br />

auf die Terminal-Registerkarte im Output-Fenster unten klicken.<br />

Wechseln Sie dann in das Verzeichnis mit dem Programm<br />

(in unserem Beispiel ist das /home/jono/projects/<br />

Super App/) und führen Sie dieses aus:<br />

cd projects/Super App<br />

python app.py<br />

(Plug-ins) von anderen Anbietern für<br />

Geany, mit denen man die Funktionen<br />

des Texteditors erweitern kann.<br />

8 Task-Support Geany zeigt alle<br />

TODO und FIXME-Kommentare an<br />

einem Ort an, so dass sie leichter ausgeführt<br />

und korrigiert werden können.<br />

9 Eingebettetes Terminal In dem<br />

eingebetteten Terminal können Sie Teile<br />

Ihres Codes in einem Interpreter testen<br />

und Dateien einfach und schnell finden.<br />

10 Debugger-Support Der integrierte<br />

Debugger vereinfacht die<br />

Suche nach Fehlern und problematischen<br />

Stellen im Code.<br />

Abb. 1 Der<br />

Geany-Texteditor<br />

ist einfach und<br />

übersichtlich.<br />

97


Coding<br />

Abb. 2 Mit den<br />

Funktionen von<br />

Geany sind auch<br />

große Projekte<br />

einfach zu<br />

handhaben.<br />

Auf Ihrem Bildschirm sollte jetzt „Hello World!“ erscheinen.<br />

Schauen wir uns nun kurz an, wie wir uns mit Geany einfacher<br />

durch den Code bewegen können.<br />

Klicken Sie im Browser auf der linken Seite auf die Registerkarte<br />

Symbols. Diese Registerkarte werden Sie noch sehr<br />

oft verwenden, um Code-Abschnitte zu finden. Wie Sie jetzt<br />

schon sehen können, zeigt die Registerkarte unsere main()<br />

-Funktion. Wenn Sie jetzt noch auf die Registerkarte Documents<br />

klicken, dann sehen Sie auch unsere einzige Quelldatei.<br />

Doch richtig deutlich wird die Nützlichkeit dieser Registerkarte<br />

dann, wenn Sie mit vielen Quelldateien arbeiten.<br />

Wenn Sie die main()-Funktion in der Symbols-Registerkarte<br />

klicken, erscheint ein kleiner Pfeil am Rand des Editors, der auf<br />

die Funktion hinweist. Ebenfalls im Editor erscheint neben<br />

jedem Code-Block ein kleines weißes Kästchen mit einem -<br />

darin. Mit diesem kleinen Kästchen können Sie Teile des<br />

Codes „wegfalten“, die gerade nicht von Interesse sind. Wenn<br />

Sie in das Kästchen klicken, verwandelt sich das - in ein + Symbol<br />

als Hinweis, dass hier ein Code-Block ausgeblendet ist.<br />

Wir wollen jetzt eine Klasse erstellen, um Ihnen noch einmal<br />

zu zeigen, wie einfach Geany die Navigation in Ihrem<br />

Code macht. Fügen Sie den folgenden Code zu Ihrem Programm<br />

hinzu:<br />

class MyClass:<br />

def __init__(self):<br />

print “Creating a MyClass object”<br />

def show_info(self):<br />

print “This class is MyClass”<br />

def foo(self, value):<br />

print “You provided me with %s “ % value<br />

if __name__ == ‘__main__’:<br />

obj = MyClass()<br />

obj.show_info()<br />

obj.foo(5)<br />

In diesem Code erstellen wir eine einfache (und ziemlich<br />

nutzlose) Klasse. Beachten Sie, dass wir die main()-Funktion<br />

entfernt haben. Sie ist nicht mehr erforderlich.<br />

Während Sie den Code geschrieben haben, ist Ihnen vielleicht<br />

aufgefallen, dass die kleinen weißen Code-Folding-<br />

Kästchen automatisch neben jeder neu hinzugefügten Klassen-Funktion<br />

aufgetaucht sind. Geany denkt mit und versteht<br />

den Code, den Sie schreiben. Der Editor wendet solche Funktionen<br />

automatisch an und wartet nicht, bis Sie einen Absatz<br />

zu Ende geschrieben oder die Datei gespeichert haben.<br />

Wahrscheinlich ist Ihnen noch eine weitere Funktion aufgefallen:<br />

Wenn Sie Ihre Klassen-Funktionen aufrufen (wenn Sie<br />

also obj eintippen und dann den Funktionsnamen), springt in<br />

Geany ein kleines Fenster auf, in dem Funktionen aufgelistet<br />

werden, die dem Code entsprechen, den Sie bis jetzt geschrieben<br />

haben. <strong>Das</strong> ist ein unglaublich nützliches Hilfsmittel,<br />

und Geany schlägt oft sogar Funktionsnamen für unterschiedliche<br />

APIs vor, die Sie verwenden.<br />

Nachdem wir die Klasse zu unserem Programm hinzugefügt<br />

haben, schauen Sie sich die Registerkarte Symbols im<br />

Browser links im Fenster an. Sie sehen, dass hier neben unserer<br />

erstellten Klasse ein kleines blaues Icon erscheint. Die<br />

Funktionen innerhalb der Klasse werden als Teil der Klassenhierarchie<br />

angezeigt. Für eine kleine Anwendung wie diese<br />

bringt die Klassenansicht nicht viel, aber bei einer großen Anwendung,<br />

wie zum Beispiel die in Abb. 2, ist dieser Klassen-<br />

Navigator extrem hilfreich, wenn Sie etwas suchen und in der<br />

Codebasis hin- und herspringen müssen.<br />

Konfiguration<br />

Einer der Hauptunterschiede zwischen einer IDE und einem<br />

Editor liegt in den unterschiedlichen Konfigurationsmöglichkeiten.<br />

Viele IDEs bieten eine Anzahl sinnvoller Standardeinstellungen<br />

und erlauben darüber hinaus nur eingeschränkte<br />

Konfigurationsänderungen, damit die IDE für die User nicht<br />

zu kompliziert wird. Editoren hingegen besitzen nicht die<br />

komfortable Frontend-Handhabung der IDEs, doch bei den<br />

meisten können viel mehr Funktionen nach Bedarf konfiguriert<br />

werden. <strong>Das</strong> gilt auch für Geany.<br />

Geany bietet geradezu fantastische Konfigurationsmöglichkeiten<br />

für alle möglichen Aspekte des Programmierens.<br />

Sie können Geany in zwei Bereichen konfigurieren:<br />

1 Edit > Preferences – hier konfigurieren Sie die Anwendung<br />

an sich.<br />

2 Edit > Plugin Preferences – hier konfigurieren Sie zusätzliche<br />

Komponenten bzw. Plug-ins (mehr zu Plug-ins<br />

später).<br />

Schauen wir uns ein paar Elemente von Geany (ohne zusätzliche<br />

Plug-ins) an, die Sie vielleicht konfigurieren<br />

möchten.<br />

Zuerst konfigurieren wir einmal die Information, die an die<br />

Header-Kommentare angefügt wird, wenn Sie eine neue<br />

Datei zu Ihrem Projekt hinzufügen. Klicken Sie Edit > Preferences<br />

> Templates, dann sehen Sie die verschiedenen Felder,<br />

die Sie ändern können. Geany füllt automatisch viele der<br />

Felder für Sie aus, doch einige der Informationen wollen Sie<br />

wahrscheinlich ändern.<br />

In einigen Feldern steht etwas, das nach Zeichensalat aussieht,<br />

zum Beispiel %Y-%m-%d im Datumsfeld. Dies sind<br />

Codes, die wie Templates funktionieren und etwa wie hier<br />

das Format der Datumsanzeige festlegen. %Y-%m-%d wird<br />

als 2012-12-25 angezeigt. (%Y bedeutet 2012, %m 12 und<br />

%d 25). Eine Liste all dieser Codes und ihrer Funktionen finden<br />

Sie hier: http://man.cx/strftime.<br />

Für viele Programmierer gehören die Tastaturbelegungen<br />

zu den wichtigsten Funktionen, die sie selbst nach ihren Wünschen<br />

einstellen möchten. Programmieren ist eine Kunst und<br />

eine Wissenschaft, die ihren eigenen Takt und Rhythmus<br />

Plug-ins<br />

Einer der Riesenvorteile von Geany ist die große Anzahl von<br />

Plug-ins von anderen Anbietern, die Sie installieren können.<br />

Viele dieser Plug-ins sind schon in Ihrem jeweiligen Paketmanager<br />

enthalten (wie im Ubuntu Software Centre oder über<br />

yum). Sie finden aber auch bei http://plugins.geany.org<br />

Informationen über Plug-ins.<br />

98


Coding<br />

Versionskontrolle?<br />

Eine der häufigsten Fragen ist, ob Geany einen integrierten<br />

Support für Git, Bazaar, Subversion, CVS und<br />

andere Versionskontrollsysteme hat. Standardmäßig<br />

unterstützt Geany diese Systeme nicht, doch auch<br />

dafür es gibt ein Plug-in. Mehr Informationen finden<br />

Sie auf http://plugins.geany.org/geanyvc.html.<br />

braucht. Wenn man „drin“ ist, dann möchte man den Rhythmus<br />

nicht unterbrechen, weil sonst die Produktivität im<br />

Code-Schreiben beeinträchtigt wird. <strong>Das</strong> ist einer der Gründe,<br />

warum die meisten von uns schon ganze Nächte durchgehackt<br />

haben, weil sie nämlich den Programmierfluss nicht<br />

stören wollten.<br />

Nichts unterbricht den Fluss so sehr wie die Verwendung<br />

der Maus. Bewegt man die Hände weg von der Tastatur zur<br />

Maus und wieder zurück, wird man automatisch langsamer.<br />

Tastaturbelegungen sind daher wichtig, um den Programmierfluss<br />

aufrechtzuerhalten. Wenn Sie noch nie Tastaturbelegungen<br />

benutzt haben, dann wird es Zeit, dass Sie sie lernen.<br />

Zum Glück können Sie in Geany fast jede<br />

Tastenbelegung selbst konfigurieren. Klicken Sie auf Edit ><br />

Preferences und dann auf die Registerkarte Keybindings.<br />

Ein anderer Bereich für die Konfiguration ist der eigentliche<br />

Editor. Ein Texteditor scheint eigentlich eine simple Sache zu<br />

sein – man gibt Text ein –, doch die Leute verwenden Texteditoren<br />

auf ganz unterschiedliche Weise. Einzüge, Syntaxhervorhebung,<br />

Zeilennummerierung, automatischer Zeilenumbruch,<br />

Zeilenvorschub und überflüssige Leerzeichen,<br />

Codevervollständigung und andere Funktionen sind dabei für<br />

die User interessant.<br />

Um einzustellen, welche Teile des Editors sichtbar sind<br />

und welche nicht, klicken Sie auf View > Editor.<br />

Wir empfehlen, dass Sie auf jeden Fall die Zeilennummerierung<br />

einschalten. Vor allem, wenn Sie mit anderen Programmierern<br />

zusammenarbeiten, ist es sehr hilfreich, wenn<br />

Sie die Nummer der Zeile benennen können, in der Sie ein<br />

Problem sehen. Sie können über View > Editor > Color Scheme<br />

auch eine andere Farbgebung auswählen, falls Sie etwa<br />

ein dunkleres Schema bevorzugen. Weitere Farbschemata<br />

finden Sie unter www.geany.org/Download/<br />

Extras#colors.<br />

Tasks ausführen<br />

Üblicherweise fügt man beim Programmieren Kommentare<br />

zum Code dazu, mit Hinweisen, was in einem bestimmten<br />

Absatz noch verbessert werden soll. Wenn beispielsweise<br />

eine bestimmte Funktion eingeschränkt ist, dann können Sie<br />

das Folgende zum Code hinzusetzen:<br />

#TODO: Expand this to include support for XYZ.<br />

Alternativen zu Geany<br />

» Eclipse bereitete den Weg für die heutigen<br />

IDEs. <strong>Das</strong> plattform- und sprachenübergreifende<br />

Tool wurde zum Schreiben kommerzieller<br />

Anwendungen entwickelt. Es ist<br />

kompliziert und nicht sehr benutzerfreundlich,<br />

unterstützt aber viele Programmiersprachen.<br />

» KDevelop gehört zu den frühesten IDEs,<br />

die speziell für eine Desktop-Umgebung<br />

kreiert wurden. Es ist vor allem für KDE-<br />

Programmierer gedacht und bietet eine<br />

Sie können auch einen Kommentar neben ein Stück Code<br />

schreiben, das noch korrigiert werden muss. <strong>Das</strong> sieht dann<br />

oft so aus:<br />

#FIXME: Make this thread-safe.<br />

<strong>Das</strong> Problem an diesen kurzen Notizen ist, dass sie sich oft<br />

kaum wiederfinden lassen, wenn man sie vor der Freigabe<br />

des Codes bearbeiten möchte.<br />

Zum Glück besitzt Geany eine praktische kleine Funktion,<br />

mit der Sie sich alle diese Notizen gesammelt an einem Ort<br />

ansehen können. Es wird sozusagen eine TODO-Liste erzeugt,<br />

auf der all die Dinge stehen, um die Sie sich noch kümmern<br />

müssen. Benutzen Sie einfach TODO und FIXME,<br />

genau wie oben beschrieben, und stellen Sie unter Edit > Plugin<br />

Preferences > Addons die Funktion „Show available tasks<br />

in the Message window“ ein. Sie können dafür auch andere<br />

Begriffe als TODO und FIXME definieren, wenn Sie das wollen,<br />

doch TODO und FIXME sind sehr gebräuchlich, deshalb<br />

ist es sinnvoll, wenn Sie diese Standardeinstellung belassen.<br />

Geany ist ein kleiner und doch ungemein leistungsstarker<br />

Texteditor, der Ihnen alle wichtigen Werkzeuge bietet, die Sie<br />

brauchen, um Code zu schreiben. Die Entwickler von Geany<br />

haben sich auf eine einfache Handhabung und auf die Bedürfnisse<br />

von ernsthaften Programmierern konzentriert und<br />

das Programm nicht mit Schnickschnack überfrachtet, den<br />

die meisten Programmierer gar nicht brauchen.<br />

Deshalb hat man das Gefühl, einen ausgereiften Texteditor<br />

an der Hand zu haben. Und mit den vielen Konfigurationsmöglichkeiten<br />

und der großen Auswahl an zusätzlichen Plugins<br />

können Sie Geany auf Ihre individuellen Bedürfnisse<br />

zuschneiden.<br />

Geany ist ein leicht zu lernender Editor; in diesem Artikel<br />

stehen schon die wichtigsten Dinge, die Sie wissen müssen,<br />

damit Sie loslegen können. Wir empfehlen, dass Sie den Code<br />

auf Ihrem Desktop-Rechner schreiben und ihn dann auf den<br />

<strong>Raspberry</strong> <strong>Pi</strong> portieren. Doch es funktioniert genauso, wenn<br />

Sie alles auf dem <strong>Pi</strong> machen. Happy programming trails!<br />

umfassende Auswahl an Funktionen.<br />

» GEdit könnte man auf den ersten Blick für<br />

einen einfachen Texteditor halten, doch es<br />

gibt eine ganze Reihe von Plug-ins und Erweiterungen,<br />

mit denen sich GEdit in etwas verwandeln<br />

lässt, das eher wie Geany aussieht.<br />

» Qt Creator ist eine IDE, die speziell für Qtund<br />

QML-Apps entwickelt wurde. Man kann<br />

mit ihr nicht nur Code schreiben, sondern auch<br />

Schnittstellen erstellen, Dokumentationen<br />

Abb. 3 Geany<br />

bietet eine großartige<br />

Auswahl<br />

von sinnvollen<br />

Standardeinstellungen.<br />

durchstöbern und mehr. Wenn Sie Qt-Apps<br />

schreiben, empfehlen wir den Qt Creator.<br />

» Anjuta ist das Produkt einer langen<br />

Entwicklungsgeschichte. Diese große IDE<br />

wurde für das Schreiben von Gnome-<br />

Anwendungen entwickelt, unterstützt<br />

aber auch andere Anwendungsarten.<br />

» Bluefish ist ein genialer Editor, wenn<br />

Sie nur Web-Content in HTML, PHP<br />

oder Python erstellen möchten.<br />

99


Coding<br />

Code-Konzepte:<br />

Datentypen<br />

Die Auswahl<br />

eines falschen<br />

Datentyps in<br />

einem Programm<br />

kann Probleme<br />

verursachen. In<br />

diesem Fall erhalten<br />

Sie einen<br />

TypeError.<br />

Funktionen sagen Programmen, was sie tun sollen, aber es sind<br />

Daten, mit denen sie dies tun. Sehen wir uns also die Daten bei<br />

Python an.<br />

In diesem Artikel behandeln wir die Basisdatentypen bei<br />

Python sowie die Konzepte, die mit ihnen einhergehen.<br />

Auf den nachfolgenden Seiten sehen wir uns dann einige<br />

weiterführende Themen an, die auf dem aufbauen, was wir<br />

hier machen: Datenabstraktion, schicke Strukturen wie etwa<br />

Bäume und anderes.<br />

Was sind Daten?<br />

Die Programme, die wir schreiben, enthalten eine Vielzahl<br />

von Datentypen. In einen Zinsrechner sind beispielsweise der<br />

Zinssatz, die Laufzeit des Kredits sowie die Höhe des Kredits<br />

jeweils Datentypen; in einem Einkaufslisten-Programm gibt<br />

es alle möglichen Arten von Essen sowie die Liste, in der sie<br />

gespeichert sind. Der Computer kennt jedoch nicht den Unterschied<br />

zwischen all diesen Datentypen. Er kann nur mit ein<br />

paar ganz grundlegenden Datentypen etwas anfangen, und<br />

als Programmierer muss man diese kreativ einsetzen, um<br />

damit die Vielfalt der realen Welt abzubilden.<br />

Wir beginnen mit drei Datentypen. Zunächst einmal haben<br />

wir Zahlen. 3, 10 und 2580 sind Beispiele dieses Datentyps.<br />

Um genau zu sein, sind das Integer-Werte (ganze Zahlen),<br />

auch „ints“ genannt. Python kennt noch andere Arten von<br />

Zahlen, beispielsweise „long“ (lange Integer), „float“ (Fließkommawerte<br />

wie 10,35 oder 0,8413) und „complex“ (komplexe<br />

Zahlen). Zweitens gibt es Strings wie etwa ’Hello<br />

World’, ’Banane’ oder ’<strong>Pi</strong>zza’. Hierbei handelt es sich jeweils<br />

um eine Sequenz von Zeichen, die in einfachen oder doppelten<br />

Anführungszeichen stehen. Unser dritter Datentyp sind<br />

Listen wie zum Beispiel [’Banane’, ’Orange’, ’Himbeere’].<br />

Listen ähneln Strings, jedenfalls unter dem Gesichtspunkt,<br />

dass sie Sequenzen darstellen. Was beide Datentypen unterscheidet,<br />

ist, dass in einer Liste jedes Element einem anderen<br />

Typus angehören kann. Im obigen Beispiel sind alle Elemente<br />

Strings, aber Sie könnten auch eine andere Liste anlegen,<br />

welche die verschiedenen Datentypen mischt, wie etwa<br />

[’Banane’, 10, ’a’]. Listen erkennt man an den eckigen Klammern,<br />

die sie umgeben, und jedes Element ist vom nächsten<br />

durch ein Komma getrennt.<br />

Mit Daten arbeiten<br />

Es gibt eine Vielzahl von Dingen, die Sie mit den verschiedenen<br />

Datentypen in Python anstellen können. Sie können zwei<br />

Zahlen addieren, subtrahieren, teilen und multiplizieren und<br />

Python wird das Ergebnis zurückgeben:<br />

>>> 23 + 42<br />

65<br />

>>> 22 / 11<br />

2<br />

Wenn Sie mehrere Arten von Zahlen mischen, wird Python<br />

das Ergebnis so ausgeben, dass die höchste Genauigkeit gewährleistet<br />

ist. Addieren Sie beispielsweise eine ganze Zahl<br />

und einen Fließkommawert, wird das Ergebnis eine Fließkomma-Zahl<br />

sein. Sie können das mit der Funktion type()<br />

überprüfen. Sie gibt als Antwort den Datentyp des Wertes<br />

zurück, den Sie ihr übergeben haben:<br />

>>> type(8)<br />

<br />

>>> type(23.01)<br />

<br />

>>> type(8 + 23.01)<br />

<br />

Sie können auch die gleichen Operationen auf Strings und<br />

Listen anwenden, wobei sie dort allerdings unterschiedliche<br />

Funktionen haben. Der +-Operator fügt zwei Strings oder<br />

zwei Listen zusammen, während der *-Operator den Inhalt<br />

einer Liste oder eines Strings wiederholt.<br />

>>> ”Hallo” + ”Welt”<br />

”Hallo Welt”<br />

>>> [”Apfel”] * 2<br />

[”Apfel”, ”Apfel”]<br />

Strings und Listen haben zudem ihr eigenes Set an Operationen,<br />

wie zum Beispiel das Schneiden. Damit lassen sich bestimmte<br />

Teile eines Strings über einen numerischen Index<br />

auswählen. Die Zählung beginnt dabei bei 0.<br />

>>> word = ”Hallo”<br />

>>> word[0]<br />

’H’<br />

>>> word[3]<br />

’ l’<br />

>>> list = [’Banane’, ’Orange’, ’Himbeere’]<br />

>>> list[2]<br />

100


Coding<br />

’Orange’<br />

Indizes funktionieren auch umgekehrt. Wenn Sie auf das letzte<br />

Element einer Liste oder in einem String zugreifen möchten,<br />

können Sie als Indexnummer -1 nutzen. -2 würde das<br />

vorletzte Element adressieren, -3 das drittletzte und so weiter.<br />

Beachten Sie, dass, wenn Sie mit negativen Indizes arbeiten,<br />

die Zählung nicht bei 0 beginnt.<br />

Methoden<br />

Listen und Strings haben noch weitere Spezialoperationen,<br />

diese werden Methoden genannt. Sie ähneln Funktionen wie<br />

type(), weil auch sie eine Prozedur ausführen. Was sie davon<br />

unterscheidet, ist, dass sie auf ein spezielles Datum angewendet<br />

werden, das sie bearbeiten. Deshalb unterscheiden<br />

Sie sich auch hinsichtlich der Syntax. Zwei Methoden für Listen<br />

sind zum Beispiel append und insert.<br />

>>> list.append(’Birne’)<br />

>>> list<br />

[’Banane’, ’Orange’, ’Himbeere’, ’Birne’]<br />

>>> list.insert(1, ’Pflaume’)<br />

>>> list<br />

[’Banane’, ’Pflaume’, ’Orange’, ’Himbeere’, ’Birne’]<br />

Wie Sie sehen können, wird die Methode aufgerufen, indem<br />

Sie einen Punkt an das Datenelement anhängen, das Sie bearbeiten<br />

möchten, gefolgt vom Namen der Methode. Die Argumente<br />

der Methode werden in den Klammern übergeben,<br />

wie Sie es auch bei Funktionen tun würden. Genauso funktioniert<br />

es bei Strings und allen anderen Datenobjekten:<br />

>>> word = ”HALLO”<br />

>>> word.lower()<br />

’hallo’<br />

Es gibt viele verschiedene Methoden, die auf Listen und<br />

Strings angewendet werden können, auf Tupel oder Wörterbücher<br />

(mehr dazu weiter unten). Um alle Methoden und die<br />

Reihenfolge der Argumente kennenzulernen, konsultieren Sie<br />

die Dokumentation von Python.<br />

Variablen<br />

In unseren Beispielen haben wir die Variablen genutzt, um<br />

die Arbeit mit Daten zu vereinfachen. Variablen sind eine<br />

Möglichkeit der Benennung von Werten – bestimmten Datenstücken.<br />

Sie erleichtern die Verwaltung der einzelnen<br />

Daten, mit denen Sie arbeiten, die Programmierung wird<br />

deutlich weniger komplex (sofern Sie aussagekräftige<br />

Namen verwenden).<br />

Wie wir oben gesehen haben, erstellen Sie in Python eine<br />

Variable mit einer Zuweisung. Zuerst kommt der Name der<br />

Variablen, dann ein Gleichheitszeichen, gefolgt von der Information,<br />

die Sie der Variablen zuweisen möchten. Von diesem<br />

Zeitpunkt an werden Sie jedes Mal, wenn Sie auf den<br />

zuvor angegebenen Namen verweisen, mit den Daten arbeiten,<br />

denen Sie diesem Namen zugewiesen haben. In den<br />

Beispielen haben wir dies gesehen, als wir uns auf das zweite<br />

Zeichen eines Strings oder das dritte Element einer Liste bezogen<br />

haben, indem wir einen Ausdruck an die Variable anhängten.<br />

Auch wenn wir die type()-Funktion verwenden,<br />

greifen wir auf den Inhalt der Variablen zu:<br />

>>> type(word)<br />

<br />

>>> type(list)<br />

<br />

Andere Datentypen<br />

Es gibt zwei weitere gängige Datentypen, die bei Python<br />

Anwendung finden: Tupel und Wörterbücher.<br />

Tupel sind ähnlich wie Listen – ein Sequenzdatentyp, welcher<br />

Elemente diverser Art enthalten kann. Der große Unterschied<br />

ist, dass Tupel unveränderlich sind: Wenn ein Tupel<br />

einmal erstellt wurde, können Sie ihn nicht mehr modifizieren.<br />

Tupel werden mithilfe runder Klammern angelegt:<br />

(’Banane’, ’Baum’, ’Katze’).<br />

Wörterbücher beinhalten – wie auch Listen und Tupel –<br />

eine Sammlung zusammengehöriger Elemente, allerdings<br />

werden die Elemente nicht durch Nummern indexiert, sondern<br />

durch Schlüssel. Zur Erstellung von Wörterbüchern nutzen<br />

Sie die geschweiften Klammern {}. Bei Wörterbüchern<br />

innerhalb von Python können Sie jeden nicht wandelbaren<br />

Datentyp als Schlüssel verwenden (dazu gehören auch<br />

Strings), sofern der Schlüssel nicht schon im Wörterbuch<br />

vorkommt. Wenn Sie einen bereits existierenden Schlüssel<br />

verwenden, wird sein alter Wert überschrieben und ist dauerhaft<br />

verloren.<br />

>>> english = {’free’: ’as in beer’, ’linux’: ’operating system’}<br />

>>> english[’free’]<br />

‘as in beer’<br />

>>> english[’free’] = ’as in liberty’<br />

>>> english[’free’]<br />

’as in liberty’<br />

Schleifen<br />

Eine häufig vorkommende Aufgabenstellung ist die Anwendung<br />

einer bestimmten Operation auf alle Elemente eines sequenziellen<br />

Datentyps wie etwa einer Liste. Sehen Sie sich<br />

folgendes kleines Python-Programm an:<br />

list = [’Banane’, ’Orange’, ’Kirsche’]<br />

for item in list:<br />

print item<br />

Zuerst legen wir ganz normal eine Liste an, dann verwenden<br />

wir das for … in …-Konstrukt, um die print-Funktion auf<br />

jedes Element der Liste anzuwenden. <strong>Das</strong> zweite Wort in diesem<br />

Code-Konstrukt muss nicht item sein, das ist nur ein<br />

Variablenname, der temporär jedem Listenelement zugewiesen<br />

wird, um darauf die print-Funktion anzuwenden. Wir hätten<br />

auch for letter in word schreiben können, und es hätte<br />

ebenso funktioniert.<br />

Mit diesen Basisdatentypen im Gepäck sind Sie bereit,<br />

Aufgabenstellungen aus der realen Welt anzugehen, wie wir<br />

auf den nächsten Seiten sehen werden.<br />

Lesen Sie die Python-Dokumentation, um auch mit anderen<br />

Methoden vertraut zu werden, welche die Sprache für die<br />

Datentypen bietet. Sie werden viele nützliche Werkzeuge wie<br />

etwa sort und reverse finden.<br />

Der Python-<br />

Interpreter ist<br />

ein großartiges<br />

Werkzeug, um<br />

mit Python-Code<br />

zu experimentieren<br />

und herauszufinden,<br />

wie<br />

verschiedene Datentypen<br />

zusammenarbeiten.<br />

101


Coding<br />

Designkonzepte:<br />

Komplexe Typen<br />

Wie unterschiedliche Datentypen zusammenspielen,<br />

um die Häufigkeit von Wörtern zu ermitteln.<br />

Wenig überraschend:<br />

<strong>Das</strong><br />

häufigste Wort<br />

in der englischen<br />

Originalausgabe<br />

von HG Wells‘<br />

The Time<br />

Machine ist der<br />

Artikel „the“.<br />

Pythons meistgebrauchte Datentypen wie int und float<br />

bedürfen kaum einer Erklärung. Es sind Zahlenwerte<br />

mit den typischen Operationen für mathematische<br />

Anwendungen. Die etwas komplexeren Typen wie String,<br />

Liste, Tupel und Dictionary sind in ihrer Anwendung weniger<br />

intuitiv, daher zeigen wir in diesem Artikel, wie man sie in der<br />

Praxis verwendet.<br />

Wir werden ein kurzes Programm schreiben, das die<br />

Häufigkeit einzelner Worte in einer Textdatei ermittelt.<br />

Satzzeichen werden ignoriert und Worte, die in Groß- und<br />

Kleinschreibung auftauchen (zum Beispiel Python und<br />

python), werden in der Statistik zusammengefasst. Nach der<br />

Analyse gibt das Programm das Ergebnis auf dem Bildschirm<br />

aus. Dies soll folgendermaßen aussehen:<br />

the: 123<br />

you: 10<br />

a: 600<br />

...<br />

Als Beispieltext verwenden wir den Roman The Time<br />

Machine von HG Wells, den Sie von der Website des Project<br />

Gutenberg herunterladen und im gleichen Verzeichnis unter<br />

dem Namen timemachine.txt abspeichern können, in dem<br />

Sie Ihre Python-Datei ablegen möchten.<br />

Im ersten Schritt machen wir den Text unserem Python-<br />

Programm verfügbar. Dazu verwenden wir die open()-Funktion:<br />

tm = open(‘timemachine.txt’, ‘r’)<br />

In diesem Beispiel erhält open() zwei Parameter. Der erste<br />

ist der Name der zu öffnenden Datei. Läge die Datei in<br />

einem anderen Verzeichnis, dann müssten wir hier den kompletten<br />

Dateipfad angeben. Der zweite Parameter legt fest, in<br />

welchem Modus die Datei geöffnet werden soll. Wir geben r<br />

für Lesezugriff an; andere gültige Werte wären w zum<br />

Schreiben und rw zum Lesen und Schreiben.<br />

<strong>Das</strong> zurückgegebene Datei-Handle weisen wir der<br />

Variable tm zu, damit wir im Weiteren auf die Datei zugreifen<br />

können. Dazu gibt es zahlreiche, auf den jeweiligen Zweck<br />

spezialisierte Möglichkeiten. In unserem Fall verwenden wir<br />

eine einfache for-in-Schleife. Deren Funktion können Sie testen,<br />

indem Sie im interaktiven Modus des Interpreters timemachine.txt<br />

öffnen und Folgendes eingeben:<br />

>>> for line in tm:<br />

print line<br />

...<br />

Auf Ihrem Bildschirm sollte nun jede einzelne Zeile des<br />

Romans erscheinen. Wenn wir diesen Code nun unter dem<br />

Namen cw.py in einer Datei abspeichern, dann haben wir<br />

bereits ein erstes Programmgerüst fertig..<br />

Aufräumarbeiten<br />

In der Programmbeschreibung haben wir festgelegt, dass<br />

Interpunktionszeichen entfernt und Groß-/Kleinschreibung<br />

ignoriert werden sollen, außerdem wollen wir ja Worte und<br />

nicht Zeilen zählen. Bisher lesen wir aber nur ganze, unveränderte<br />

Zeilen inklusive aller Satzzeichen und seltsamer<br />

Sonderzeichen (wie \r\n) ein.<br />

Die string-Dokumentation von Python (http://docs.<br />

python.org/library) verrät uns, dass es bereits vier vorgefertigte<br />

Methoden gibt, die uns unserem Ziel bedeutend<br />

näherbringen: strip(), translate(), lower() und split().<br />

Alle diese Methoden werden auf das String-Objekt angewendet,<br />

das sie verändern sollen – sie sind also Funktionen.<br />

Beispielsweise entfernt strip() bestimmte Zeichen vom<br />

Anfang und vom Ende des jeweiligen Strings:<br />

>>> line.strip()<br />

Wenn man strip() keine Argumente übergibt, dann entfernt<br />

die Funktion alle nicht sichtbaren Zeichen wie<br />

Leerzeichen und Zeilenumbrüche.<br />

Die Funktion translate() tauscht einzelne Buchstaben<br />

gegen andere aus, sie kann aber auch zum Löschen<br />

bestimmter Zeichen genutzt werden. Da wir nur alle<br />

Satzzeichen entfernen möchten, übergeben wir der Funktion<br />

zwei Argumente: Als erstes None und als zweites die Liste<br />

102


Coding<br />

der zu löschenden Zeichen:<br />

>>> line.translate(None, ‘!”#$%&\’()*+,-./:;?@[\\]^_`{|}~’)<br />

lower() verwandelt einzelne Zeichen in deren kleingeschriebene<br />

Pendants. split() zerlegt einen String in eine Liste<br />

mehrerer Strings, indem es den Ursprungstext an all jenen<br />

Stellen auseinanderbricht, die dem Funktionsargument entsprechen:>>><br />

line.split(‘ ‘)<br />

In diesem Beispiel übergeben wir in einzelnes Leerzeichen<br />

als Trennzeichen. Da alle Satzzeichen bereits entfernt sind,<br />

erzeugt dies eine Liste aller Worte des Ursprungstextes.<br />

Wenn wir all dies in die oben erstellte for-Schleife packen,<br />

dann erkennen wir bereits einen bemerkenswerten<br />

Fortschritt. Der Code sollte nun so aussehen:<br />

tm = open(‘timemachine.txt’, ‘r’)<br />

for line in tm:<br />

line = line.strip()<br />

line = line.translate(None, ‘!”#$%&\’()*+,-./:;?@<br />

[\\]^_`{|}~’)<br />

line = line.lower()<br />

list = line.split(‘ ‘)<br />

Alle String-Methoden geben einen neuen, modifizierten<br />

String zurückgeben; das ursprüngliche String-Objekt bleibt<br />

unverändert. Daher weisen wir jedes Funktionsergebnis<br />

erneut der Variable line zu und „vergessen“ damit deren vorherigen<br />

Wert.<br />

Einzigartig<br />

Bisher haben wir mit String-Funktionen alle Daten entfernt,<br />

die uns nicht interessieren. Wir haben außerdem mehrere<br />

lange Strings, die jeweils einer Textzeile entsprachen, in kleinere<br />

Häppchen zerlegt und diese in einer Liste gespeichert.<br />

Damit haben wir nun exakt das abstrakte Datenkonzept<br />

erzeugt, das uns eigentlich interessiert: Wörter.<br />

Aber noch sind wir nicht am Ziel. Wir müssen noch herausfinden,<br />

welche eindeutigen Wörter es gibt – nicht nur in<br />

einer einzelnen Zeile, sondern in der gesamten Textdatei.<br />

<strong>Das</strong> Identifizieren eindeutiger Werte kann uns Python mit<br />

der dictionary-Klasse abnehmen. Diese Klasse speichert<br />

Schlüssel/Wert-Paare und legt fest, dass jeder Schlüssel nur<br />

ein einziges Mal vorkommen darf. Wenn wir also Wörter als<br />

dictionary-Schlüssel verwenden, eliminieren wir garantiert<br />

alle Duplikate.<br />

Außerdem können wir das dictionary verwenden, um die<br />

Häufigkeit eines Worts zu speichern, indem wir den Wert des<br />

jeweiligen Eintrags bei jedem Wortvorkommen um 1 erhöhen.<br />

Wir erstellen also ein leeres dictionary. Da es für die<br />

gesamte Textdatei gültig sein soll, machen wir dies außerhalb<br />

der for-Schleife:<br />

dict = {}<br />

Nun brauchen wir eine Methode, die jedes einzelne Wort<br />

im dictionary speichert. Hierzu reicht eine einfache<br />

Zuweisung aus, also könnten wir mit einer weiteren<br />

for-Schleife über unsere Wortliste iterieren und dem dictionary<br />

jedes Wort als Schlüssel und 1 als Wert (da das Wort ja<br />

einmal vorkam) zuzuweisen:<br />

for word in list:<br />

dict[word] = 1<br />

Ärgerlicherweise wird – falls dieser Schlüssel bereits existierte<br />

– der alte Wert einfach überschrieben. Um stattdessen<br />

diesen Wert zu erhöhen, bauen wir eine if-else-Verzweigung<br />

in die Schleife ein:<br />

if word in dict:<br />

count = dict[word]<br />

count += 1<br />

dict[word] = count<br />

else:<br />

dict[word] = 1<br />

In diesem Code wird dict[word] auf zwei verschiedene<br />

Weisen verwendet. In der zweiten Zeile gibt es den dictionary-Wert<br />

zurück und weist ihn der Variable count zu. In der<br />

vierten und sechsten Zeile wird hingegen dem dictionary-Wert<br />

der Variablenwert von count bzw 1 zugewiesen.<br />

Die dritte Zeile ist einfacher: Wenn ein Wort bereits im dictionary<br />

enthalten ist, dann wird dessen bisherige Häufigkeit<br />

um 1 erhöht.<br />

Zusammenführen<br />

Aus der Sicht eines Computers haben wir damit unser Ziel<br />

erreicht: Die Wörter sind eingelesen, identifiziert und gezählt.<br />

Um aber auch dem Benutzer das Ergebnis unserer Mühen zu<br />

präsentieren, benötigen wir noch eine Ausgaberoutine. Der<br />

print-Abschnitt sollte am Ende des bisherigen Codes außerhalb<br />

jeder Schleife stehen und in etwa folgendermaßen aussehen:<br />

for word,count in dict.iteritems():<br />

print word + “: “ + str(count)<br />

Diese for-Schleife unterscheidet sich von den bisher kennengelernten<br />

Schleifen. Indem wir die iteritems-Funktion<br />

verwenden, erhalten wir gleichzeitig Zugriff auf den Schlüssel<br />

(word) und auf den Wert (count) des aktuellen dictionary-Eintrags.<br />

Außerdem verwenden wir die str()-Funktion,<br />

um den Ganzzahlwert count in einen String zu konvertieren.<br />

Der Grund dafür ist der +-Operator, der Ganzzahlen und<br />

Strings nicht miteinander verknüpfen kann.<br />

Wenn Sie nun das Programm starten, dann sollten Sie so<br />

etwas auf dem Bildschirm sehen:<br />

...<br />

other: 20<br />

sick: 2<br />

ventilating: 2<br />

...<br />

Daten? Verarbeiten!<br />

Wir haben gesehen, wie einige Datentypen und deren<br />

Funktionen eingesetzt werden, um praxisnahe Aufgaben zu<br />

lösen. Außerdem haben wir gezeigt, wie wichtig die richtige<br />

Auswahl des Datentyps für das Erreichen des Ziels ist.<br />

So hatten wir zunächst einen String für jede Textzeile,<br />

dann speicherten wir jedes Wort in einer Liste und schließlich<br />

speicherten wir jedes eindeutige Wort in einem dictionary.<br />

<strong>Das</strong> Programm lässt sich natürlich verbessern.<br />

Beispielsweise könnte man die Worte nach Häufigkeit sortieren.<br />

Und man könnte den Benutzer nach einem Wort suchen<br />

lassen.<br />

In der<br />

Dokumentation<br />

von Pythons<br />

Standard-<br />

Bibliothek,<br />

http://docs.<br />

python.org/<br />

library lassen<br />

sich selten<br />

genutzte<br />

Funktionen<br />

und deren<br />

Anwendung<br />

entdecken.<br />

103


Coding<br />

Designkonzepte:<br />

Abstraktion<br />

Abstraktion macht Ihren Code robuster, wiederverwendbar<br />

und wartungsfreundlicher.<br />

Hat man eine Programmidee, dann geht es meist darum,<br />

mit welchen Daten man zu einem bestimmten<br />

Ergebnis gelangt. Auf welche Weise die Daten verarbeitet<br />

werden, spielt anfangs keine Rolle – was später zu<br />

unlesbarem Code und unbehebbaren Fehlern führt. In diesem<br />

Tutorial betrachten wir daher die Technik der<br />

Abstraktion. Zunächst geht es um die Abstraktion im<br />

Allgemeinen, dann um ihren Einfluss auf das Programmieren<br />

von Methoden.<br />

Quadratwurzeln<br />

Um das Konzept der Abstraktion zu verstehen, betrachten<br />

wir Quadratwurzeln und die unterschiedlichen Ansätze für<br />

deren Berechnung. Ein Ansatz wurde von Newton entwickelt<br />

und ist daher als das Newton-Verfahren bekannt.<br />

Es besagt, dass wir zur Bestimmung der Quadratwurzel<br />

der Zahl (x) mit einem geschätzten Wert (y) dieser Wurzel<br />

beginnen. Wir verbessern dann diesen Wert (y) mit dem<br />

Mittelwert von (y) und dem Ergebnis der Division von (x) und<br />

(y). Wenn wir diesen Vorgang wiederholen, dann nähert sich<br />

der errechnete Wert immer mehr dem tatsächlichen Wert an.<br />

Meist werden wir kein finales Ergebnis erhalten, aber die<br />

Näherung wird besser und besser. Irgendwann werden wir<br />

eine Genauigkeit erreicht haben, die für unseren Zweck ausreicht.<br />

Um das Verfahren besser zu verstehen, werfen Sie<br />

einen Blick auf die Tabelle,<br />

die ein Beispiel für die<br />

Quadratwurzel von 2 zeigt.<br />

Diese Verfahren bedeutet<br />

eine Menge Rechenarbeit,<br />

nur um eine Quadratwurzel<br />

zu bestimmen. Stellen Sie<br />

sich vor, dass Sie diese Methode jedes Mal angewandt hätten,<br />

wenn Sie im Mathematikunterricht eine Quadratwurzel<br />

benötigten. Den Satz des Pythagoras hätten Sie vermutlich<br />

weitaus seltener genutzt.<br />

Glücklicherweise wurden ab einem bestimmten Zeitpunkt<br />

Taschenrechner in den Schulen erlaubt und die Berechnung<br />

Newtons Verfahren<br />

Näherung (y) Division (x/y) Mittelwert (((x/y) + y)/2)<br />

1 2/1 = 2 (2 + 1)/2 = 1.5<br />

1.5 2/1.5 = 1.33 (1.33 + 1.5)/2 = 1.4167<br />

1.4167 2/1.4167 = 1.4118 (1.4118 + 1.4167)/2 = 1.4142<br />

„Die Technik verbirgt die<br />

Komplexität der Gesamtaufgabe<br />

vor uns.“<br />

einer Quadratwurzel war mit einem einzigen Tastendruck erledigt.<br />

Beide Ansätze führten zum gleichen Ergebnis – und<br />

genau das ist Abstraktion. Wenn wir ein Problem wie beispielsweise<br />

den Satz des Pythagoras lösen müssen, dann ist es uns<br />

vollkommen egal, wie eine Quadratwurzel berechnet wird. Uns<br />

ist wichtig, DASS eine Quadratwurzel berechnet wird. So gesehen<br />

ist die Wurzeltaste des Taschenrechners eine Blackbox:<br />

Wir sehen nie hinein und wir kennen den Inhalt nicht, aber wir<br />

verlassen uns darauf, dass sie das korrekte Ergebnis liefert.<br />

Diese Sichtweise ist ein wertvoller Ansatz beim<br />

Programmieren, da er die Komplexität der Gesamtaufgabe vor<br />

uns verbirgt. Um zu zeigen, wie Abstraktion die Entwicklung<br />

vereinfacht, betrachten wir folgenden Python-Code. Er<br />

bestimmt die Hypotenuse eines rechtwinkligen Dreiecks:<br />

import math<br />

def pythag(a, b):<br />

a2b2 = (a * a) + (b * b)<br />

guess = 1.0<br />

while (math.fabs((guess * guess) - a2b2) > 0.01):<br />

guess = (((a2b2 / guess) + guess) / 2)<br />

return guess<br />

Als Erstes wird Ihnen auffallen, dass der Code kaum lesbar<br />

ist. Zwar ist er kurz genug, dass man sich hindurcharbeiten<br />

könnte, aber auf den ersten Blick ist der Zweck dieser Zeilen<br />

nicht zu erkennen. Schlimmer noch: Diesen Code auf logische<br />

oder programmatische Fehler zu testen<br />

ist nahezu unmöglich. Und sollte<br />

doch ein Fehler auftreten, dann hilft<br />

nur die Neuerstellung der gesamten<br />

Funktion.<br />

Wie würden Sie beispielsweise<br />

diesen Code daraufhin testen, ob<br />

eine Näherung ausreichend gut ist? Wie würden Sie den Code<br />

identifizieren, der die Näherung verbessert? Was wäre, wenn<br />

der Code nicht die gewünschten Ergebnisse liefert – wo würden<br />

Sie beginnen, nach dem Fehler zu suchen?<br />

Außerdem findet sich in dieser Funktion Code, der auch an<br />

anderer Stelle nützlich sein könnte – beispielsweise wenn wir<br />

eine Quadratwurzel berechnen möchten oder wenn wir den<br />

Mittelwert zweier Zahlen benötigen. Nichts davon ist wiederverwendbar,<br />

da es in der Funktion verborgen ist. Wenn wir die<br />

jeweiligen Codeteile an andere Stellen kopieren, dann vergrößern<br />

wir die Codemenge und kopieren möglicherweise enthaltene<br />

Programmfehler, die wir vermutlich nie mehr beheben<br />

können.<br />

Also schreiben wir den Code erneut, diesmal sollen aber<br />

einige Abstraktionen die eben genannten Probleme vermeiden.<br />

Im Folgenden sind nur die Definitionen einiger Hilfsfunktionen<br />

aufgeführt, den jeweiligen Code dürfen Sie selbst eingeben:<br />

104


Coding<br />

„Der Scope bestimmt<br />

den Gültigkeitsbereich<br />

einzelner Elemente.“<br />

import math:<br />

def square(x):<br />

...<br />

def closeEnough(x, guess):<br />

...<br />

def improveGuess(x, guess):<br />

...<br />

def sqrt(x, guess):<br />

...<br />

def pythag(a, b):<br />

a2b2 = square(a) + square(b)<br />

return sqrt(a2b2)<br />

Wir haben den Code in mehrere kleine Funktionen aufgeteilt,<br />

die jeweils eine eigene, exakt definierte Aufgabe erfüllen.<br />

Dies hat mehrere Vorteile: Beispielsweise ist die<br />

pythag()-Funktion nun sehr einfach zu lesen und zu verstehen.<br />

In der ersten Zeile steht sehr deutlich, dass a2b2 die<br />

Summe zweier Quadratzahlen ist. Die zweite Zeile sagt ebenso<br />

klar, dass die Funktion die Wurzel dieser Summe zurückgibt.<br />

Darüber hinaus können wir den Code, da er nun in einzelne<br />

Funktionen aufgebrochen ist, sehr einfach testen. Um beispielsweise<br />

herauszufinden, ob improveGuess() sinnvolle<br />

Werte liefert, übergeben wir der Funktion einfach einige<br />

Werte für x und guess und überprüfen das Ergebnis von<br />

Hand.<br />

Und wenn die pythag()-Funktion nicht das gewünschte<br />

Ergebnis liefert, dann müssen wir zwar all die verschiedenen<br />

Hilfsfunktionen einzeln auf Fehler testen, deren einfacher<br />

Aufbau macht dies aber zum Kinderspiel.<br />

Ein weiterer Vorteil dieses Ansatzes ist die<br />

Wiederverwendbarkeit. Jede dieser Funktionen kann auch<br />

von anderen Programmstellen aufgerufen werden, die damit<br />

ihrerseits lesbarer werden. Wenn beispielsweise eine andere<br />

Funktion die Quadratwurzel einer Zahl ermitteln soll, dann<br />

ruft sie einfach sqrt() auf: sechs einfache Buchstaben anstelle<br />

von vier Programmzeilen, in denen sich Fehler eingeschlichen<br />

haben könnten.<br />

Ein letzter Vorteil der Abstraktion: Da die Ermittlung der<br />

Quadratwurzel nur noch in einer einzigen Funktion geschieht,<br />

könnten wir den verwendeten Rechenweg komplett ersetzen.<br />

Sofern wir die Funktion weiterhin sqrt nennen und diese<br />

Funktion exakt ein Argument hat, müssen wir die aufrufenden<br />

Programmteile nicht verändern und sie würden dennoch<br />

Abstraktion<br />

Java<br />

All unsere Tätigkeiten auf einem Computer durchqueren<br />

zahllose Abstraktionsschichten.<br />

C<br />

Assembler<br />

Objectcode<br />

wie erwartet funktionieren.<br />

Sollte Ihnen also eine effizientere Methode zur Berechnung<br />

einer Quadratwurzel einfallen, müssen Sie sich nicht durch<br />

Tausende Codezeilen hindurcharbeiten und jeden Abschnitt<br />

verändern, der sich mit Quadratwurzeln beschäftigt. Sie<br />

ändern nur diese eine Methode und das gesamte Programm<br />

profitiert davon.<br />

Der Code kann noch weiter verbessert werden, indem man<br />

Pythons Scope-Konzept nutzt. Scope bestimmt den<br />

Gültigkeitsbereich einzelner Variablen (beispielsweise ist eine<br />

im Funktionsrumpf definierte Variable nur innerhalb dieser<br />

Funktion bekannt). Gleiches gilt auch für Funktionen: Da closeEnough()<br />

und improveGuess() sehr speziell sind und<br />

voraussichtlich nur für die sqrt()-Funktion genutzt werden,<br />

platzieren wir diese beiden Funktionen innerhalb der<br />

sqrt()-Funktion:<br />

def sqrt(x, guess):<br />

def closeEnough(x, guess):<br />

...<br />

def improveGuess(x, guess):<br />

...<br />

...<br />

Die zwei Funktionen sind nun nur noch für Code innerhalb<br />

der sqrt()-Definition sichtbar; sie befinden sich im Scope von<br />

sqrt(). Programmteile außerhalb von sqrt() wissen nichts von<br />

der Existenz der beiden Hilfsfunktionen.<br />

Abstraktionsschichten<br />

Dieses Beispiel hat gezeigt, wie hilfreich Abstraktion ist. Zwar<br />

bedeutet Abstraktion zunächst mehr Tipparbeit, diese macht<br />

sich bei der Fehlersuche aber schnell bezahlt.<br />

Was wissen Sie zum Beispiel darüber, wie Python<br />

Ganzzahlen im Arbeitsspeicher Ihres Computers ablegt? Oder<br />

wie die CPU arithmetische Operationen wie Addition und<br />

Subtraktion ausführt? Vermutlich ebenso wenig wie die meisten<br />

anderen Programmierer: nämlich nichts. Wir akzeptieren<br />

einfach, dass der Python-Interpreter nach der Eingabe von 2 +<br />

3 das richtige Ergebnis liefert.<br />

Der finale Code,<br />

mit dem wir die<br />

Hypotenuse<br />

eines rechtwinkligen<br />

Dreiecks<br />

bestimmen, ist<br />

länger als die<br />

erste Lösung.<br />

Aber er ist besser<br />

lesbar und<br />

robuster.<br />

105


Coding<br />

Designkonzepte:<br />

Dateien und Module<br />

Wussten Sie, dass Sie mit nur zwei Zeilen Python-Code eine<br />

Funktionsbibliothek erweitern und externe Daten lesen können?<br />

Die meisten<br />

Programmiersprachen<br />

laden<br />

Dateiinhalte nur<br />

häppchenweise<br />

ein. In diesem<br />

Beispiel lesen<br />

wir immer bis<br />

zum nächsten<br />

Zeilenumbruch.<br />

Mit den meisten Software-Projekten kommt man nicht<br />

allzu weit, bevor man sich der Frage stellen muss, wie<br />

denn all die Daten in die Anwendung gelangen. Ob es<br />

um Lochkarten geht, mit denen im 19. Jahrhundert die Webstühle<br />

gesteuert wurden, oder um Googles Robots, die Webseiten<br />

für die Suchmaschine auslesen, stets sind externe<br />

Daten ebenso wichtig wie das Programm selbst.<br />

Auch auf der Kommandozeile werden Sie Zeuge der<br />

Verarbeitung externer Daten: Wenn Sie beispielsweise ls eintippen,<br />

um sich den Inhalt<br />

„<strong>Das</strong> System verhindert den<br />

Zugriff, wenn eine Datei<br />

verändert wird.“<br />

des aktuellen Verzeichnisses<br />

anzeigen zu lassen, dann liest<br />

dieses Kommando den Inhalt<br />

einer Datei ein und gibt das<br />

Ergebnis in eine andere (das<br />

Terminal) aus.<br />

Zwar entspricht dies nicht dem klassischen Verständnis<br />

von externen Daten, ober so wurde das Linux-Dateisystem nun<br />

einmal konzipiert – nahezu alles ist eine Datei. Diese<br />

Sichtweise vereinfacht es, das Ergebnis eines Kommandos zu<br />

speichern oder das Ergebnis als Input eines weiteren<br />

Kommandos zu verwenden.<br />

Beispielsweise leitet ls >list.txt die Ausgabe des<br />

Kommandos in eine Datei namens list.txt um. Die Ausgabe<br />

selbst kann ebenfalls wie eine Datei behandelt werden: ls |<br />

sort –r leitet das Ergebnis von ls direkt als Eingabe an das<br />

sort-Kommando um und erstellt eine alphabetisch sortierte<br />

Liste des Verzeichnisinhalts. Der vertikale Balken nennt sich<br />

<strong>Pi</strong>pe, englisch für Rohrleitung. Wie weit dieses Konzept in der<br />

Praxis geht, hängt von Ihrem System ab. Zwar bietet jede<br />

Programmiersprache Funktionen zum Laden und Speichern<br />

von Dateien, wie hoch der notwendige Programmieraufwand<br />

aber tatsächlich ist, ist sehr unterschiedlich. Lediglich die<br />

Reihenfolge der Operationen ist stets dieselbe: Zuerst wird<br />

eine Datei geöffnet oder erstellt. Dann wird in diese Datei<br />

geschrieben oder aus ihr gelesen<br />

und schließlich muss die<br />

Datei explizit geschlossen werden,<br />

damit sie anderen<br />

Prozessen zur Verfügung steht.<br />

Die meisten Sprachen verlangen<br />

nach der Angabe des<br />

Zugriffsmodus, da dieser dem Dateisystem verrät, ob<br />

Änderungen am Inhalt zu erwarten sind. Auf diese Weise<br />

können mehrere Prozesse gleichzeitig eine Datei lesen, wenn<br />

keine Änderung droht. Wenn aber ein Prozess in die Datei<br />

schreiben möchte, dann erhält dieser meist exklusiven<br />

Zugriff. Bei Datenbank ist der gleichzeitige Zugriff auf die<br />

Tabellen und Zellen sehr ähnlich geregelt.<br />

In Python – wie in den meisten anderen Sprachen auch<br />

– wird eine Datei zum Lesen mit einem Einzeiler geöffnet:<br />

>>> f = open(“list.txt”, “r”)<br />

Wenn die Datei nicht existiert, dann quittiert Python dies<br />

mit einem „No such file or directory“-Fehler. Um dies zu vermeiden,<br />

haben wir die Ausgabe unseres Kommandozeilenbeispiels<br />

in die Datei namens list.txt gespeichert. Sie liegt in<br />

dem Verzeichnis, von dem aus wir den Python-Interpreter<br />

gestartet haben..<br />

Umgebungsvariablen<br />

Wo genau eine Datei gesucht bzw. gespeichert wird, kann<br />

schnell eine unübersichtliche Angelegenheit werden. Denn<br />

jedes System hat seine eigene Strategie, das „aktuelle“<br />

Verzeichnis zu bestimmen: mal ist es das zuletzt genutzte<br />

Verzeichnis, mal das Programmverzeichnis und mal ist es<br />

das Benutzerverzeichnis. <strong>Das</strong> wäre nicht weiter schlimm,<br />

wenn es nur um Dateien ginge, die Ihr Programm selbst<br />

erzeugt hat. Wenn es sich aber um Konfigurationsdateien<br />

oder Dateisymbole handelt, dann ist deren Verzeichnis nur<br />

schwer zu bestimmen. Auch auf Python kann man sich hier<br />

nicht verlassen, da diese Sprache auf vielen Plattformen läuft<br />

und sich den jeweiligen Gegebenheiten anpasst. Die Lösung<br />

dieses Problems heißt Umgebungsvariable.<br />

Diese kann man sich wie globale Variable vorstellen, nur<br />

dass sie nicht im Programmcode definiert werden, sondern<br />

106


Coding<br />

in der Linux-Sitzung eines einzelnen Benutzers. Wenn Sie auf<br />

der Kommandozeile env eintippen, dann sehen Sie alle<br />

Umgebungsvariablen, die für Ihre Terminalsitzung definiert<br />

wurden. Bei genauem Hinsehen zeigt sich, dass einige<br />

Variablen auf Verzeichnisse zeigen; insbesondere ist uns an<br />

dieser Stelle HOME wichtig. Der Wert dieser Variable entspricht<br />

dem Ihnen auf diesem Rechner zugewiesenen, persönlichen<br />

Home-Verzeichnis. Um diese Variable in einem<br />

Python-Programm zu verwenden, müssen wir betriebssystemspezifische<br />

Funktionen importieren:<br />

import os<br />

Solche Importe heißen in Python-Module und fügen der<br />

Programmiersprache zusätzliche Funktionen, Klassen und<br />

Definitionen hinzu. Module erweitern die meist sehr einfachen<br />

Schlüsselworte und Funktionen einer Programmiersprache<br />

um komplexere Elemente, die oftmals einem<br />

bestimmten Einsatzzweck dienen. In anderen<br />

Programmiersprachen heißen Module Bibliothek oder<br />

Assembly. Mit Modulen kopiert man eigentlich den<br />

Programmcode anderer Leute in ein eigenes Projekt – das<br />

ist im Normalfall kein Diebstahl geistigen Eigentums, sondern<br />

ist erwünscht und hilft, dass nicht jeder Programmierer<br />

das Rad neu erfinden muss. Da Module wie os von nahezu<br />

jedem Python-Programm verwendet werden, setzen sie<br />

sogar weltweite Standards.<br />

Standards setzen<br />

Es gibt Bibliotheken namens std, die einer Programmiersprache<br />

all die grundlegenden Funktionen unterschieben, die<br />

die Sprache nicht selbst bereitstellt: mathematische<br />

Funktionen, Datentypen, String-Bearbeitung und Input/<br />

Output für spezielle Dateitypen. Meist listet eine Dokumentationsdatei<br />

auf, welche Funktionen eine Bibliothek enthält,<br />

welche Argumente diese erwarten und welche Werte sie<br />

zurückgeben. Oftmals findet sich sogar der Quellcode dieser<br />

Bibliotheken. Auf den meisten Linux-Systemen enthält beispielsweise<br />

das Verzeichnis /lib/python2.x sämtliche<br />

Module. Wenn Sie die Datei os.py in einen Texteditor laden,<br />

dann sehen Sie den Code, den Sie soeben Ihrem Projekt hinzugefügt<br />

haben, und außerdem, welche Funktionen Ihnen<br />

nun zur Verfügung stehen. Oftmals steht am Anfang einer<br />

solchen Datei, ob und unter welchen Umständen Sie das<br />

Modul verwenden und weitergeben dürfen.<br />

Python liefert zahllose<br />

Module für jeden denkbaren<br />

Verwendungszweck mit – und<br />

mit wenigen Mausklicks im<br />

Paketmanager lassen sich<br />

Hunderte weitere nachinstallieren.<br />

An dieser Stelle sei jedoch<br />

vor dem hässlichen Haupt der Modul-Abhängigkeiten<br />

gewarnt: Wenn Ihr Code auf einem Modul basiert, dann müssen<br />

Sie dieses Modul auf jedem Rechner installieren, auf dem<br />

Ihr Programm laufen soll. Und wenn dieses Modul seinerseits<br />

auf weiteren Modulen basiert … Gleiches gilt übrigens ebenfalls<br />

für C oder C++: Auch in solch kompilierten Sprachen linkt<br />

der Programmcode gegen Bibliotheken, die bei Auslieferung<br />

des Programms mitgeliefert werden müssen. Paketmanager<br />

helfen dabei, solche Installationsprobleme zu meistern.<br />

<strong>Das</strong> os-Modul<br />

Zurück zu unserem Projekt. <strong>Das</strong> os-Modul dient dem Zweck,<br />

einen plattformunabhängigen Zugriff auf plattformspezifische<br />

Elemente zu haben. In unserem konkreten Fall wollen<br />

wir eine Datei an „der richtigen Stelle“ finden. Was wir damit<br />

„Wenn Sie os.py in einen<br />

Editor laden, sehen Sie den<br />

hinzugefügten Code.“<br />

meinen, wird mit folgender Zeile klar:<br />

f = open(os.environ[“HOME”]+”/list.txt”,”r”)<br />

Diese Zeile öffnet die Datei file.txt in Ihrem Home-<br />

Verzeichnis. Python weiß, welches Home-Verzeichnis Ihnen<br />

gehört, da die os.environ-Funktion aus dem os-Modul denjenigen<br />

String liefert, welcher dem Wert der genannten<br />

Umgebungsvariablen entspricht – in unserem Fall HOME.<br />

Nachdem wir die Datei nun geöffnet haben, können wir<br />

deren Inhalt auslesen:<br />

f.readline()<br />

Dieser Code liest eine einzelne Zeile aus der Textdatei und<br />

zeigt sie an. Da sich Python merkt, an welcher Stelle innerhalb<br />

der Datei diese Zeile endete, liest ein erneuter Aufruf<br />

dieses Codes eine weitere Textzeile ein. Auch dies hat Python<br />

mit nahezu allen anderen Sprachen gemein.<br />

Wenn Sie hingegen den kompletten Dateiinhalt lesen möchten,<br />

dann verwenden Sie f.read(). Da es sich in unserem<br />

Beispiel um eine Textdatei handelt, lässt sich der Dateiinhalt<br />

problemlos in einen String umwandeln. Dies gilt allerdings<br />

nicht für binäre Dateien: In diesen sind die Bits und Bytes<br />

durch den Datentyp bestimmt, der hier abgespeichert wurde.<br />

Es ergibt daher keinen<br />

Sinn, eine solche Datei in<br />

einem Texteditor zu öffnen<br />

oder mit f.readline() zu<br />

lesen – meist endet der<br />

Versuch mit einer<br />

Fehlermeldung. Die Lösung<br />

in diesem Fall ist, dem Dateimodus ein b hinzuzufügen. So<br />

wird Python gewarnt, dass binäre Daten zu erwarten sind,<br />

und ein f.readline() zeigt Ihnen die hexadezimalen Werte<br />

des Dateiinhalts an.<br />

Um auch solche Daten sinnvoll einzusetzen, ist etwas<br />

Mehrarbeit notwendig. Um beispielsweise ein jpg-Bild anzuzeigen,<br />

müssen Sie sich zunächst in das Dateiformat einlesen,<br />

die komprimierten Daten in ein unkomprimiertes Bitmap<br />

schreiben und schließlich die einzelnen <strong>Pi</strong>xel auf den<br />

Bildschirm malen. Für dieses Tutorial wollen wir es aber<br />

dabei belassen, die Datei noch ordentlich zu schließen und<br />

damit die Datenintegrität zu gewährleisten:<br />

f.close<br />

Nun, da Sie auch mit Dateien arbeiten können, sind Sie mit<br />

Ihren Code-Experimenten flexibler als je zuvor.<br />

Binäre Dateien<br />

haben ohne<br />

bekannten<br />

Datentyp und<br />

ohne Verarbeitungsmethoden<br />

keinen Sinn.<br />

Daher sehen Sie<br />

die einzelnen<br />

Bytewerte,<br />

wenn Sie ein<br />

Bild in unserem<br />

Programm<br />

öffnen.<br />

107


Coding<br />

Python: So fangen<br />

Alle Abenteuer mit dem <strong>Raspberry</strong> <strong>Pi</strong> starten mit einer einzelnen Codezeile.<br />

Und genau damit wollen wir hier beginnen.<br />

Python-Programme<br />

können Sie auf<br />

unterschiedliche<br />

Weisen laufen<br />

lassen: direkt vom<br />

Interpreter, durch<br />

Aufruf der Python-<br />

Anwendung oder<br />

durch Hinzufügen<br />

eines Shebang zu<br />

einer Skriptdatei.<br />

Der <strong>Raspberry</strong> <strong>Pi</strong> wurde hauptsächlich als Bildungsinstrument<br />

entwickelt. Aber das wichtigste pädagogische Ziel<br />

war nicht das Betriebssystem oder die <strong>Hardware</strong>, sondern<br />

die Produktion einer billigen und leicht zugänglichen Plattform<br />

für die Programmierung. Die <strong>Pi</strong>-Erfinder liebten an den<br />

Heimcomputern der 1980er Jahre, dass man sie einschalten<br />

und sofort Code eingeben konnte, ohne vorher irgendetwas installieren<br />

zu müssen. Man konnte ohne Umschweife mit dem<br />

System herumexperimentieren und dadurch viel über das<br />

Programmieren und die Funktionsweise des Computers lernen.<br />

Wenn Sie Zugriff auf das Innerste Ihrer Maschine erhalten<br />

möchten, stellt Programmieren die beste Methode dar.<br />

Moderne Computer arbeiten nicht mehr in der gleichen<br />

Weise. Hier haben Betriebssysteme und Befehlszeilen die BA-<br />

SIC-Interpreter der alten Maschinen ersetzt. Aber Programmierung<br />

ist auch heute noch der beste Weg, etwas über Ihren<br />

Rechner zu erfahren, und was vielleicht noch wichtiger ist, es ist<br />

eine der besten Möglichkeiten, Kompetenzen zu erlangen, die<br />

auf fast alle Plattformen, Systeme und Programmiersprachen<br />

übertragen werden können. Außerdem benötigen Sie keine besondere<br />

Erfahrung, um anzufangen. Weil die meisten Anweisungen,<br />

die wir verwenden, über die Befehlszeile eingegeben werden,<br />

ist es sinnvoll, sich als Erstes mit dieser vertraut zu<br />

machen. Es hilft, wenn Sie wissen, wie Programmiersprachen<br />

arbeiten, aber selbst dann ist der beste Weg zu lernen, ins<br />

kalte Wasser zu springen.<br />

Die offizielle Programmiersprache des <strong>Raspberry</strong> <strong>Pi</strong> heißt<br />

Python. Dies ist eine fest etablierte Sprache, die bereits von<br />

Millionen Entwicklern benutzt wird. Python wurde für den <strong>Raspberry</strong><br />

<strong>Pi</strong> in erster Linie deshalb ausgewählt, weil es einfach zu<br />

lernen und ideal zum Experimentieren geeignet ist. Aber diese<br />

Programmiersprache ist auch eine mächtiges Werkzeug, das für<br />

viele ambitionierte Projekte bei Google und vielen neuen Technologien<br />

eingesetzt wird. Python ist überdies plattformunabhängig<br />

und beinhaltet die gleichen Konzepte und Paradigmen wie<br />

fast jede andere Programmiersprache. Wenn Sie sich also<br />

näher mit Python beschäftigen, wird Ihnen dies nicht nur helfen,<br />

das Maximum aus Ihrem <strong>Raspberry</strong> <strong>Pi</strong> herauszuholen, sondern<br />

es kann Ihnen auch die Welt des Computers eröffnen, so wie<br />

das 1983 die alten 8-Bit-Maschinen taten.<br />

Python-Grundlagen<br />

Python ist bereits auf Ihrem <strong>Raspberry</strong> <strong>Pi</strong> installiert, aber Sie<br />

können es auch auf jeder anderen Maschine, die Sie besitzen,<br />

installieren. Es gibt Versionen für Windows, OS X und Linux<br />

sowie für weitere Systeme. Sie können testen, ob Python bereits<br />

installiert ist, indem Sie ein Terminalfenster öffnen und<br />

das Wort python eingeben. Wenn alles funktioniert, sehen Sie<br />

ein paar Zeilen Ausgabe, die mit der Zeichenkette >>> beginnen.<br />

Es handelt sich um den Python-Interpreter und damit um<br />

das, was Python zu einer solch guten Sprache macht. Vielleicht<br />

wissen Sie noch nicht, was ein Interpreter überhaupt ist, doch<br />

das ist schnell erklärt: Alles, was er im Grunde macht, ist, Ihre<br />

Eingaben zu übersetzen und ihre eingegebenen Wörter in<br />

Aktionen umzuwandeln. Geben Sie zum Beispiel print(“Hello<br />

world!”) ein. Sobald sie die Enter-Taste gedrückt haben, wird<br />

der Python-Interpreter Ihre Eingabe decodieren und entsprechend<br />

Ihrem Kommando den Text „Hello world!“ anzeigen.<br />

Allerdings besitzen die meisten Programmiersprachen keinen<br />

Interpreter mehr. Stattdessen schreiben Sie die Anweisungen in<br />

eine Datei und benutzten ein anderes Kommando, um Ihren<br />

Code in die Aktionen umzusetzen, die Sie benötigen. Mit Python<br />

können Sie dies ebenfalls tun. Geben Sie quit() ein, um den Interpreter<br />

zu beenden, und öffnen Sie anschließend einen Texteditor.<br />

Einen einfach zu bedienenden Editor namens Nano<br />

108


Coding<br />

Sie an<br />

können Sie aus der Kommandozeile heraus aufrufen. Wenn Sie<br />

beispielsweise nano hello.py eingeben, wird Nano geöffnet, eine<br />

Textdatei mit dem Namen hello.py kreiert und der Cursor an<br />

oberster Stelle in der Datei platziert, sodass Sie direkt mit der<br />

Eingabe beginnen können. Schreiben Sie nun wieder<br />

print(“Hello world!”) und drücken Sie Steuerung + X. Sie werden<br />

gefragt, ob Sie die Datei speichern wollen, und beantworten<br />

dies mit Y. Sie haben damit eine neue Quelldatei erstellt,<br />

deren Inhalt Sie mit der Eingabe python hello.py ausführen<br />

können.<br />

Die Endung .py der Datei ist nur dazu da, dass Sie wissen,<br />

dass es sich um Python-Code handelt, und wird sonst nicht von<br />

Linux verwendet. Wenn Sie der Kommandozeile mitteilen möchten,<br />

dass es sich um Python-Code handelt, können Sie einen<br />

sogenannten Shebang (die Zeichenkombination !#) verwenden.<br />

Für Python sieht die Shebang-Zeile folgendermaßen aus, und<br />

Sie fügen ihn in die erste Zeile Ihrer Quelldatei ein:<br />

#!/usr/bin/python. Danach geben Sie chmod +x hello.py ein<br />

und können Ihre Datei ohne weitere Kommandos öffnen.<br />

Geben Sie einfach ./hello.py ein, um das Skript aufzurufen.<br />

Es ist nützlich, wenn Sie mit der Kommandozeile umgehen<br />

können, da diese einen guten Überblick bietet und einfach zu<br />

benutzen ist. Es gibt allerdings eine bequemere Möglichkeit der<br />

Befehlseingabe, nämlich die sogenannte Entwicklungsumgebung.<br />

Im Grunde handelt es sich dabei um nichts anderes als<br />

einen aufgemotzten Texteditor. Es gibt stets einen Bereich für<br />

die Eingabe von Text, aber häufig auch noch Bereiche für spezielle<br />

Features, die die Programmiersprache, in der Sie entwickeln,<br />

mitbringt. Zum Betriebssystem Raspbian gehört eine integrierte<br />

Entwicklungsumgebung (IDE) namens IDLE. Sie sollten<br />

ruhig ein bisschen damit herumprobieren, um herauszufinden,<br />

ob IDLE Ihre bevorzugte Entwicklungsumgebung werden könnte.<br />

IDLE startet im interaktiven Modus, deren große Vorteile darin<br />

bestehen, dass der eingegebene Code gemäß den unterschiedlichen<br />

Arten von Anweisungen spezifisch hervorgehoben wird,<br />

dass Pop-ups Informationen zu den bei Python verwendeten Objekten,<br />

Variablen und Methoden liefern und dass alle Einrückungen<br />

automatisch vorgenommen werden. Geben Sie beispielsweise<br />

zunächst value = 1 in IDLE ein und danach value., dann<br />

erscheint ein Menü, das Ihnen die möglichen Methoden zu der<br />

Variablen liefert.<br />

Anweisungen<br />

Nun da wir die Grundlagen von Python-Skripten kennengelernt<br />

haben, ist es an der Zeit, sich die Sprache selbst etwas<br />

genauer anzusehen. Wir haben bereits den Befehl print<br />

(“Hello world!”) ausgeführt, und dieser sagt uns schon viel<br />

über das Programmieren in Python. Vorn steht die Anweisung<br />

print. Anweisungen sind Wörter mit einer vordefinierten Bedeutung<br />

in Python, insgesamt gibt es nur einige wenige davon. Die<br />

Vorschrift print nimmt wie gesehen den in Klammern und Anführungszeichen<br />

stehenden Wert und übergibt ihn an das Standard-Ausgabegerät,<br />

was in den meisten Fällen der Bildschirm<br />

sein wird. Dies ist ein Beispiel für etwas, das Funktion genannt<br />

wird, und alles, was dabei geschieht, ist, dass Daten an einen<br />

anderen Teil des Codes übergeben und von diesem bearbeitet<br />

werden. print ist eine der wenigen in Python vorab definierten<br />

Anweisungen – gewöhnlich schreibt man eigene Anweisungen<br />

oder übernimmt welche von anderen Programmierern. Würden<br />

wir unsere „Hello world!“-Zeile in eine Funktion umwandeln,<br />

sähe diese folgendermaßen aus:<br />

def helloworld():<br />

print(“Hello world!”)<br />

return<br />

Geben Sie dies doch einmal direkt in den Interpreter ein,<br />

dann können Sie sofort mit der Ausgabe experimentieren. Bei<br />

dem oben angegebenen Text sehen Sie außerdem etwas, das<br />

Sie unbedingt beherzigen sollten, nämlich die Einrückung von<br />

Codezeilen. Die erste Zeile – in der die Funktion definiert wird –<br />

beginnt am linken Rand, und alle weiteren Zeilen der Funktion<br />

werden mit der Tab-Taste (oder mittels Leerzeichen) eingerückt.<br />

<strong>Das</strong> erleichtert die Lesbarkeit des Codes ungemein und erlaubt<br />

es dem Programmierer, auf einen Blick zu sehen, wo ein Block<br />

beginnt und endet. Wenn Sie nun helloworld() in eine neue<br />

Zeile tippen, sehen Sie die Ausgabe der soeben erstellten Funktion.<br />

Sie haben nun Ihren ersten logischen Block Code<br />

geschrieben!<br />

Bedingte Anweisungen<br />

Wenn Sie bisher noch nie programmiert haben, fragen Sie sich<br />

vielleicht, wie Sie die Logik in Ihrem Code aufbauen sollen.<br />

Dazu gibt es viele Möglichkeiten, doch die einfachste ist es,<br />

sich an die Reihenfolge zu halten, in der Bedingungen durchlaufen<br />

werden. Damit ist der Ablauf von Anweisungen zu einem<br />

Entscheidungspunkt, der von dem Zustand eines Parameters<br />

abhängt, gemeint. Der Ablauf kann in verschiedene Richtungen<br />

weitergehen. Der Grundstein für eine Bedingung ist if:<br />

Integrierte<br />

Entwicklungsumgebungen<br />

wie<br />

IDLE sind im<br />

Grunde Texteditoren<br />

mit<br />

<strong>erweiterte</strong>m<br />

Funktionsumfang.<br />

109


Coding<br />

if something == 1:<br />

print(“It’s true!”)<br />

<strong>Das</strong> ist das korrekte Format einer if-Anweisung in Python.<br />

Hier gibt es einiges Neues, etwa das Wort something. Es<br />

handelt sich hierbei um eine Variable, ihr Name ist beliebig<br />

gewählt. Eine Variable beinhaltet einen – eben variierenden –<br />

Wert, und im Fall der if-Anweisung wird geprüft, ob der Inhalt der<br />

Variablen der Wert 1 ist. Wenn dies der Fall ist, wird die Zeile<br />

„It’s true!“ ausgegeben. Ist dies jedoch nicht der Fall, wird die<br />

print-Anweisung übersprungen. Variablen sind extrem wichtig,<br />

und im Gegensatz zu anderen Programmiersprachen müssen<br />

Sie in Python nicht einem vordefinierten Datentyp zugewiesen<br />

werden. Um den oben genannten Codeschnipsel laufen zu<br />

lassen, müssen wir something einen Wert zuweisen:<br />

something = 1<br />

Vielleicht fragen Sie sich, warum wir diesmal nur ein einfaches<br />

Gleichheitszeichen in der Zuweisung benutzt haben und<br />

nicht – wie bei der if-Bedingung – ein doppeltes. Dies liegt<br />

daran, dass die beiden Varianten unterschiedliche Aufgaben<br />

haben, die man gut auseinanderhalten sollte. <strong>Das</strong> doppelte<br />

Gleichheitszeichen ist ein Vergleichsoperator. Es gibt daneben<br />

noch weitere Operatoren dieser Sorte:<br />

< kleiner<br />

größer<br />

>= größer gleich<br />

== gleich<br />

!= ungleich<br />

Diese Operatoren können Sie benutzen, um den Wert einer<br />

Variablen zu überprüfen, während das einfache Gleichheitszeichen<br />

der Variablen einen Wert zuweist. Daher wird es Zuweisungsoperator<br />

genannt. <strong>Das</strong> = ist der häufigste Zuweisungsoperator,<br />

doch es gibt noch andere:<br />

+= Addition und Zuweisung<br />

-= Subtraktion und Zuweisung<br />

*= Multiplikation und Zuweisung<br />

/= Division und Zuweisung<br />

%= Zuweisung des Teilungsrestes<br />

Diese Operatoren erlauben es Ihnen, Werte in Parametern zu<br />

manipulieren, wie Sie es aus mathematischen Formeln kennen.<br />

Und genau wie in mathematischen Formeln können Sie Klammern<br />

verwenden, um die Operationen in genau der Reihenfolge<br />

ablaufen zu lassen, die Sie wünschen. Zum Beispiel:<br />

total = (10/2) * (20/10)<br />

Geben Sie print(total) ein, um sich das Ergebnis anzeigen zu<br />

lassen und zu sehen, wie es berechnet wurde. Es gibt noch<br />

viele weitere Operatoren, aber für die meisten Projekte werden<br />

diese nicht notwendig sein. Haben Sie bemerkt, dass wir ein<br />

weiteres wichtiges Konzept in dem Beispiel behandelt haben?<br />

Wir übergaben print einen Variablennamen und keinen Wert,<br />

und zudem war der Wert der Variablen eine Zahl und kein alphanumerisches<br />

Zeichen. print war trotzdem in der Lage, daraus<br />

eine sinnvolle Ausgabe zu erstellen.<br />

Die Fähigkeit, ein Argument in Klammern an eine Funktion zu<br />

übergeben, ist ebenfalls wichtig, und Sie können dies bei Ihren<br />

eigenen Funktionen genauso machen, indem Sie in der Funktionsdefinition<br />

einen Variablennamen in die Klammern schreiben.<br />

Um unsere „Hello world!“-Funktion vollständig allgemein zu halten,<br />

ändern wir sie folgendermaßen ab:<br />

def helloworld(message):<br />

print(message)<br />

return<br />

Wenn Sie nun helloword(“This is a test”) aufrufen, wird der<br />

Wert innerhalb der Klammern an die Variable „message“ innerhalb<br />

der Funktion übergeben und per print ausgegeben. Dank<br />

der print-Funktion in Python brauchen wir uns im Gegensatz zu<br />

Der for-Loop<br />

ist eine der am<br />

häufigsten vorkommenden<br />

Anweisungen.<br />

Ohne ihn<br />

kann man kaum<br />

ein Python-Skript<br />

schreiben.<br />

110


Coding<br />

Welche Python-Version habe ich?<br />

Es gibt zwei Versionen von Python, die weit<br />

verbreitet sind – Version 2 und Version 3 (auch<br />

bekannt als Python 3000) –, was zu Verwirrung<br />

führen kann. Die am häufigsten verwendete Version<br />

ist die ältere Version Python 2.x, die lange<br />

Zeit der Standard für alle Python-Entwicklungsprojekte<br />

war. <strong>Das</strong> ist auch die Version, die der<br />

<strong>Raspberry</strong> <strong>Pi</strong> standardmäßig verwendet. Sie<br />

können das überprüfen, indem Sie python in die<br />

Kommandozeile eingeben. Die erste Ausgabezeile<br />

sollte im Prinzip ungefähr so aussehen:<br />

Python 2.7.3rc2 (default, May 6 2012, 20:02:25)<br />

<strong>Das</strong> bedeutet in diesem Fall, dass Sie Python<br />

2.7.3 (release candidate 2) verwenden, was der<br />

letzte Stand des 2.x-Zweigs ist. Obgleich das<br />

Kommando python bei Raspbian zu dieser Version<br />

der Programmiersprache führt, ist Version 3 überraschenderweise<br />

ebenfalls standardmäßig installiert.<br />

Wenn Sie in die Kommandozeile lediglich<br />

pyth tippen und dann die Tab-Taste drücken,<br />

schlägt die Auto-Vervollständigung Ihnen alle<br />

weiteren möglichen Eingaben vor,<br />

etwa python2.7 und python3.2, die<br />

jeweils eine eigene Anwendungsdatei<br />

besitzen. Falls Sie Ihr Skript<br />

mit der neueren Python-Version<br />

starten möchten, geben Sie an<br />

dieser Stelle einfach python3.2<br />

ein. Analog dazu können Sie auf<br />

dem Raspbian-Desktop mit IDLE<br />

beziehungsweise IDLE3 auswählen,<br />

ob sie die Entwicklungsumgebung<br />

für Python 2.7 oder Phython 3<br />

verwenden möchten. Zumindest<br />

am Anfang spielt es jedoch<br />

kaum eine Rolle, mit welcher<br />

Python-Version Sie arbeiten.<br />

Aus Kompatibilitätsgründen<br />

sind die meisten unserer Tutorials für<br />

die ältere Version geschrieben.<br />

Standardmäßig sind zwei Versionen von Python installiert.<br />

Per Kommandozeile können sie zwischen diesen auswählen.<br />

vielen anderen Programmiersprachen keine Gedanken zu machen,<br />

welchen Datentyp eine Variable hat, bevor wir sie an print<br />

übergeben. Die einzelnen Datentypen sind trotzdem wichtig,<br />

weil sie vorgeben, wie Funktionen aufgebaut werden und was<br />

sie tun.<br />

„Es gibt bei Python jede<br />

Menge zu entdecken und<br />

auszuprobieren.“<br />

Datentypen<br />

Auch wenn Sie einer Variablen keinen Datentyp zuweisen müssen,<br />

sind Datentypen bei Python genauso wichtig wie bei anderen<br />

Programmiersprachen. <strong>Das</strong> liegt daran, dass Datentypen<br />

normalerweise nicht von einem Typ in einen anderen Typ konvertiert<br />

werden können, ohne dass es zu Fehlern kommt. Wenn<br />

Sie eine lange Fließkommazahl wie <strong>Pi</strong> in eine Ganzzahl und<br />

dann zurück in eine Fließkommazahl konvertieren würden, gingen<br />

alle Nachkommastellen verloren. <strong>Das</strong> ist wichtig zu verinnerlichen,<br />

damit Sie schon im Vorfeld planen können, mit welchen<br />

Datentypen ihr Code arbeiten wird, bevor Sie den Code<br />

geschrieben haben. Dieses Wissen öffnet Ihnen auch den<br />

Zugang zu einigen Extrafunktionalitäten von Python.<br />

Zum Beispiel haben wir in unserer „Hello world!“-Ausgabe<br />

bereits mit dem string-Datentyp gearbeitet, auch wenn wir ihn<br />

nicht explizit so benannt haben. Wenn Sie einer Variablen eine<br />

Zahl zuweisen, wird diese normalerweise<br />

eine Ganzzahl sein,<br />

solange sie kein Komma enthält,<br />

und andernfalls vermutlich<br />

eine Fließkommazahl. Abgesehen<br />

von den Datentypen, die<br />

einzelne Werte enthalten, gibt<br />

es spezielle Datentypen, die eine Auflistung von Werten enthalten<br />

können. Diese werden Arrays genannt. Arrays sind sehr<br />

nützlich, wenn Sie eine Gruppe von Werten zusammengruppieren<br />

möchten. Hier ist ein Beispiel:<br />

mylist = [8,2,6,4,10]<br />

Die obige Zeile erstellt eine Liste von Zahlen und weist sie<br />

der Variablen mylist zu. Wenn Sie bestimmte Elemente des<br />

Arrays ansprechen wollen, können Sie dies zum Beispiel über<br />

mylist[0] tun. So würden Sie das erste Element im Array ansprechen.<br />

Arrays beginnen immer mit einer 0, nicht mit einer 1.<br />

Zum Schluss möchten wir noch zwei weitere Dinge veranschaulichen,<br />

bevor wir Sie in die Welt der Python-Tutorials entlassen.<br />

<strong>Das</strong> erste ist das Prinzip der Loops. Ein Loop führt den<br />

gleichen Abschnitt Code so lange aus, bis eine Bedingung erreicht<br />

wird. Wir können zum Beispiel jedes Element in unserer<br />

zuvor erstellten Liste mit einem solchen for-Loop ausgeben:<br />

for i in mylist:<br />

print i<br />

8<br />

2<br />

6<br />

4<br />

10<br />

Alles, was der Loop tut, ist, für jedes Element in der Liste die<br />

nachfolgende print-Anweisung auszuführen. for-Loops werden<br />

sehr häufig verwendet, um Aufgaben dieser Art zu erledigen,<br />

und Sie werden sie bald als festen Bestandteil in Ihren Programmen<br />

verwenden. Ein genauso wichtiger Bestandteil sind<br />

Methoden. Es handelt sich dabei um Funktionen, die die von<br />

Ihnen verwendeten Datentypen erben. Bei unserer Beispielliste<br />

wäre sort eine solche Methode.<br />

Wenn Sie dem Beispiel vor<br />

der print-Anweisung den Methodenaufruf<br />

mylist.sort() hinzufügen,<br />

wird die Anordnung der<br />

Elemente im Array verändert.<br />

Lassen Sie den for-Loop jetzt<br />

laufen, so werden die Elemente in aufsteigender Reihenfolge<br />

ausgegeben.<br />

Mit diesen Ausführungen haben wir Python nur ein klein<br />

wenig angerissen. Es gibt noch jede Menge mehr zu entdecken<br />

und auszuprobieren. Eine gute Informationsquelle ist die offizielle<br />

Website http://docs.python.org, und daneben gibt es<br />

noch viele andere Anlaufstellen im Internet, wenn Sie Unterstützung<br />

brauchen oder sich mit anderen Python-Anwendern<br />

austauschen möchten.<br />

111


Coding<br />

Designkonzepte:<br />

Eine IDE nutzen<br />

Die Arbeit in einem Texteditor ist Ihnen zu mühsam? Dann brauchen<br />

Sie eine integrierte Entwicklungsumgebung.<br />

Tippfehler finden, Schlüsselworte markieren, den Code<br />

hübsch formatieren – es gibt viele stupide Tätigkeiten,<br />

die ein Computer übernehmen könnte. Da ist es ärgerlich,<br />

dass die Kommandozeile des Python-Interpreters all<br />

dies nicht kann. Editoren wie Kate oder Gedit markieren hingegen<br />

die diversen Elementtypen mit unterschiedlichen<br />

Farben und machen so dem Programmierer das Leben einfacher:<br />

Auch wenn einem die Sprache neu ist, erkennt man auf<br />

einen Blick, wenn ein Element nicht erkannt wird, wenn eine<br />

Klammer nicht stimmt oder wenn man einen einfachen<br />

Formatierungsfehler vor sich hat. Aber auch viele Experten<br />

vertrauen auf die farbigen Markierungen, die ihnen einen Teil<br />

der Arbeit abnehmen – gerade wenn man Code so schnell<br />

tippt wie der berühmte Richard Stallman. Was wiederum der<br />

Grund dafür sein könnte, dass Stallmans Emacs-Editor selbst<br />

über dieses Syntax-Highlighting verfügt.<br />

Syntax-Highlighting ist für Anfänger und Experten gleichermaßen<br />

sinnvoll. Man sieht Fehler schneller und man kann<br />

schneller Code schreiben oder verbessern. Sie sollten sich<br />

also auf die Suche nach<br />

einem Editor begeben, mit<br />

dem Sie sich wohlfühlen und<br />

der Sie und Ihr Projekt in allen<br />

Stadien der Software-<br />

Entwicklung unterstützt.<br />

Syntax-Highlighting und Autovervollständigung sind zwei der besten Gründe<br />

für eine Integrierte Entwicklungsumgebung wie Komodo.<br />

„Syntax-Highlighting ist<br />

für Einsteiger ebenso<br />

wichtig wie für Experten.“<br />

Reine Texteditoren sind für interpretierte Sprachen und einzelne<br />

Dateien sinnvoll, sie stoßen aber schnell an ihre Grenzen,<br />

wenn das Projekt wächst. Für solche Fälle wurde Integrierte<br />

Entwicklungsumgebungen (Englisch: Integrated Development<br />

Environment, IDE) entwickelt. Sie verwalten die diversen Code-<br />

Dateien eines Projekts und kümmern sich darum, wie diese zu<br />

einer ausführbaren Datei verarbeitet werden. Zudem haben sie<br />

ein Auge darauf, ob Funktionen und Objekte aus einer Datei<br />

auch in einer anderen Datei verwendet werden dürfen.<br />

Die meisten IDEs haben eine sehr ähnliche Funktionsweise<br />

und können mit den Besonderheiten zahlreicher<br />

Programmiersprachen umgehen. Um Ihnen eine Vorstellung<br />

der Möglichkeiten zu geben, zeigen wir im Folgenden einige<br />

ihrer typischen Funktionen und wie Sie diese für Ihre Projekte<br />

nutzen können.<br />

Komodo auf dem <strong>PC</strong><br />

In fast allen Beispielen in diesem Heft nutzen wir Python, um<br />

Ideen und Konzepte vorzustellen. Für diese Sprache gibt es<br />

etliche IDEs wie beispielsweise<br />

Eric, aber – vermutlich weil<br />

Python eine Cross-Plattform-<br />

Sprache ist – es gibt nicht die<br />

EINE IDE, die von jedem Python-<br />

Programmierer verwendet wird.<br />

Zudem sind viele IDEs nur gegen<br />

Geld zu haben, was insbesondere für Programmieranfänger<br />

wenig sinnvoll ist.<br />

Also ignorieren wir diese kommerziellen Optionen und verwenden<br />

die Freeware-Alternative Komodo Edit. Sie läuft nicht<br />

direkt auf dem <strong>Pi</strong>, da es keine spezielle ARM-Version gibt, aber<br />

da ein Desktop-<strong>PC</strong> ohnehin stets die bessere Variante zum<br />

Erstellen großer Textmengen ist, stellt Komodo eine großartige<br />

Python-IDE dar. Wenn Sie doch lieber direkt auf dem <strong>Pi</strong><br />

programmieren wollen, dann empfehlen wir Ihnen Geany.<br />

Die Installation ist denkbar einfach: Sie laden Komodo auf<br />

Ihren Linux-<strong>PC</strong>, entpacken das Paket und starten die<br />

Installation mit ./install.sh im gewünschten Verzeichnis. Die<br />

meisten Distributionen präsentieren Ihnen nun ein entsprechendes<br />

Programmsymbol auf dem Desktop, alternativ starten<br />

Sie die IDE mit bin/komodo von Ihrem Home-Verzeichnis<br />

aus. Lassen Sie sich vom ersten Anblick nicht entmutigen –<br />

die Standardkonfiguration zeigt eine große Anzeige für die<br />

kommerzielle Vollversion und zudem viele Fenster, die Sie<br />

bald kennenlernen werden. Die zwei Fenster auf der linken<br />

Seite zeigen oben einen einfachen Dateimanager und unten<br />

eine Projektansicht. Unter „Projekt“ versteht die IDE alle<br />

Dateien, die zur Anwendung gehören: den Code,<br />

Konfigurationsdateien und mehr. Um ein neues Projekt anzu-<br />

112


Coding<br />

legen, klicken Sie auf das kleine Symbol rechts daneben. Wir<br />

empfehlen, mit einer Python-3-Vorlage anzufangen. Um dem<br />

Projekt existierende Dateien hinzuzufügen, ziehen Sie sie mit<br />

der Maus auf den Projektnamen oder öffnen Sie mit einem<br />

Rechtsklick das Kontextmenü. Der Datei-Dialog gestattet die<br />

Auswahl zwischen all den von Komodo unterstützten<br />

Sprachen und setzt daraufhin die Definition einer Umgebungsvariablen<br />

an den Dateianfang.<br />

Code-Erzeugung<br />

Wir gehen nun von einer leeren, im Editor geöffneten Code-<br />

Datei aus, um die Vorteile einer IDE zu demonstrieren. Geben<br />

Sie import ein. Mit diesem Schlüsselwort wird Python veranlasst,<br />

externe Module zu laden, um dem Programm neue<br />

Funktionen hinzuzufügen. In einem einfachen Texteditor<br />

müssen Sie den genauen Namen des gewünschten Moduls<br />

kennen. In Komodo wird Ihnen hingegen eine Liste der installierten<br />

Module angezeigt, aus der Sie nur noch den gewünschten<br />

Eintrag auswählen. Wählen Sie math, um mathematische<br />

Funktionen zu importieren, und fügen Sie der Datei folgenden<br />

Code hinzu.<br />

def square(x):<br />

return x * x<br />

Diese Funktion errechnet das Quadrat von x. Wie Sie<br />

bemerkt haben sollten, fiel die Texteingabe leichter als in<br />

einem Texteditor, denn beispielsweise wurde der Zeileneinschub<br />

automatisch erzeugt. Wenn Sie in einer weiteren<br />

Zeile print square() eingeben, dann kennt Komodo bereits<br />

die square-Funktion und fordert Sie auf, zwischen den<br />

Klammern einen Wert einzugeben.<br />

Leider integriert Komodo Edit den Interpreter nicht selbst<br />

in seine Oberfläche, weshalb immer etwas Handarbeit gefordert<br />

ist. Wenn Sie [Strg]+[R] drücken oder ‘Tools > Run<br />

Command’ aus dem Menü wählen, dann erscheint ein kleiner<br />

Dialog, in den Sie %(python)<br />

%F eingeben. Dies veranlasst<br />

Komodo, %(python)<br />

durch den Dateinamen des<br />

Python-Interpreters zu<br />

ersetzen, der im<br />

Preferences-Fenster festgelegt<br />

wurde. %F wird noch durch den Dateipfad zum<br />

aktuellen Skript ersetzt. Dies startet nun Ihr Skript und<br />

öffnet ein weiteres Fenster, in dem die Ausgaben des<br />

Programms gesammelt werden. Auch Fehler werden in<br />

diesem Command-Output-Fenster angezeigt und erfreulicherweise<br />

genügt ein Mausklick auf eine Fehlermeldung, um<br />

die betreffende Code-Zeile im Editor anzuzeigen.<br />

Syntax-Überprüfung<br />

Sie sollten außerdem ein Auge auf das Syntax Checking<br />

Status-Fenster werfen. Dessen Inhalt wird in Echtzeit aktualisiert<br />

und zeigt alle Syntaxfehler wie beispielsweise inkorrekte<br />

Einrückungen, die im Projekt entdeckt wurden. Aus diesem<br />

Grund müssen Sie stets sicherstellen, dass im Drop-down-<br />

Menü am rechten unteren Ende des Bildschirms die richtige<br />

Sprache eingestellt ist – nur so weiß Komodo, welche<br />

Syntaxregeln gelten. Wenn Sie im Editor eine Funktion<br />

erstellt haben, dann werden Ihnen kleine eckige Klammern<br />

am linken Bildschirmrand auffallen. Sie markieren Codebereiche,<br />

die vom Kontrollfluss der umgebenden Funktion<br />

unabhängig sind. Wenn Sie auf das kleine Pluszeichen klicken,<br />

dann werden diese Bereiche zusammengefaltet und<br />

geben den Blick auf andere Codestellen frei.<br />

„Werfen Sie einen Blick auf<br />

den Reiter Syntax Checking<br />

Status.“<br />

Komodo beinhaltet Vorlagen, mit denen Sie ein Projekt starten können. Für<br />

wiederkehrende Projekttypen können Sie eigene Vorlagen erstellen.<br />

Viele IDEs und sogar einige Texteditoren haben ganz ähnliche<br />

Fähigkeiten. Tatsächlich erklärt das obige Beispiel, wie<br />

der Großteil aller IDEs funktioniert: wie eine fortschrittliche<br />

Textverarbeitung, die externe Tools und eine Sandbox für die<br />

Programmausführung unter ihrer Oberfläche verbirgt.<br />

Nachdem wir das run-Kommando ausgeführt haben, können<br />

wir es zu Komodos Toolbox hinzufügen und ihm eine<br />

Tastenkombination für den späteren Gebrauch zuweisen. Im<br />

Run-Dialog aktivieren Sie dazu „Add to toolbox“, woraufhin<br />

ein weiteres Fenster mit dem soeben verwendeten Python-<br />

Kommando erscheint. Nach einem Rechtsklick darauf wählen<br />

Sie „Properties“. An dieser Stelle können Sie dem<br />

Kommando einen freundlichen<br />

Namen geben und auf der Key-<br />

Binding-Seite eine Tastenkombination<br />

zuweisen.<br />

Definieren Sie nun eine weitere<br />

Funktion, indem Sie<br />

zunächst nur die Deklaration<br />

def square_root(x): eingeben. Wenn Sie im Funktionsrumpf<br />

nun math. eingeben, dann sehen Sie die Liste all jener<br />

mathematischen Funktionen, die wir mit dem import-<br />

Schlüsselwort importiert hatten. Wählen Sie math.sqrt und<br />

geben Sie eine öffnende runde Klammer ein. Ein kleines Popup<br />

informiert Sie nun darüber, was die Funktion macht und<br />

welche Argumente Sie erwartet. Solche Details sind es, die<br />

eine IDE auch zum Erlernen von neuen Sprachen wertvoll<br />

macht. Sie hilft Einsteigern bei ihrer Arbeit, indem sie das<br />

Nachschlagen in der Dokumentation übernimmt.<br />

Produktivität<br />

In den Augen einiger Entwickler ist diese sogenannte Autovervollständigung<br />

ein Zeichen für faule Programmierer – nur<br />

wer selbst den gesamten Code eingibt und Fehler selber findet,<br />

sei ein echter Kerl. Da auch wir echte Kerle sein möchten,<br />

pflichten wir diesen Meinungen natürlich bei – weisen<br />

aber darauf hin, dass sich auch in der professionellen Software-<br />

Entwicklung die Vorteile der stets verfügbaren Dokumentation<br />

und des schnelleren Schreibens herumgesprochen haben.<br />

Sprachen zu beherrschen bedeutet in der Software-<br />

Entwicklung vor allem das Verständnis der zugrunde liegenden<br />

Konzepte. Bei allem anderen darf die IDE gerne helfen.<br />

113


Coding<br />

Designkonzepte:<br />

Ein Unix-Tool<br />

Wir bauen ein Unix-Tool nach, um unsere Python-Kenntnisse zu<br />

verbessern und ein echtes Programm zu erstellen.<br />

Ein vollwertiges Programm! <strong>Das</strong> ist das erklärte Ziel<br />

der nächsten Seiten. Mit den nächsten Tutorials<br />

werden wir eine Python-Implementation des<br />

bekannten Unix-Tools cat entwickeln. Wie die meisten<br />

Unix-Tools bietet sich cat für solch ein Unterfangen an,<br />

da es klein und auf eine einzige Aufgabe spezialisiert ist.<br />

Zudem nutzt es nicht triviale<br />

Techniken wie Dateien, <strong>Pi</strong>pes<br />

und ähnliche Betriebssystem-<br />

Interna.<br />

Daher wird die<br />

Programmierung nicht lange<br />

dauern und uns gleichzeitig<br />

tief in die Features von Pythons Standardbibliothek einführen.<br />

Sobald sie diese Grundlagen gemeistert haben,<br />

Der Programmcode unseres Tools. Er ist zwar nicht lang, aber er verwendet<br />

sehr viele wichtige Sprachfeatures, die Sie immer wieder benötigen werden.<br />

„Sie wissen mehr als<br />

genug, um echte Tools<br />

zu entwickeln.“<br />

steht Ihren größeren Projekten bestenfalls das<br />

Kennenlernen zusätzlicher Bibliotheken im Weg. Unsere<br />

Ziele für das aktuelle Projekt sind:<br />

Ein Python-Programm namens cat.py zu erstellen, das<br />

beim Aufruf ohne jegliches Argument Benutzereingaben von<br />

der Standard-Input-<strong>Pi</strong>pe entgegennimmt und mit dem ersten<br />

Zeilenumbruch die<br />

Eingaben an die Standardausgabe<br />

sendet.<br />

Wenn die Argumente Dateinamen<br />

sind, dann soll cat.py<br />

jede Zeile der ersten Datei an<br />

die Standardausgabe senden<br />

und dann mit den weiteren Dateien ebenso verfahren.<br />

Es soll zwei optionale Argumente entgegennehmen: Mit -E<br />

soll cat.py ein $-Zeichen an das Ende jeder Zeile stellen und<br />

mit -n soll es die Zeilennummer an den Beginn einer jeden<br />

Zeile stellen.Unser cat-Klon wird mit beliebig vielen<br />

Dateinamen umgehen können, die ihm als Argument übergeben<br />

wurden. Dazu verwenden wir Python 3 – sollte Ihre<br />

Python-Version also noch 2.x lauten, dann installieren Sie<br />

nun die neuere Version: Einige unserer Programmfeatures<br />

sind zu Python 2.x nicht rückwärtskompatibel.<br />

Python-Dateien<br />

Fangen wir mit dem einfachsten Teil der Aufgabe an: den<br />

Inhalt einer Datei Zeile für Zeile an die Standardausgabe zu<br />

übergeben. In Python greift man auf eine Datei mittels der<br />

open-Anweisung zu, die ein Dateiobjekt zurückliefert. Mit diesem<br />

Objekt können wir die Datei lesen oder verändern. Um<br />

das Dateiobjekt für den späteren Gebrauch griffbereit zu<br />

haben, speichern wir das Ergebnis von open in einer Variable:<br />

file = open(“hello.txt”, “r”)<br />

Dies erstellt eine Variable namens file und ermöglicht es,<br />

später den Inhalt der Datei hello.txt zu lesen. Wir werden nur<br />

lesen und nicht schreiben können, da das zweite Argument r<br />

des Funktionsaufrufs angibt, dass die Datei im Lesemodus<br />

geöffnet werden soll.<br />

Nun, da wir Zugriff auf den Dateiinhalt haben, müssen wir<br />

diesen Inhalt Zeile für Zeile an die Standardausgabe senden.<br />

Dies ist in Python sehr einfach, da Dateien sogenannte „iterierbare“<br />

(in anderen Sprachen „enumerable“) Objekte sind.<br />

Iterierbare Objekte wie beispielsweise Listen, Strings, Tupel<br />

und Dictionarys gestatten den Zugriff auf die in ihnen gespeicherten<br />

Elemente mittels einer for-Schleife. Für eine<br />

Textdatei bedeutet dies, dass eine for-Schleife alle in ihr enthaltenen<br />

Textzeilen durchläuft:<br />

for line in file:<br />

print(line)<br />

114


Coding<br />

Die print-Funktion ihrerseits sendet jedes ihr übergebene<br />

Argument an die Standardausgabe des aktuellen<br />

Programms. Wenn Sie die drei Code-Zeilen in eine Datei<br />

schreiben, diese ausführbar machen und eine Datei hello.txt<br />

im gleichen Verzeichnis mit ein paar Textzeilen füllen, dann<br />

werden Sie sehen, dass wir das erste Ziel fast erreicht haben.<br />

Allerdings ist hinter jeder ausgegebenen Textzeile eine<br />

Leerzeile aufgetaucht.<br />

Der Grund dafür liegt in der print-Funktion verborgen, die an<br />

das Ende jeder Ausgabe selbständig einen Zeilenumbruch<br />

anhängt. Da die einzelnen Zeilen der Textdatei bereits einen<br />

Zeilenumbruch enthalten, haben wir nun einen zu viel.<br />

Dies lässt sich leicht beheben, indem man der print-Funktion<br />

ein zweites, mit Namen versehenes Argument übergibt:<br />

print(line, end=““). Damit wird print angewiesen, anstelle<br />

eines Zeilenvorschubs einen leeren String (vulgo „nichts“)<br />

anzuhängen.<br />

Argumente empfangen<br />

Im Vergleich mit dem echten cat-Programm hat unser<br />

Dreizeiler noch einen entscheidenden Nachteil: Um den<br />

Inhalt einer anderen Datei auszugeben, müssten wir den<br />

Programmcode ändern. Da dies wenig benutzerfreundlich<br />

ist, benötigt unser Programm nun eine Möglichkeit, die auf<br />

der Kommandozeile eingegebenen Programmargumente<br />

(beispielsweise cat.py hello.txt) zu verarbeiten.<br />

Der Python-Interpreter zeichnet automatisch alle von der<br />

Kommandozeile stammenden Argumente auf und stellt sie<br />

mithilfe des Moduls sys einem Programm zur Verfügung.<br />

Obwohl sys Teil der Standardbibliothek ist, kann der<br />

Programmcode nicht direkt darauf zugreifen. Stattdessen<br />

muss das Modul importiert und auf dessen Elemente mit der<br />

Punktnotation zugegriffen werden. Den Anfang macht der<br />

Import<br />

import sys<br />

am oberen Ende der cat.py-Datei. Am sys-Modul interessiert<br />

uns nur das argv-Objekt, das eine Python-Liste ist und<br />

alle auf der Kommandozeile eingegebenen Argumente enthält.<br />

Hier gilt es, zwei Dinge zu beachten: <strong>Das</strong> erste Argument<br />

ist der Programmname selbst, die Programmargumente folgen<br />

dahinter. Zudem können Sie auf argv nur mit der<br />

Punktnotation zugreifen. Um<br />

also auf das erste Argument<br />

zuzugreifen, schreibt man<br />

sys.argv[1].<br />

Mit diesem Wissen sollten<br />

Sie nun den Programmcode<br />

so anpassen können, dass anstelle von hello.txt der Wert<br />

von sys.argv[1] verwendet wird. Fortan können Sie cat.py<br />

mit dem Namen jeder beliebigen Textdatei aufrufen.<br />

Mehrere Dateien<br />

In den Spezifikationen haben wir angegeben, dass cat mehr<br />

als nur eine Datei entgegennehmen und deren Inhalte Stück<br />

für Stück anzeigen soll. Um auch dieses Feature einzubauen,<br />

müssen wir in einer Schleife über alle Elemente von argv iterieren<br />

und den bisherigen Programmcode innerhalb dieser<br />

Schleife ausführen. Hierbei müssen wir auf das erste<br />

argv-Element achten, das ja der Programmname ist uns<br />

nicht weiter interessiert. Um die Schleife mit dem ersten<br />

„richtigen“ Argument beginnen zu lassen (und weil der<br />

Programmname an Listenposition [0] gespeichert wurde),<br />

genügt folgende Anweisung:<br />

for file in sys.argv[1:]:<br />

„Am sys-Modul interessiert<br />

uns nur das argv-Objekt.“<br />

In diesem einfachen Beispiel sind die Ausgaben des echten Unix-Tools und<br />

unserer Python-Nachbildung völlig identisch.<br />

Da die Entgegennahme mehrerer Dateinamen über<br />

Argumente und die anschließende Verarbeitung dieser<br />

Dateien eine sehr häufige Tätigkeit ist, hat Python für den<br />

dazu notwendigen Code bereits eine vollwertige Funktion in<br />

petto. Um das dazu notwendige<br />

Modul fileinput zu<br />

importieren,<br />

stellen Sie wieder import<br />

fileinput an den Anfang der<br />

Code-Datei und ersetzen den<br />

gesamten Code durch<br />

for line in fileinput.input():<br />

print(line, end=””)<br />

Dieser Zweizeiler öffnet alle auf der Kommandozeile<br />

genannten Dateien und gibt deren Inhalt zeilenweise an die<br />

eine for-Schleife weiter. Und sollte dem Programm kein<br />

Dateiname übergeben worden sein, dann liest die Funktion<br />

automatisch aus der Standardeingabe sys.stdin.<br />

Zugegebenermaßen hat dieses Tutorial darauf verzichtet,<br />

Sie größere Mengen Code abtippen zu lassen, Sie sollten<br />

aber dennoch einen Eindruck davon bekommen haben, welche<br />

Schätze sich in Pythons riesiger Standardbibliothek verbergen.<br />

Vieles davon ist nur in Ausnahmefällen wirklich wichtig,<br />

eine umfassende Kenntnis der jeweiligen Bibliothek kann<br />

Ihnen aber in jedem Fall sehr viel Arbeit oder eine aufwendige<br />

Fehlersuche ersparen.<br />

115


Coding<br />

Designkonzepte:<br />

Ein echter Klon<br />

Die Reise in die Welt von Python geht mit einem<br />

verbesserten Klon des Unix-Tools cat in die nächste Runde.<br />

Auf den letzten Seiten haben wir angedeutet, wie<br />

man mit der Standardbibliothek von Python einen<br />

einfachen cat-Klon entwickelt. In diesem Tutorial<br />

werden wir zusätzliche Features einbauen und eine<br />

Möglichkeit entwickeln, Optionsargumente auszuwerten.<br />

Wir beginnen mit der Dateneingabe aus der Standardeingabe-<strong>Pi</strong>pe.<br />

In Linux werden alle <strong>Pi</strong>pes wie Dateien<br />

behandelt: Ob Sie nun einem Programm eine Datei als<br />

Argument übergeben oder<br />

„Glücklicherweise hat<br />

Python eine mächtige<br />

Alternative zu sys.argv.“<br />

ob Sie eine <strong>Pi</strong>pe als<br />

Argument übergeben,<br />

macht keinen Unterschied<br />

– grundsätzlich gibt es keine<br />

Abweichungen zwischen<br />

beiden.<br />

Dies gilt auch für Python selbst. Ihr Programm benötigt<br />

lediglich Zugriff auf das sys-Modul, das es – wenn<br />

Sie dem vorigen Tutorial gefolgt sind – bereits hat.<br />

Fangen wir mit einem kleinen Testprogramm an:<br />

import sys<br />

for line in sys.stdin:<br />

print(line, end=””)<br />

Die erste Zeile importiert das sys-Modul. Die folgende<br />

Zeile ist derjenigen sehr ähnlich, die wir bereits hatten, allerdings<br />

wird für die for-Schleife statt einer geöffneten Datei<br />

das Objekt stdin aus dem sys-Modul verwendet. Wie eine<br />

richtige Datei ist auch Pythons Standardeingabe-<strong>Pi</strong>pe ein iterierbares<br />

Objekt und gibt daher Zeile für Zeile an die Schleife<br />

weiter. Da die Standardeingabe im Allgemeinen leer sein<br />

dürfte, funktioniert stdin dennoch etwas anders: Anstatt<br />

alles auszugeben, was bereits in der <strong>Pi</strong>pe vorhanden ist, wartet<br />

stdin auf Eingaben des Benutzers. Erst wenn der<br />

Benutzer einen Zeilenumbruch eingegeben hat (also die<br />

Python verfügt über alle Features, die man für die Erstellung nützlicher<br />

Programme benötigt. In diesem Beispiel sehen Sie, wie die replace-Methode<br />

genutzt wird, um Zeilenumbrüche zu entfernen. Im Tutorial verwenden wir die<br />

etwas elegantere rstrip-Methode für den gleichen Zweck.<br />

[Return]-Taste gedrückt hat), gibt stdin den Text an die<br />

Schleife weiter. Die print-Funktion sendet nach wie vor den<br />

Inhalt von line an die Standardausgabe.<br />

Wir haben jetzt zwei unterschiedliche Versionen unseres<br />

Programms und müssen sie irgendwie zusammenführen.<br />

Wenn das Programm mit Argumenten gestartet wird, dann<br />

soll es die Dateiinhalte sammeln und ausgeben. Wenn es ohne<br />

Argumente gestartet wird, dann soll es alle in die<br />

Standardeingabe eingegebenen<br />

Zeilen ausgeben. Mit unserem aktuellen<br />

Wissen können wir dies problemlos<br />

umsetzen, da wir lediglich<br />

die Länge von sys.argv untersuchen<br />

müssen. Wenn sie größer als<br />

1 ist, dann kommt die Dateiversion<br />

zum Zug, anderenfalls die stdin-Version:<br />

if len(sys.argv) > 1:<br />

[Dateien ausgeben...]<br />

else:<br />

[stdin ausgeben...]<br />

<strong>Das</strong> einzig Interessante an diesem Code ist die len()-Funktion.<br />

Sie ist in Python eingebaut und kann auf jedes<br />

Aufzählungsobjekt (String, Tupel, Liste, Dictionary …) angewendet<br />

werden. Sie gibt an, wie viele Elemente in dem Objekt<br />

enthalten sind. Es gibt etliche ähnlicher Funktionen, die auf<br />

http://docs.python.org/3/library/functions.html<br />

beschrieben sind.<br />

Argumente und Optionen<br />

Dieser Ansatz funktioniert zwar wie gewünscht, scheitert aber<br />

an den optionalen Argumenten, die wir ja noch einbauen wollten.<br />

Glücklicherweise hat Python eine mächtige Alternative zu<br />

sys.argv, die sich genau um solche Zwecke kümmert. Zur<br />

Erinnerung: <strong>Das</strong> Original-cat hat zahlreiche Optionen, von<br />

denen wir zwei in unserem Programm nachbilden werden. Die<br />

Option -E zeigt am Ende jeder Zeile ein $-Zeichen und die<br />

Option -n stellt jeder Textzeile eine Zeilennummer voran.<br />

Um diese Optionen nicht selbst aus argv herauslesen zu<br />

müssen, erstellen wir uns ein OptionParser-Objekt. Dieses<br />

Objekt ist Teil des optparse-Moduls und wird uns den größten<br />

Teil der Arbeit abnehmen. Es entdeckt nicht nur automatisch<br />

Argumente und Optionen, es erzeugt auch automatisch einen<br />

Hilfetext. Dieser wird immer dann angezeigt, wenn der<br />

Benutzer fehlerhafte Argumente übergeben hat oder wenn er<br />

-h oder -help angibt:<br />

[jon@LT04394 ~]$ ./cat.py --help<br />

Usage: cat.py [OPTION]... [FILE]...<br />

Options:<br />

-h, --help show this help message and exit<br />

116


Coding<br />

Auf der Python-<br />

3-Webseite<br />

findet sich eine<br />

herausragende<br />

Dokumentation<br />

aller eingebauten<br />

Klassen und<br />

Funktion. In<br />

vielen Fällen enthalten<br />

die Texte<br />

auf http://docs.<br />

python.org/3/<br />

sogar detaillierte<br />

Anwendungsbeispiele.<br />

-E Show $ at line endings<br />

-n Show line numbers<br />

Um mit dem OptionParser loszulegen, importieren<br />

wir die notwendigen Komponenten:<br />

from optparse import OptionParser<br />

Diese Zeile sieht etwas ungewohnt aus, denn anstatt ein<br />

ganzes Modul zu importieren, importieren wir lediglich das<br />

OptionParser-Objekt. Auf diese Weise startet das Programm<br />

schneller und wir sparen Speicherplatz.<br />

Als Nächstes erstellen wir eine Instanz dieses Objekts, nennen<br />

ihr mit add_option die zu entdeckenden Optionen und<br />

übergeben ihr einen Hilfetext im benannten Parameter usage:<br />

usage = “usage: %prog [option]... [file]...”<br />

parser = OptionParser(usage=usage)<br />

parser.add_option(“-E”, dest=”showend”, action=”store_true”, help=”Show<br />

$ at line<br />

endings”)<br />

parser.add_option(“-n”, dest=”shownum”, action=”store_true”,<br />

help=”Show line numbers”)<br />

Der %prog-Teil des usage-Strings wird von<br />

OptionParser automatisch mit dem Programmnamen<br />

ersetzt. Der dest-Parameter gibt den Bezeichner an,<br />

den wir im Programmcode<br />

„Die letzte Zeile einer<br />

Textdatei hat oftmals<br />

keinen Zeilenumbruch.“<br />

verwenden, um das<br />

Vorhandensein einer<br />

bestimmten Option abzufragen.<br />

action gibt an, welchen<br />

Wert dieser<br />

Bezeichner haben soll – im<br />

Fall von store_true wird der Wert ein boolesches<br />

Wahr sein, wenn die entsprechende Option Teil der<br />

Programmargumente war, und anderenfalls ein boolesches<br />

Falsch. Mit add_option kann man auch<br />

Standardwerte angeben oder neben Optionen auch<br />

Optionsargumente auslesen. Weitere Anwendungsgebiete<br />

und andere gültige Werte für action sind auf<br />

http://docs.python.org/3/library/optparse.html<br />

dokumentiert.<br />

Nach diesen Vorbereitungen kann OptionParser an<br />

seine Arbeit gehen und uns seine Erkenntnisse in<br />

zwei Array-Variablen übergeben:<br />

(options, args) = parser.parser_args()<br />

Die options-Variable enthält alle zuvor definierten<br />

Optionen, also -E und -n. Die Variable args enthält alle übrigen<br />

Argumente.<br />

Während wir uns an die Implementierung der beiden<br />

Optionen wagen, werfen wir einen Blick auf Pythons String-<br />

Funktionen: Die Option -E bzw. showend soll am Ende jeder<br />

Zeile ein Dollarsymbol anhängen – also direkt vor dem<br />

unsichtbaren Zeilenumbruch, der das Ende jeder Zeile markiert.<br />

Da die letzte Zeile einer Textdatei allerdings oftmals keinen<br />

abschließenden Zeilenumbruch hat, dürfen wir von dessen<br />

Existenz nicht ausgehen.<br />

Also löschen wir den möglicherweise vorhandenen Zeilenumbruch<br />

mit der Funktion string.rstrip(). Diese entfernt<br />

alle unsichtbaren Zeichen am Ende eines Strings – und wenn<br />

da kein Zeilenumbruch zu finden ist, dann hat die Funktion<br />

eben keinen Effekt. Wenn wir der Funktion einen String als<br />

Argument übergeben würden, dann würde sie anstelle<br />

unsichtbarer Zeichen diesen String vom Zeilenende entfernen.<br />

Anschließend geben wir der Variable end, die wir der<br />

print-Funktion übergeben werden, den Wert $\n. Auf diese<br />

Weise übernimmt es print, das $-Zeichen an das Zeilenende<br />

zu setzen.<br />

Letzte Ideen<br />

Die Option -n bzw. shownum werden<br />

wir einfacher aufbauen. Wir<br />

verketten einfach die aktuelle<br />

Zeilennummer mit der jeweiligen<br />

Textzeile (inklusive des möglicherweise<br />

vorhandenen Zeilenumbruchs) und übergeben der<br />

Print-Funktionen einen leeren String als end-Parameter.<br />

Damit sind wir immer noch nicht ganz am Ziel angelangt.<br />

Da das Programm vier mögliche Kombinationen übergebener<br />

Optionen berücksichtigen muss, bedarf es noch nach einer<br />

Kontrollflusslogik. Außerdem müssen wir irgendwo die kumulative<br />

Zahl der ausgegebenen Zeilen ablegen, falls -n angegeben<br />

bzw. nach shownum verlangt wurde.<br />

Für all dies gibt es mehrere Ansätze. Da es sich hier<br />

aber um ein Tutorial handelt, werden wir die Lösung mit<br />

einem Einstieg in die Objektorientierte Programmierung<br />

angehen und die gewünschte Funktionalität in einer eigenen<br />

Klasse implementieren.<br />

117


Coding<br />

Designkonzepte:<br />

Klassenobjekte<br />

Wir führen die Ergebnisse der vorhergehenden Seiten<br />

zusammen und stellen den cat-Klon fertig.<br />

Auf den letzten Seiten haben wir große Fortschritte<br />

gemacht. Wir haben die Fähigkeit implementiert, den<br />

Inhalt mehrerer Textdateien auf dem Bildschirm anzuzeigen.<br />

Wir können Eingaben aus der Standardeingabe-<strong>Pi</strong>pe<br />

ausgeben und unser Programm kann<br />

Kommandozeilenoptionen<br />

erkennen und entsprechend<br />

reagieren. Was nun noch<br />

fehlt, ist die Implementation<br />

der Zeilennummern;<br />

anschließend müssen wir die<br />

einzelnen Bestandteile zu<br />

einem funktionierenden Programm zusammenfassen.<br />

„Die Herangehensweise<br />

entspricht dem Aufbau<br />

der realen Welt.“<br />

Objekte<br />

Wie bereits angekündigt, gibt es mehrere Wege zu diesem<br />

Ziel. Wir könnten die Aufgabe mit einigen verschachtelten<br />

Schleifen lösen, dieser Ansatz führt bei größeren Projekten<br />

aber schnell zu einem unleserlichem Code. Wir wählen daher<br />

Hier ist unsere cat-Implementation in allen Varianten: mit und ohne Optionen,<br />

mit und ohne Dateiangabe.<br />

den objektorientierten Weg, der zwar überdimensioniert<br />

erscheinen mag, aber einen guten Eindruck der Eleganz der<br />

Objektorientierten Programmierung gibt.<br />

Wenn man größere Programme entwickelt, ist deren<br />

Lesbarkeit eine der größten Herausforderungen. Nur gut lesbare<br />

Programme können (selbst<br />

vom Entwickler) nach längerer Zeit<br />

noch problemlos verstanden werden,<br />

lassen sich leicht erweitern und<br />

ermöglichen die effiziente Fehlersuche.<br />

Daher wurden im Lauf der<br />

Zeit Paradigmen entwickelt, welche<br />

die Komplexität großer Programme gering halten.<br />

Eines dieser Paradigmen ist die Objektorientierte<br />

Programmierung. Hier sind die einzelnen Elemente eines<br />

Programms diversen Objekten zugeordnet, die jeweils einen<br />

eigenen Status (also Variablenwerte) haben können und so<br />

den aktuellen Zustand des Objekts beschreiben. Auch<br />

Funktionen sind Objekten zugeordnet und ermöglichen es,<br />

diesen Zustand zu verändern.<br />

Diese Herangehensweise entspricht dem Aufbau der realen<br />

Welt: Sie können Ihre Hand mit deren Eigenschaften<br />

beschreiben, beispielsweise mit der Anzahl und Position der<br />

Finger. Und Sie können mit Ihrer Hand Funktionen ausführen,<br />

zum Beispiel einen Finger krümmen, eine Taste drücken oder<br />

eine Tasse halten. Ihre Hand ist ein Objekt mit einem Status<br />

und mit Funktionen, die diesen Status verändern.<br />

Wir werden einen Teil unseres cat-Programms zu einem<br />

Objekt machen, dessen Status die Anzahl der gezeigten<br />

Zeilen beschreibt und dessen Funktion das Anzeigen von<br />

Datei-Inhalten ist.<br />

Python-Objekte<br />

Python implementiert Objekte auf Basis eines<br />

Klassensystems. Eine Klasse ist eine Vorlage und ein Objekt<br />

ist eine bestimmte Instanz dieser Klasse, modelliert nach dieser<br />

Vorlage. Ähnlich wie bei einer Funktion definieren wir<br />

auch eine Klasse mit einem Python-Schlüsselwort:<br />

class catCommand:<br />

Innerhalb dieser Klasse definieren wir Methoden (die<br />

unseren altbekannten Funktionen entsprechen) und<br />

Eigenschaften, die jede Instanz dieser Klasse haben soll. Es<br />

gibt einige besondere, häufig genutzte Methoden. Eine davon<br />

ist die init-Methode. Sie wird aufgerufen, wenn eine Instanz<br />

erzeugt wird, und ermöglicht es, die Eigenschaftswerte des<br />

neu geschaffenen Objekts zu initialisieren.<br />

def __init__(self):<br />

self.count = 1<br />

In diesem Fall weisen wir der Variable count den Wert 1<br />

118


Coding<br />

zu, da dies die erste Zeilennummer sein wird, die wir anzeigen<br />

werden. Wichtiger aber ist das self-Argument, das der<br />

init-Funktion übergeben wurde – hier handelt es sich um den<br />

großen Unterschied zwischen Methoden und Funktionen.<br />

Jede Methode hat – selbst wenn sie sonst keine<br />

Argumente benötigt – diese self-Variable. Sie wird automatisch<br />

vom Interpreter geliefert und ihr Wert entspricht der<br />

Klasseninstanz, für die die Methode aufgerufen wurde. Daher<br />

ist self.count diejenige count-Variable, die der individuellen<br />

Instanz der catCommand-Klasse zugeordnet ist.<br />

Die run-Methode<br />

<strong>Das</strong> Objekt benötigt noch eine Methode, die abhängig von<br />

den gewünschten Optionen die Textzeilen verändert. Wir<br />

nennen sie run-Methode:<br />

def run(self, i, options):<br />

#set default options<br />

e = “”<br />

for line in i:<br />

#modify printed line according to options<br />

if options.showend:<br />

[...last month]<br />

if options.shownum:<br />

line = “{0} {1}”.format(self.count, line)<br />

self.count += 1<br />

print(line, end=e)<br />

Beachten Sie, dass auch diese Methode ein self-Argument<br />

hat. Die beiden anderen Argumente werden der<br />

Methode wie einer normalen Funktion beim Aufruf übergeben.<br />

<strong>Das</strong> erste Argument i wird eine Referenz auf die Datei<br />

sein, die diese Methode anzeigen soll. <strong>Das</strong> zweite Argument<br />

options ist eine Referenz auf die vom OptParse identifizierten<br />

Programmoptionen.<br />

Die Logik dieser Methode ist recht einfach: Jede einzelne<br />

Zeile der aktuellen Datei wird abhängig von den gewählten<br />

Optionen verändert. Es wird möglicherweise – wie im vorherigen<br />

Tutorial beschrieben – das Zeilenendezeichen zu „$\n“<br />

verändert. Anschließend wird eventuell die Zeile mit der format-Methode<br />

derart umgebaut, dass ihr die in der init-Methode<br />

definierte count-Variable vorangestellt wird.<br />

Anschließend inkrementieren wir den Wert von count und<br />

geben die Zeile aus.<br />

Der wichtigste Aspekt dieser Methode ist die Verwendung<br />

von self. Dieses Schlüsselwort gestattet uns den Zugriff auf<br />

Variablen, die innerhalb der aktuellen Objektinstanz definiert<br />

sind. Da diese Variablen der<br />

„Ein besonders schönes<br />

Beispiel gelungener<br />

Programmiererlyrik.“<br />

Instanz gehören, behalten sie<br />

ihren Wert so lange bei, wie die<br />

Instanz existiert. Sofern wir<br />

immer die run-Methode des<br />

gleichen Objekts aufrufen, kann<br />

der nächste Aufruf mit exakt<br />

dem count-Wert weiterarbeiten, mit dem der vorhergehende<br />

Aufruf beendet wurde.<br />

Nun müssen wir nur noch unsere bisherigen Ergebnisse<br />

zusammenführen. Dies machen wir in der main-Funktion –<br />

diese wird in Python zwar nicht benötigt, da aber viele<br />

Programmiersprachen zwingend eine main-Funktion voraussetzen,<br />

hat es sich auch in Python eingebürgert:<br />

def main():<br />

[option parsing code ...]<br />

c = catCommand()<br />

if len(args) > 1:<br />

for a in args:<br />

<strong>Das</strong> fertige Programm hat es uns trotz seiner Kürze ermöglicht, zahlreiche<br />

Aspekte der Python-Programmierung kennenzulernen.<br />

f = open(a, “r”)<br />

c.run(f, options)<br />

else:<br />

c.run(sys.stdin, options)<br />

Da sich der OptionParser-Code des letzten Tutorials nicht<br />

verändert hat, haben wir ihn an dieser Stelle unterschlagen.<br />

Neu hingegen ist die Zeile c = catCommand(): Sie erstellt eine<br />

neue Instanz der catCommand-Klasse, also ein catCommand-Objekt.<br />

<strong>Das</strong> c-Objekt besitzt eine Variable count, die<br />

von all seinen Methoden mittels self.count zugreifbar ist.<br />

Dies ermöglicht es uns, die Zeilennummern zu zählen.<br />

Anschließend prüfen wir, ob dem Programm Argumente<br />

übergeben wurden, und rufen in diesem Fall für jede entsprechende<br />

Datei die run-Methode des Objekts c auf, der wir auch<br />

noch die vom OptionParser ermittelten Optionen mitgeben.<br />

Falls hingegen keine Argumente vorliegen, dann rufen wir einfach<br />

die run-Methode mit<br />

sys:stdin anstelle eines<br />

Dateiobjekts auf.<br />

Zu guter Letzt rufen wir<br />

die main-Funktion mit einem<br />

besonders schönen Beispiel<br />

von Programmiererlyrik auf:<br />

main__”:<br />

if __name__ == “__<br />

main()<br />

Dieses Konstrukt ruft die main-Funktion auf – aber nur<br />

unter bestimmten Umständen. Die Variable __name__ hat in<br />

Python eine besondere Bedeutung: Wenn ein Programm von<br />

der Kommandozeile oder sonst wie gestartet wurde, dann ist<br />

der Wert dieser Variable „__main__“. Wenn es hingegen als<br />

externes Modul in ein anderes Python-Programm importiert<br />

wurde, hat es diesen Wert nicht. Auf diese Weise wird verhindert,<br />

dass ein importiertes Modul unerwünschte<br />

Nebenwirkungen hat oder dass main unbeabsichtigt mehrmals<br />

aufgerufen wird.<br />

119


Coding<br />

Designkonzepte:<br />

Module<br />

Wir zeigen, wie wir große Code-Mengen entwirren<br />

und Struktur in unsere Programme bringen.<br />

Beim Programmieren geht es häufig darum, eine komplexe<br />

Aufgabe in kleine, handliche Elemente aufzubrechen.<br />

Auf den letzten Seiten haben wir bereits etliche<br />

Werkzeuge und Techniken kennengelernt, die dem<br />

Programmierer dabei helfen. Von Variablen über Funktionen<br />

bis hin zu Objekten – sie alle strukturieren das ursprüngliche<br />

Problem. Ein Hilfsmittel haben wir noch nicht besprochen,<br />

weil man es erst dann benötigt, wenn des Programm ob seiner<br />

schieren Größe nicht mehr handhabbar ist: das Konzept<br />

der Module und Namensräume.<br />

Sie werden mittlerweile festgestellt haben, dass Code-<br />

Dateien mit zunehmender Länge immer schwieriger zu lesen<br />

sind. Auch wenn das Programm nur aus wenigen Hundert<br />

Zeilen besteht, so scheinen die Funktionen nach kürzester<br />

Zeit ineinander zu verlaufen, und wenn Sie auf der Suche<br />

nach der Ursache eines Programmfehlers sind, dann können<br />

Sie sich kaum noch daran erinnern, wo genau eine bestimmte<br />

Variable definiert wurde.<br />

Wenn der ganze Code in nur einer einzigen Textdatei<br />

steht, dann ist es<br />

„Ab einer bestimmten<br />

Code-Menge wird man auf<br />

Konflikte stoßen.“<br />

schwierig festzustellen,<br />

welche<br />

Abhängigkeiten zwischen<br />

den einzelnen<br />

Programmelementen<br />

bestehen – also welche<br />

Variablen von mehreren Funktionen genutzt werden,<br />

welche Funktionen einander aufrufen etc. Auch der Weg der<br />

Daten durch den Programmfluss ist kaum noch zu visualisieren.<br />

Ab einer bestimmten Code-Menge wird man auch auf<br />

Namenskonflikte stoßen, wenn beispielsweise zwei<br />

Funktionen aufgrund ihrer Tätigkeit den Namen add bekommen<br />

sollen. Und wenn dann auch noch die einzige<br />

Möglichkeit, eine irgendwann einmal geschriebene Funktion<br />

im neuen Projekt zu verwenden, darin besteht, sie zu kopieren,<br />

dann ist klar: Dem Code fehlt es an Struktur.<br />

<strong>Das</strong> Chaos beherrschen<br />

Module sind Pythons Antwort auf solche Herausforderungen.<br />

Mit dem Einsatz von Modulen strukturiert sich der<br />

Code wie von selbst, Namenskonflikte treten seltener auf und<br />

sie machen es zum Kinderspiel, einzelne Code-Elemente in<br />

mehreren Projekten zu verwenden.<br />

Zweifellos haben Sie in Ihren ersten Python-Programmen<br />

bereits Module verwendet – seien es die eingebauten Module<br />

oder solche von Drittherstellern –, um deren zusätzliche<br />

Funktionen zu nutzen. Erinnern Sie sich beispielsweise an<br />

das optparse-Modul aus dem vorhergehenden Tutorial. Wir<br />

konnten dieses Modul nutzen, indem wir es mit der<br />

import-Anweisung in unser Programm einbanden:<br />

import optparse<br />

Nachdem wir diese Zeile in unseren Code eingefügt hatten,<br />

standen uns wie von Geisterhand neue Funktionen zur<br />

Verfügung, die automatisch Kommandozeilenargumente<br />

analysierten. Wir hatten Zugriff auf die Funktion, indem wir<br />

den Modulnamen, einen Punkt und den Funktionsnamen<br />

aneinanderreihten:<br />

optparse.OptionParser()<br />

Allein der besseren Lesbarkeit wegen lohnt sich dieser<br />

Ansatz. Darüber hinaus mussten wir uns nicht darum sorgen,<br />

auf Variablen- und Funktionsnamen zu verzichten, die irgendwo<br />

im optparse-Modul Verwendung finden, da diese im optparse-Namensraum<br />

vom Rest der Welt verborgen sind. Und<br />

um den optparse-Code wiederzuverwenden, reicht ein einfaches<br />

import optparse.<br />

Wie Module funktionieren<br />

So mächtig und hilfreich Module auch sein mögen, so einfach<br />

sind sie auch zu implementieren. In Python sind sie<br />

nichts anderes als Dateien. Hier ist der Beweis: Erstellen Sie<br />

ein neues Verzeichnis und erstellen Sie dort eine Datei<br />

namens fact.py. In dieser Datei definieren Sie eine Funktion,<br />

welche die Fakultät einer beliebigen Zahl errechnet:<br />

def factorial(n):<br />

result = 1<br />

while n > 0:<br />

if n == 1:<br />

result *= 1<br />

else:<br />

result *= n<br />

n -= 1<br />

return n<br />

Dann erstellen Sie eine zweite Datei namens doMath.py.<br />

In dieser Datei importieren Sie zuerst das soeben erstellte<br />

Modul und rufen dann dessen fakultaet-Funktion auf:<br />

import fact<br />

print fact.factorial(5)<br />

Wenn Sie nun doMath.py aufrufen, dann sollte auf<br />

Ihrem Bildschirm das Ergebnis 120 erscheinen. Wie Sie<br />

sehen, ist der Name eines Moduls nichts anderes als der<br />

Dateiname ohne Erweiterung im gleichen Verzeichnis.<br />

Und wir können jede Funktion in diesem Modul aufrufen,<br />

indem wir deren Namen den Modulnamen und einen<br />

Punkt voranstellen<br />

Der Python-Pfad<br />

Damit stellt sich die Frage, wo Python all die anderen Module<br />

findet – sie befinden sich ja schließlich nicht im gleichen<br />

120


Coding<br />

Indem Sie Ihre<br />

Programme in<br />

kleine Einzelteile<br />

zerlegen und<br />

in separaten<br />

Dateien und<br />

Verzeichnisse<br />

speichern, bringen<br />

Sie Ordnung<br />

in Ihre Projekte<br />

und vereinfachen<br />

zukünftige Code-<br />

Änderungen.<br />

Verzeichnis wie unsere Programme. Die Antwort darauf lautet,<br />

dass Python eine vordefinierte Liste von Verzeichnisnamen<br />

hat, in denen der Interpreter nach all den Modulen<br />

sucht, die wir in den import-Anweisungen angegeben haben.<br />

Zuerst wird nach den eingebauten Modulen (den Built-Ins) im<br />

Installationsverzeichnis gesucht. Anschließend wird die<br />

Verzeichnisliste abgearbeitet, die im path gespeichert ist.<br />

Dieser path ist der $PATH-Umgebungsvariable sehr ähnlich<br />

– er verwendet die gleiche Syntax und dient exakt dem gleichen<br />

Zweck. Allerdings wird der Wert dieser Variable dynamisch<br />

erzeugt. Zum Start eines Programms besteht er aus<br />

diesen zwei Elementen:<br />

<strong>Das</strong> Verzeichnis, das das Skript beherbergt, welches die<br />

import-Anweisung enthält.<br />

Den PYTHONPATH, der wiederum eine Reihe von<br />

Verzeichnissen ist, die bei der Installation festgelegt wurden.<br />

Sie können die path-Variable jederzeit inspizieren:<br />

Importieren Sie das sys-Modul und sehen Sie sich dessen<br />

Attribut path an (zur Erinnerung: sys.path). Nach seinem<br />

Start darf ein Programm den Wert dieser Variable übrigens<br />

jederzeit verändern.<br />

Gültigkeitsbereiche<br />

Bevor Sie nun munter Ihre eigenen Module erstellen, nehmen<br />

wir uns noch des Themas Gültigkeitsbereiche an. Wir bereits<br />

vor wenigen Seiten angedeutet, bestimmt der<br />

Gültigkeitsbereich (Scope), in welchen Programmteilen eine<br />

Variable oder eine Funktion anderen Elementen zur<br />

Verfügung steht. Beispielsweise kann ein Python-Modul folgenden<br />

Code enthalten:<br />

food = [“apples”, “oranges”, “pears”]<br />

print food<br />

def show_choc():<br />

food = [“snickers”, “kitkat”, “dairy milk”]<br />

print food<br />

show_choc()<br />

print food<br />

Wie Sie sehen, ist die food-Variable innerhalb der Funktion<br />

eine Liste von Schokoriegeln und außerhalb der Funktion eine<br />

Liste von Obst. Dieser Umstand demonstriert zwei unterschiedliche<br />

Gültigkeitsbereiche: den globalen<br />

Gültigkeitsbereich des Moduls mit dem Obst und einen lokalen<br />

Gültigkeitsbereich der Funktion mit den Schokoriegeln.<br />

Schon in kleinen Programmen mit nur einer einzigen<br />

Code-Datei raten wir davon ab, Variablen im globalen<br />

Gültigkeitsbereich zu definieren: Es verwirrt den Leser.<br />

Module lindern dieses Problem ein wenig, da ein Modul seinen<br />

eigenen „globalen“ Gültigkeitsbereich hat – da aber auch<br />

Module immer größer und unübersichtlicher werden, ist das<br />

keine endgültige Lösung. Erst in Kombination mit Klassen, die<br />

wiederum eigene Gültigkeitsbereiche haben, sind Variablen in<br />

dem Objekt gekapselt, dem sie auch wirklich gehören.<br />

Python-Style<br />

Mit einem Alter von über zwanzig<br />

Jahren ist Python eine recht alte<br />

Programmiersprache. Dies hat den<br />

Vorteil, dass viele kluge<br />

Programmierer mittlerweile herausgefunden<br />

haben, wie man die Sprache<br />

am besten verwendet – also auf welche<br />

Weise bestimmte Aufgabentypen<br />

am besten zu lösen sind, wie man<br />

Funktionen benennt oder wie man den<br />

Code so formatiert, dass auch andere<br />

Menschen (oder Ihr Zukunfts-Ich) ihn<br />

verstehen.<br />

Wenn Sie an diesen sogenannten<br />

Best Practices interessiert sind, dann<br />

legen wir Ihnen zwei Webseiten ans<br />

Herz, auf denen Sie ein tiefes<br />

Verständnis für die Sprache Python<br />

erlangen können.<br />

http://python.net/~goodger/projects/pycon/2007/idiomatic/<br />

handout.html<br />

www.python.org/dev/peps/<br />

pep-0008<br />

121


Coding<br />

Designkonzepte:<br />

Massenspeicher<br />

Der einfachste Weg, in Python persistente Daten<br />

als Dateien zu speichern.<br />

Speicher ist billig: Heutzutage können Sie eine externe<br />

500-GB-Festplatte für weniger als 50 Euro kaufen.<br />

Sogar Smartphones haben mindestens 8 GB Speicher<br />

und können zum Preis einer Jeans auf bis zu 64 GB aufgerüstet<br />

werden.<br />

Daher ist es keine Überraschung, dass nahezu jede<br />

Anwendung auf die eine oder andere Weise Daten speichert;<br />

seien es Konfigurationsdaten, Cache-Dateien für beschleunigte<br />

Web-Zugriffe, Spielstände, Aufgabenlisten oder Fotos<br />

– die Liste ließe sich beliebig fortführen.<br />

Vor diesem Hintergrund demonstriert dieses Tutorial, wie<br />

man mit solch persistenten Daten unter Python elegant<br />

umgeht.<br />

Die offensichtlichste Form eines persistenten Speichers in<br />

Python ist das Dateisystem. Die Unterstützung ist in den<br />

Standardbibliotheken enthalten und meist benötigen Sie<br />

nicht einmal weitere Module, um Dateien zu lesen und zu<br />

schreiben.<br />

Um eine Datei im aktuellen Verzeichnis (also von wo aus<br />

Sie das Python-Skript<br />

„Nahezu jede Anwendung<br />

speichert Daten auf die<br />

eine oder andere Weise.“<br />

gestartet haben oder<br />

wo diese sich befanden,<br />

als Sie die Shell<br />

starteten) zu öffnen,<br />

rufen Sie die<br />

open()-Funktion auf:<br />

file = open(“lxf-test.txt”, “w”)<br />

<strong>Das</strong> erste Argument ist der Dateiname, das zweite<br />

Argument spezifiziert den Modus, in dem die Datei geöffnet<br />

wird – in diesem Fall im Schreibmodus, aber andere gültige<br />

Modi wären Lesen (r) und Anhängen (a).<br />

In Python ist eine Datei normalerweise ein Iterator. <strong>Das</strong><br />

heißt, dass man das in-Schlüsselwort verwenden kann, um in<br />

einer Schleife Zeile für Zeile durchzulaufen und deren Inhalt<br />

zu verarbeiten. Bevor wir eine Datei auslesen, wollen wir aber<br />

zunächst Daten in eine solche schreiben.<br />

In Dateien schreiben<br />

Angenommen, Sie entwickeln eine eigene RSS-<br />

Anwendung, um den Google Reader zu ersetzen. Sie haben<br />

bereits eine Oberfläche und können den Anwender nach<br />

einer Liste der Feeds fragen (beispielsweise mit raw_input()<br />

oder mit einem Web-Formular und CGI). Nun wollen Sie diese<br />

Liste auf Festplatte speichern, um zu einem späteren<br />

Zeitpunkt nach Feed-Aktualisierungen zu suchen. Im<br />

Augenblick sind die Feeds nur in einer Python-Liste gespeichert:<br />

feeds = [“http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/<br />

front_page/rss.xml”, “http://www.tuxradar.com/rss”]<br />

Diese Liste ins Dateisystem zu speichern ist mit der<br />

write()-Methode ganz einfach:<br />

for feed in feeds:<br />

file.write(“{0}\n”.format(feed))<br />

Beachten Sie, dass wir den Format-String verwenden, um<br />

am Ende jeder Feed-Adresse einen Zeilenumbruch einzufügen<br />

– anderenfalls hätten wir alle Adressen in einer Zeile und<br />

könnten sie nicht mehr separieren.<br />

Den Inhalt der Datei wiederzuverwenden ist ähnlich einfach.<br />

Wir iterieren über den Dateiinhalt, laden jede Zeile einzeln<br />

ein und entfernen den Zeilenumbruch. Dies überlassen<br />

wir Ihnen.<br />

Wenn Sie Dateien im Python-Code verwenden, dann müssen<br />

Sie zwei Punkte beachten. Der erste Punkt ist, dass Sie<br />

alles, was Sie speichern möchten, in einen String umwandeln<br />

müssen. Dies ist denkbar einfach, da Sie lediglich die eingebaute<br />

str()-Funktion verwenden müssen, beispielsweise<br />

str(42) => „42“.<br />

Der andere Punkt ist, dass Sie eine geöffnete Datei nach<br />

Gebrauch wieder schließen müssen – sonst riskieren Sie<br />

Datenverlust, da das Betriebssystem Daten zwischenspeichert<br />

und dieser Speicher möglicherweise nicht rechtzeitig<br />

geleert wird. Sie schließen eine Datei manuell mit der close()-<br />

Methode, in unserem Beispiel wäre dies file.close().<br />

Eleganter ist allerdings die Verwendung des with-Schlüsselworts:<br />

with open(“lxf-test.txt”, “a”) as file:<br />

feeds = [line.rstrip(“\n”) for line in f]<br />

Dieser kurze Python-Code öffnet das Dateiobjekt und –<br />

sobald der Block innerhalb der with-Anweisung beendet ist<br />

– schließt es automatisch wieder. Wenn Sie nicht genau wissen,<br />

was die zweite Zeile macht, dann schlagen Sie „List<br />

comprehensions“ auf http://docs.python.org nach. Dort finden<br />

Sie Beispiele für effizienten Code<br />

Serialisieren<br />

Die Arbeit mit Dateien wäre weitaus einfacher, wenn man<br />

sich nicht um das Konvertieren der Daten in und aus Strings<br />

kümmern müsste. Insbesondere bei Dictionarys und komplexen<br />

Datentypen schleichen sich schnell Fehler ein.<br />

Glücklicherweise enthält Python zwei Werkzeuge, um dies zu<br />

vereinfachen.<br />

<strong>Das</strong> erste Tool ist das pickle-Modul. pickle nimmt viele<br />

Python-Objekte entgegen und konvertiert sie in Strings<br />

(Serialisieren) und diese auch wieder zurück in Objekte<br />

(Deserialisieren). Sie müssen sich nur noch um das Öffnen<br />

und Schließen der Dateien kümmern, den Rest übernimmt<br />

das Modul:<br />

import pickle<br />

122


Coding<br />

Wenn persistente Daten für Sie wichtig sind, dann ist die ZODB-Objektdatenbank ein gutes Hilfsmittel. Sie ist in Python<br />

einfach zu handhaben und besser integrierbar als eine relationale Datenbank (www.zodb.org).<br />

import pickle<br />

...<br />

with open(“lxf-test.txt”, “a”) as file:<br />

pickle.dump(feeds, file)<br />

…<br />

with open(“lxf-test.txt”, “r”) as file:<br />

feeds = pickle.load(file)<br />

Dies ist nicht nur schnell umzusetzen, es hat auch<br />

Anwendungen außerhalb der persistenten Daten. Wenn Sie<br />

beispielsweise die Feed-Liste über das Netzwerk übertragen<br />

wollen, dann würden Sie diese Liste ebenfalls zuerst in einen<br />

einzelnen String umwandeln müssen.<br />

<strong>Das</strong> einzige Problem dieser Lösung ist, dass sie nur mit<br />

Python funktioniert – anderen Programmiersprachen ist das<br />

pickle-Datenformat hingegen unbekannt. Hierfür lautet die<br />

Lösung JSON: JSON steht für JavaScript Object Notation<br />

und ist ebenfalls eine Methode, Objekte in Strings umzuwandeln.<br />

Der Vorteil von JSON ist, dass nahezu jede<br />

Programmiersprache Möglichkeiten besitzt, JSON zu lesen<br />

und zu schreiben. In Python verwendet man JSON genauso<br />

wie pickle. Im obigen Beispiel müssten Sie lediglich pickle<br />

mit json ersetzen, um Ihre Daten zukunftssicher abzuspeichern.<br />

Grenzfälle<br />

In einigen Fällen werden Sie mehrere Objekte und unterschiedlichste<br />

Objekttypen haben, die Sie für die weitere<br />

Verwendung abspeichern möchten. Solche Fälle mit pickle<br />

abzudecken verursacht oft sehr viel Tipparbeit.<br />

Glücklicherweise nimmt Ihnen das Standardmodul shelve<br />

diese Arbeit ab und vereinfacht den Zugriff.<br />

shelve ist ein persistentes Dictionary – oder genauer<br />

gesagt eine Möglichkeit, Schlüssel/Wert-Paare persistent zu<br />

speichern. Die Besonderheit daran ist, dass jeder Dictionary-<br />

Wert ein beliebiges, von pickle serialisierbares Python-Objekt<br />

sein darf.<br />

Sehen wir uns ein Beispiel an: Angenommen, dass unser<br />

RSS-Reader nicht nur die Feed-Adressen speichern soll, sondern<br />

auch die Anzahl der ungelesenen News und welche<br />

News zuletzt gelesen wurde. Diese Daten könnten wir in<br />

einem Dictionary speichern:<br />

tracker = { “bbc.co.uk”: { “last-read”: “foo”,<br />

“num-unread”: 10, },<br />

“tuxradar.co.uk”: { “last-read”: “bar”,<br />

“num-unread”: 5, }}<br />

Wir können nun die Liste der Feeds und der jeweiligen<br />

Details in einer einzelnen Datei speichern, indem wir shelve<br />

einsetzen:<br />

import shelve<br />

shelf = shelve.open(“lxf-test”)<br />

shelf[“feeds”] = feeds<br />

shelf[“tracker”] = tracker<br />

shelf.close()<br />

Ein paar Dinge gibt es beim Einsatz von shelve zu beachten:<br />

Beispielsweise hat shelve seine eigenen Methoden, um<br />

Dateien zu öffnen und zu schließen; die üblichen Datei-<br />

Methoden können Sie nicht verwenden.<br />

Um Daten mit shelve zu speichern, müssen Sie diese wie<br />

in jedem anderen Dictionary auch zuerst einem Schlüssel<br />

zuweisen. Und wie bei Dateien müssen Sie das shelve manuell<br />

schließen, um Dateiverlust zu vermeiden.<br />

Der Zugriff auf Daten ist ebenso einfach. Statt einem<br />

Schlüssel einen Wert zuzuweisen, fragen Sie den Wert mithilfe<br />

des Schlüssels ab: feeds = shelf[“feeds”].<br />

Wenn Sie Daten im shelve verändern möchten, dann fragen<br />

Sie zunächst den Wert ab, verändern Sie die erhaltene<br />

Kopie, speichern Sie die Kopie unter gleichem Schlüssel wieder<br />

im shelve und schließen Sie es.<br />

Mit diesem Tutorial haben Sie das Handwerkszeug<br />

erlernt, das Sie für das Laden und Speichern persistenter<br />

Daten benötigen. Aber eine weitere Möglichkeit haben wir<br />

unterschlagen: relationale Datenbanken wie beispielsweise<br />

MySQL.<br />

123


Coding<br />

Designkonzepte:<br />

Datenorganisation<br />

Wir verwenden SQL und eine relationale Datenbank, um Ordnung<br />

in unsere 70er-Jahre-Rockmusiksammlung zu bringen.<br />

„Relationalen Datenbanken<br />

werden komplexe Fragen<br />

über die Daten gestellt.“<br />

Im vorhergehenden Tutorial haben wir gelernt, wie wir in<br />

unseren Python-Programmen Daten dauerhaft speichern.<br />

Die dort verwendeten Techniken waren strikt dateibasiert<br />

und – so nützlich sie auch sind – eignen sich nicht für große<br />

Datenmengen. Wenn eine Anwendung immer umfangreicher<br />

und Geschwindigkeit immer wichtiger wird, wenn die zugrunde<br />

liegenden Ideen und Zusammenhänge immer komplexer werden,<br />

dann benötigt man andere Technologien wie beispielsweise<br />

Objektdatenbanken oder relationale Datenbanken. Da<br />

Letztere die bei Weitem häufigsten Tools für komplexe Fragen<br />

über Datenbestände sind, stellen wir die Grundlagen dieser<br />

Datenbanken und ihrer Abfragesprache (die SQL für<br />

Structured Query Language genannt wird) vor. Sobald Sie die<br />

Grundlagen beherrschen,<br />

können Sie<br />

relationale<br />

Datenbanken in Ihren<br />

Code integrieren. Als<br />

Erstes stellen Sie<br />

sicher, dass Sie<br />

MySQL oder einen Drop-in-Ersatz installiert haben und mit der<br />

MySQL-Konsole darauf zugreifen können:<br />

mysql -uroot<br />

Wenn Sie ein Passwort eingerichtet haben, dann verwenden<br />

Sie den -p-Parameter, um dieses und den Benutzernamen<br />

anzugeben. Von nun an arbeiten wir an einer kleinen<br />

Datenbank, die unsere Musiksammlung verwaltet.<br />

Relationen<br />

Fangen wir mit all den Informationen an, die wir in unserer<br />

Musiksammlung speichern möchten. Ein logischer Ansatz<br />

wäre, von unseren CDs auszugehen: Jede CD ist ein Album<br />

und jedes Album hat Informationen (oder Attribute) wie den<br />

Künstler, der das Album erstellt hat, oder die im Album enthaltenen<br />

Musiktitel.<br />

Wir könnten all diese Daten in einer einzigen, großen<br />

Tabelle – wie in „Doppelte Daten“ – speichern. Dies wäre funk-<br />

Doppelte Daten<br />

Album Free At Last Free At Last<br />

Künstler Free Free<br />

Titel Little Bit of Love Travellin’ Man<br />

Titeldauer 2:34 3:23<br />

Albumdauer 65:58 65:58<br />

Jahr 1972 1972<br />

Bandauflösung 1973 1973<br />

Relationale Datenbank<br />

Albumname<br />

Free At Last<br />

Albumdauer 65:58<br />

Jahr 1972<br />

Artist_id 1<br />

tional, aber keineswegs effizient: Für jeden Musiktitel eines<br />

Albums würden wir viele Informationen duplizieren; beispielsweise<br />

den Albumnamen, die Albumlaufzeit, das Veröffentlichungsdatum<br />

und auch Informationen über den Künstler wären<br />

mehrfach enthalten. Dies wäre sowohl eine Verschwendung<br />

von Speicherplatz als auch eine unnötige Prozessorbelastung,<br />

zudem liefe jede Veränderung Gefahr, inkonsistente<br />

Informationen zu verursachen.<br />

Relationale Datenbanken lösen diese Probleme, indem wir<br />

in den Daten einzelne Entitäten identifizieren und diese in jeweils<br />

eigenen Tabellen speichern können. In unserem Beispiel<br />

würden wir Album, Künstler und Musiktitel in eigenen Tabellen<br />

speichern. Wir hätten nur noch einen einzigen Eintrag für den<br />

Künstler Free (nämlich den Namen und das Jahr der Band-<br />

Auflösung), einen Eintrag für das Album Free At Last (den<br />

Namen, das Veröffentlichungsdatum und die Gesamtdauer) und<br />

jeweils einen Eintrag für jeden Musiktitel (der alles andere enthält).<br />

All die unnötigen Doppelungen wären verschwunden – aber<br />

wie kommen wir nun an den kompletten Datensatz eines<br />

Musiktitels, inklusive des verantwortlichen Künstlers und des<br />

Albums? An dieser Stelle kommt der „relationale“ Teil einer<br />

relationalen Datenbank ins Spiel.<br />

Jede Zeile einer Datenbanktabelle muss in irgendeiner Weise<br />

einzigartig sein. Dies geschieht entweder über eine einzelne<br />

Spalte (etwa der Künstlername in der Künstlertabelle) oder<br />

über eine Kombination mehrerer Spalten (beispielsweise<br />

Albumtitel und Jahr der Veröffentlichung). Solche einzigartigen<br />

Spalten werden „primärer Schlüssel“ genannt. Sollte sich aus<br />

den vorhandenen Daten kein primärer Schlüssel ergeben, so<br />

kann man einfach eine zusätzliche Spalte einführen und diese<br />

automatisch mit einzigartigen Werten füllen lassen. Nun fügen<br />

wir den Tabellen jeweils eine Spalte hinzu, in denen der primäre<br />

Schlüssel der verwandten Datenzeilen in anderen Tabellen<br />

steht. Wenn wir beispielsweise dem Künstler Free den primären<br />

Schlüssel artist_id mit dem Wert 1 zuweisen, dann sollte<br />

auch besagte zusätzliche Spalte in der Zeile Free At Last der<br />

Album-Tabelle genau diesen Wert 1 haben. Wenn wir nun die<br />

Tabellenzeilen kombinieren, in denen artist_id den Wert 1 hat, dann<br />

können wir die ursprünglichen Informationen wiederherstellen.<br />

124


Coding<br />

SQL<br />

<strong>Das</strong> war auch schon das große Geheimnis relationaler<br />

Datenbanken – man zerlegt einen großen Datenbestand in<br />

sinnvoll kleine Häppchen (Tabellen) und beschreibt die<br />

Beziehung dieser Häppchen untereinander (primäre<br />

Schlüssel). Um Tabellen und Schlüssel zu erzeugen und um<br />

Daten einzufügen und abzufragen, setzen die meisten relationalen<br />

Datenbanken auf SQL. Da wir nun wissen, was Tabellen<br />

und Beziehungen sind, sehen wir uns den SQL-Code an, mit<br />

dem wir diese erzeugen und nutzen.<br />

Nachdem wir uns an der MySQL-Konsole angemeldet<br />

haben, erstellen wir eine Datenbank. Eine Datenbank ist der<br />

oberste Container einer Datenhierarchie, sie enthält die<br />

Tabellen und einiges mehr. Um eine Datenbank zu erstellen,<br />

geben wir die create database Anweisung ein:<br />

create database lxfmusic;<br />

Beachten Sie das Semikolon am Ende der Anweisung –<br />

alle SQL-Befehle müssen damit enden. Aus optischen<br />

Gründen haben wir Kleinbuchstaben verwendet; SQL selbst<br />

ignoriert die Klein- und Großschreibung der Anweisungen.<br />

Ähnlich wie bei den Verzeichnissen im Linux-Dateisystem<br />

müssen wir noch in diese Datenbank wechseln, um sie<br />

bequem verwenden zu können. Sie wechseln die aktuelle<br />

Datenbank mit der use-Anweisung:<br />

use lxfmusic;<br />

Now to create some tables:<br />

create table Album (<br />

Album_id int auto_increment primary key,<br />

name varchar(100)<br />

);<br />

create table Track (<br />

Track_id int auto_increment primary key,<br />

title varchar(100),<br />

running_time int,<br />

Album_id int<br />

);<br />

Hier gilt es zu beachten, dass wir zwei, mit Semikolon<br />

getrennte Anweisungen gegeben haben. Außerdem läuft jede<br />

Anweisung über mehrere Zeilen – SQL ignoriert überzählige<br />

Leerzeichen und Zeilenumbrüche. Sofern die Interpunktion<br />

stimmt, ermöglicht dies lesbar formatierte Anweisungstexte.<br />

Die Anweisungen selbst sind dem create database-Statement<br />

ähnlich. Wir geben an, was wir vorhaben, gefolgt von<br />

dem Objekttyp, auf das sich das Vorhaben bezieht, und<br />

schließlich geben wir noch ein paar Objekteigenschaften an.<br />

Bei create database war die einzige Eigenschaft der<br />

Datenbankname, bei create table kommen noch weitere<br />

Eigenschaften dazu, jeweils in Klammern und mit Komma<br />

voneinander getrennt.<br />

Es handelt sich hier um Spaltendefinitionen: Jeder einzelne<br />

Eintrag beschreibt eine neue Spalte der zu erzeugenden<br />

Tabelle. Am Anfang steht der Spaltenname, dann beschreiben<br />

wir den Typ der zu speichernden Daten und schließlich<br />

geben wir an, ob die Spalte Teil des primären Schlüssels ist.<br />

<strong>Das</strong> auto_increment-Schlüsselwort legt fest, dass die<br />

Datenbank selbst den Wert für jeden neuen Tabelleneintrag<br />

festlegt und sich der Programmierer nicht darum kümmern<br />

muss (bzw. darf). Auf diese Weise entsteht ein automatischer<br />

primärer Schlüssel.<br />

Mehr Details zu create table finden Sie in der MySQL-<br />

Dokumentation auf http://dev.mysql.com/doc/refman/5.5/en/create-table.html.<br />

MariaDB ist ein Drop-in-Ersatz für die MySQL-Datenbank und findet in<br />

Distributionen wie Mageia, OpenSUSE und Slackware wachsende Unterstützung.<br />

Inserts und Selects<br />

Daten in unsere neu erstellten Tabellen einzufügen ist ähnlich<br />

einfach:<br />

insert into Album (name) values (“Free at Last”);<br />

Wieder legen wir Aktion und das betroffene Objekt fest.<br />

Dann geben wir die Spaltennamen und die entsprechenden<br />

Werte, die wir in die Tabelle schreiben möchten.<br />

Bevor wir nun aber auch neue Einträge die die Track-<br />

Tabelle schreiben können, müssen wir wissen, welche<br />

album_id der Eintrag Free at Last bekommen hat, ansonsten<br />

könnten wir die Tabellen nicht sinnvoll miteinander verknüpfen.<br />

Dazu verwenden wir die select-Anweisung:<br />

select * from Album where name = “Free At Last”;<br />

Diese Anweisung bedeutet, dass wir alle Spalten der<br />

Album-Tabelle auswählen möchten, deren Wert in der Spalte<br />

name exakt „Free At Last“ ist. Da wir eigentlich nur an der ID<br />

des Albums interessiert sind, ersetzen wir den Stern durch<br />

Album_id und beschleunigen damit die Abfrage um ein<br />

Vielfaches. In unserem Fall gibt dies 1 zurück (es war das erste<br />

Album, das wir angelegt hatten) und wir können einen neuen<br />

Musiktitel folgendermaßen einfügen:<br />

insert into Track (title, running_time, Album_id) values (‘Little Bit<br />

of Love’, 154, 1);<br />

Bitte beachten Sie, dass wir die Dauer des Musiktitels in<br />

Sekunden und als Ganzzahl angegeben haben. Da wir bei der<br />

Definition einer Spalte grundsätzlich einen SQL-Datentyp<br />

angeben müssen und nicht jeder Python-Typ einen korrespondierenden<br />

SQL-Typ hat (und umgekehrt), haben wir<br />

einen einfachen und im Python-Code schnell zu konvertierenden<br />

Datentyp gewählt.<br />

Damit haben Sie die wichtigsten Grundlagen von SQL<br />

kennengelernt und kennen das Handwerkszeug für schnelle<br />

und speichersparende Datenabfragen. Sollten SQL und insbesondere<br />

Datenbestände aus mehreren Tabellen für Ihre<br />

Anwendung wichtig sein, dann sollten Sie sich noch mit der<br />

Wunderwelt der join-Abfragen auseinandersetzen. Dies sind<br />

kombinierte select-Anweisungen über mehrere Tabellen bei<br />

gemeinsamem Schlüssel. Und wenn Sie dann auch noch Ihre<br />

SQL- und Programmierkenntnisse kombinieren möchten,<br />

dann benötigen Sie die passende Code-Bibliothek, beispielsweise<br />

das python-mysql-Modul für Python.<br />

125


Coding<br />

GUI-Coding: Mit<br />

Mithilfe der Clutter-Bibliothek können Sie einen Blick über den Tellerrand der<br />

Kommandozeile in die Welt der grafischen Benutzeroberflächen wagen.<br />

Hier ist es noch ein bisschen dunkel. Aber dank Clutter<br />

wird sich das bald ändern.<br />

Bisher haben wir uns im Rahmen unserer Python-Anleitungen<br />

und -Projekte auf das Schreiben von Terminal-<br />

Skripten konzentriert, doch an dieser Stelle möchten<br />

wir Ihnen einmal eine Interaktion mit dem Nutzer per grafischer<br />

Benutzeroberfläche (GUI) demonstrieren. GUI-Code<br />

wird schnell sehr umfangreich, da die Darstellung grafischer<br />

Elemente auf dem Bildschirm aus Coding-Sicht eine komplexe<br />

Angelegenheit darstellt.<br />

Dank der PyClutter-Bibliothek ist es jedoch möglich, Code,<br />

der eine grafische Oberfläche steuert, trotzdem relativ kompakt<br />

zu halten. <strong>Das</strong> Programm, das wir mit Ihnen erstellen<br />

möchten, hat einen Umfang von weniger als 70 Zeilen. Es<br />

handelt sich um ein kleines, aber nützliches Werkzeug, mit<br />

dessen Hilfe Sie die Geschwindigkeit Ihrer Internetverbindung<br />

messen können. <strong>Das</strong> Schreiben des Programms führt<br />

Sie an die Möglichkeiten von Clutter und PyClutter heran und<br />

hilft Ihnen hoffentlich, eine Vorstellung zu gewinnen, wie die<br />

Bibliothek sinnvoll im Zusammenspiel mit Python-Web-Anwendungen<br />

eingesetzt werden kann.<br />

Zunächst sollten wir uns einen Moment mit der Terminologie<br />

von Clutter beschäftigen, denn diese mag auf den ersten<br />

Blick seltsam wirken. Während andere GUI-Toolkits die Objekte<br />

üblicherweise als Fenster oder Panel definieren, bezeichnet<br />

Clutter den grafischen Darstellungsbereich als stage<br />

(„Bühne“) und ein darin erscheinendes Objekt als actor<br />

(„Schauspieler“). Die actors haben mehr Eigenschaften als<br />

ein Standard-Widget, da sie de facto in einer 3D- statt einer<br />

2D-Umgebung existieren.<br />

Clutter: Objekte erschaffen<br />

Nun aber zur Praxis! Öffnen Sie Ihre übliche Python-Entwicklungsumgebung<br />

(zum Beispiel die Bash-Shell), und<br />

legen Sie los:<br />

>>> import clutter<br />

>>> stage = clutter.Stage()<br />

>>> stage.set_size(500,300)<br />

>>> red=clutter.Color(255,0,0,255)<br />

>>> black=clutter.Color(0,0,0,255)<br />

>>> stage.set_color(black)<br />

>>> stage.show_all()<br />

Schließen Sie das Fenster, das sich daraufhin geöffnet hat,<br />

und sehen Sie sich nochmals den Code an. Was genau ist<br />

passiert? Die erste Programmzeile hat das Clutter-Modul geladen.<br />

Clutter öffnet wiederum einige Backend-Module, die<br />

mit Darstellungsbibliotheken verbunden sind, damit Objekte<br />

auf dem Bildschirm angezeigt werden können. Als Nächstes<br />

haben wir ein stage-Objekt erschaffen. Der Viewport, also<br />

das Darstellungsfeld, ist die Bühne, auf der die actor-Objekte<br />

ihre Rollen spielen.<br />

Die Attribute sind sehr einfach festzulegen, es müssen lediglich<br />

Methoden für die stage-Klassen zugewiesen werden.<br />

Hier haben wir Größe und Farbe festgelegt. Die Parameter<br />

der Methode für die Größe sind Breite und Höhe, und die<br />

Farbe wird als RGB-Wert plus Alpha im clutter.Color-Objekt<br />

festgelegt. Der letzte Befehl bestimmt, dass – wie bei anderen<br />

GUI-Toolkits – das Objekt gezeigt wird, bevor es auf dem<br />

Bildschirm dargestellt wird.<br />

Doch was ist nun mit unseren Schauspielern, den Objekten,<br />

die wir auf dem Monitor haben möchten? Fügen wir ein<br />

Textobjekt hinzu:<br />

>>> a=clutter.Text()<br />

126


Coding<br />

Clutter hantieren<br />

>>> a.set_font_name(“Sans 30”)<br />

>>> a.set_colour(red)<br />

>>> a.set_text (“Hello World!”)<br />

>>> a.set_position(130,100)<br />

>>> stage.add(a)<br />

Bei diesem Textobjekt wird hoffentlich klar, was die einzelnen<br />

Methoden tun: eine Schriftart auswählen, eine Farbe festlegen,<br />

den Text-String definieren sowie die Position auf der<br />

Darstellungsfläche bestimmen. In der letzten Zeile wird das<br />

actor-Objekt dann tatsächlich auf die Bühne geschickt. Erst<br />

an diesem Punkt wird es auf dem Monitor sichtbar.<br />

Nun ist das Objekt aber vorhanden, und Sie können damit<br />

herumexperimentieren. Versuchen Sie beispielsweise eine<br />

andere Position oder Farbe.<br />

PyClutter ist leider nicht sehr gut dokumentiert, doch immerhin<br />

bietet Python gute Hilfestellungen. Wenn Sie dir (a)<br />

eintippen, bekommen Sie die Methoden und Attribute angezeigt,<br />

die für ein bestimmtes Objekt verfügbar sind.<br />

Als Nächstes wollen wir ein lauffähiges Skript erstellen.<br />

Zuvor sollte jedoch noch eine Sache erledigt werden, nämlich,<br />

die Kontrolle über die Anwendung an die Funktion<br />

clutter.main() zu übergeben. Hierbei möchten wir uns jedoch<br />

die Option bewahren, das Programm selber beenden<br />

zu können. Dies erreichen wir durch ein Keyboard Event<br />

(Tastaturereignis).<br />

Wenn das stage-Fenster aktiv ist, erhält Clutter Signale,<br />

wann immer Tasten auf dem Keyboard gedrückt werden. Wir<br />

können daher eine Callback-Funktion einrichten, die das Ereignis<br />

verarbeitet und die Haupt-Programmschleife abbricht,<br />

sobald eine bestimmte Taste gedrückt wird. Daneben können<br />

Sie übrigens auch anderen Tasten eine Aktion zuordnen,<br />

etwa einen Farbwechsel im Darstellungsbereich.<br />

>>> def parseKeyPress(self, event):<br />

... if event.keyval == clutter.keysyms.q:<br />

... clutter.main_quit()<br />

... elif event.keyval == clutter.keysyms.r:<br />

... self.set_color(red)<br />

...<br />

>>> stage.connect(‘key-press-event’, parseKeyPress)<br />

>>> clutter.main()<br />

Wenn das Skript in einer interaktiven Python-Shell läuft,<br />

beendet die Abbruchfunktion quit nicht Python an sich, geschweige<br />

denn, dass sie die Anwendung zerstören würde.<br />

Die Funktion transferiert lediglich die Kontrolle zurück an<br />

die Python-Shell. Die Methode clutter.main_quit() beendet<br />

die laufende Anwendung oder zumindest den Clutter-<br />

Anteil davon.<br />

Einen Systemmonitor bauen<br />

Jetzt wissen Sie ein bisschen über die Schnittstelle Bescheid,<br />

also können wir uns wie versprochen der Programmierung<br />

eines Werkzeugs zuwenden, mit dem Sie die Geschwindigkeit<br />

Ihrer Internetverbindung messen können. Bei allen Fragen<br />

im Zusammenhang mit Systemstatistiken ist proc<br />

immer eine gute Anlaufstelle. <strong>Das</strong> Pseudo-Dateisystem<br />

/proc enthält einen riesigen Fundus an Informationen über<br />

Nach guter<br />

alter Tradition<br />

beginnen wir<br />

damit, der Welt<br />

hallo zu sagen.<br />

Clutter-Versionen<br />

Die Clutter-Bibliothek und demzufolge auch das Python-<br />

Modul, das die Bibliothek verwendet, ist vor einer Weile<br />

auf Version 1.0 upgedatet worden. Normalerweise rufen<br />

Updates ein paar Unstimmigkeiten zwischen alten und<br />

neuen Versionen von Software hervor, aber in diesem<br />

Fall gibt es fundamentale Unterschiede zwischen dem<br />

Code der Versionen vor und nach 0.9. <strong>Das</strong> PyClutter-<br />

Modul und die Clutter-Bibliothek sind vermutlich über das<br />

Repository Ihrer Distribution erhältlich, doch wenn Sie<br />

diese installieren, achten Sie darauf, dass Sie Version 0.9<br />

oder besser noch 1.0 haben und keine ältere. Andernfalls<br />

wird der Code dieses Tutorials nicht funktionieren.<br />

Die interaktive Shell lädt zum Herumprobieren mit<br />

Clutter-Objekten ein.<br />

127


Coding<br />

Schnell-<br />

Tipp<br />

Den Überblick<br />

über Versionen<br />

zu behalten, kann<br />

zum Alptraum<br />

werden, doch die<br />

meisten Module<br />

speichern ihre<br />

Versionsnummer<br />

in ._<br />

version_, was<br />

nicht nur für Sie<br />

selbst praktisch<br />

ist, sondern<br />

auch Ihren<br />

Anwendungen<br />

erlaubt, nach<br />

einer kompatiblen<br />

Version Ausschau<br />

zu halten.<br />

Clutter-Infos<br />

Clutter ist eine Grafik- und GUI-<br />

Bibliothek unter GPL-Lizenz. Es wurde<br />

ursprünglich vom OpenHand-Team<br />

entwickelt und später an Intel verkauft,<br />

das die Entwicklung weiterverfolgt.<br />

Clutter ist ein einfaches, schnelles und<br />

mächtiges Werkzeug zur Erstellung<br />

von 2D- und 3D-Grafiken auf diversen<br />

einen Linux-Rechner. Es besteht aus einem Sammelsurium<br />

an Dateien, aber wir benötigen an dieser Stelle nur /proc/<br />

net/dev. Diese Datei listet alle Netzwerkgeräte auf, und Sie<br />

finden darin Statistiken über empfangene und gesendete<br />

Bytes, Pakete, Fehlermeldungen und vieles mehr. Für unseren<br />

Code benötigen wir nur die Information über ein- und<br />

ausgehende Bytes. Diese wird in Form einer Gesamtsumme<br />

gegeben und stellt quasi eine Momentaufnahme zum Zeitpunkt<br />

des Öffnens der Datei dar. Um eine Geschwindigkeit<br />

ermitteln zu können, müssen wir also die Datei zweimal hintereinander<br />

in einem bestimmten zeitlichen Abstand (zum<br />

Beispiel 1 Sekunde) öffnen und die Differenz der beiden<br />

Werte ausrechnen.<br />

Nun brauchen wir nur noch eine kleine Funktion, welche<br />

die Datei einliest, diese nach der gewünschten Information<br />

durchsieht und die Rechenoperation durchführt. Bevor wir<br />

die Datei verlassen, speichern wir noch die letzte Zahl, um sie<br />

beim nächsten Öffnen von der neuen Zahl abziehen zu können.<br />

So könnte die Funktion aussehen:<br />

devfile=open(‘/proc/net/dev’,’r’)<br />

for line in devfile.readlines():<br />

line=line.strip()<br />

if (line[:4] == ‘eth0’):<br />

line=line[5:].split()<br />

print line[0], line[8]<br />

In der ersten Codezeile liest die Funktion die Datei ein, danach<br />

erfolgt die Suche innerhalb der Datei nach der Textzeile,<br />

die mit eth0 beginnt. Vor der Suche müssen die Zeilen allerdings<br />

noch gestrippt werden, denn der Output wird mit Leerzeichen<br />

aufgefüllt, um gleichmäßige Tabellenspalten zu erzeugen.<br />

Sobald die richtige Zeile in der Datei gefunden ist,<br />

entfernen wir den Schnittstellenteil und teilen den String so<br />

auf, dass wir jede der Zahlen als Element einer Liste bekommen.<br />

Der Wert der empfangenen und gesendeten Bytes befindet<br />

sich an Position 0 beziehungsweise 8 der Liste. Hier<br />

haben wir sie einfach ausgeben lassen. Tippen Sie den Code<br />

ein und schauen Sie sich die Ausgabe an. Zum Schluss müssen<br />

lediglich noch die Strings in ganze Zahlen umgewandelt<br />

und gespeichert werden.<br />

Timelines<br />

Falls Sie jetzt einwenden, dass die Ausführung des Programmcodes<br />

ja auch eine gewisse Zeitspanne benötigt (auf<br />

unserem Entwicklungssystem waren dies 0,0001 Sekunden)<br />

und somit das Ergebnis leicht verfälscht, könnten wir noch<br />

etwas in dieser Art schreiben:<br />

import time<br />

lasttime=1<br />

Plattformen. <strong>Das</strong> Backend besteht im<br />

Wesentlichen aus OpenGL, aber mit<br />

der Clutter-Bibliothek haben Entwickler<br />

ein effizientes und freundliches Tool an<br />

der Hand, um grafisch anspruchsvolle<br />

Anwendungen zu entwickeln, ohne sich<br />

mit den eher technischen OpenGL-<br />

Bibliotheken abmühen zu müssen.<br />

Zahlen. Bunte Zahlen. <strong>Das</strong> fängt doch schon mal gut an.<br />

lastin=0<br />

lastout=0<br />

def getspeed():<br />

x=open(‘/proc/net/dev’,’r’)<br />

for line in x.readlines():<br />

line=line.strip()<br />

if (line[:4] == ‘eth0’):<br />

line=line[5:].split()<br />

bin=int(line[0])<br />

bout=int(line[8])<br />

return (bin, bout)<br />

while True :<br />

z= getspeed()<br />

timedelta=time.time()-lasttime<br />

lasttime=time.time()<br />

sin=(float(z[0]-lastin))/(1024*timedelta)<br />

sout=(float(z[1]-lastout))/(1024*timedelta)<br />

print sin, sout<br />

lastin=z[0]<br />

lastout=z[1]<br />

time.sleep(5)<br />

Dies baut eine Timing-Funktion ein, sodass die Geschwindigkeit<br />

präziser errechnet werden kann, auch wenn sich<br />

der Unterschied natürlich nur im Millisekundenbereich bewegt.<br />

Falls Sie aber irgendwann die Zeitperiode an einer<br />

Stelle der Software ändern möchten, erleichtert Ihnen das<br />

obige Skript dies.<br />

Nun müssen wir das Skript noch in die Clutter-Anwendung<br />

integrieren. Man könnte es einfach ans Ende des bisherigen<br />

Programmcodes setzen, doch dann würde möglicherweise<br />

die Clutter-Hauptschleife nie aufgerufen werden. Zwar könnten<br />

wir die actor-Objekte immer noch zu jedem beliebigen<br />

Zeitpunkt aktualisieren, aber das wäre keine gute Sache. Wesentlich<br />

netter wäre es doch, den Objekten ihre Autonomie<br />

zu lassen und den Text mithilfe einer animierten Timeline zu<br />

kontrollieren.<br />

Eine Timeline ist ein Timer, der bis zu einem bestimmten<br />

Wert zählt und dann das programmiertechnische Äquivalent<br />

eines <strong>Pi</strong>epstons ausgibt – ein Signal. <strong>Das</strong> Signal kann aufgefangen<br />

und in ein Callback eingespeist werden, und Sie können<br />

auch andere Parameter hinzufügen. Für unsere Zwecke<br />

stellen wir den Timer so ein, dass er eine Funktion aufruft,<br />

welche die Netzwerkgeschwindigkeit testet und die beiden<br />

actor-Objekte aktualisiert.<br />

128


Coding<br />

Die Timeline ist ein Objekt an sich, doch wenn wir die Verbindung<br />

zwischen der Timeline und der Callback-Funktion<br />

ausführen, können wir auch unsere Textobjekte weiterleiten,<br />

sodass die Callback-Funktion diese direkt ändern kann.<br />

Timelines können wie einzelne Threads in einer Multithread-Anwendung<br />

verwendet werden. Sie sind zwar nicht so<br />

flexibel, sind aber einfacher zu managen und erleichtern die<br />

Behandlung animierter Objekte, insofern als sie die Animation<br />

des Objekts und etwaige andere Interaktionen des Objekts<br />

voneinander trennen können.<br />

import clutter<br />

import time<br />

lasttime=1<br />

lastbin=0<br />

lastbout=0<br />

black =clutter.Color(0,0,0,255)<br />

red = clutter.Color(255, 0, 0, 255)<br />

green =clutter.Color(0,255,0,255)<br />

blue =clutter.Color(0,0,255,255)<br />

def updatespeed(t, a, b):<br />

global lasttime, lastbin, lastbout<br />

f=open(‘/proc/net/dev’,’r’)<br />

for line in f.readlines():<br />

line=line.strip()<br />

if (line[:4] == ‘eth0’):<br />

line=line[5:].split()<br />

bin=int(line[0])<br />

bout=int(line[8])<br />

timedelta=time.time()-lasttime<br />

lasttime=time.time()<br />

speedin=round((bin-lastbin)/(1024*timedelta), 2)<br />

speedout=round((bout-lastbout)/(1024*timedelta), 2)<br />

lastbin, lastbout = bin, bout<br />

a.set_text(str(speedin)+’KB/s’)<br />

xx, yy=a.get_size()<br />

a.set_position(int((300-xx)/2),int((100-yy)/2) )<br />

b.set_text(str(speedout)+’KB/s’)<br />

xx, yy=b.get_size()<br />

b.set_position(int((300-xx)/2),int((100-yy)/2)+100 )<br />

def parseKeyPress(self, event):<br />

# Parses the keyboard<br />

#As this is called by the stage object<br />

if event.keyval == clutter.keysyms.q:<br />

#if the user pressed “q” quit the test<br />

clutter.main_quit()<br />

elif event.keyval == clutter.keysyms.r:<br />

#if the user pressed “r” make the object red<br />

self.set_color(red)<br />

elif event.keyval == clutter.keysyms.g:<br />

#if the user pressed “g” make the object green<br />

self.set_color(green)<br />

elif event.keyval == clutter.keysyms.b:<br />

#if the user pressed “b” make the object blue<br />

self.set_color(blue)<br />

elif event.keyval == clutter.keysyms.Up:<br />

#up-arrow = make the object black<br />

self.set_color(black)<br />

print ‘event processed’, event.keyval<br />

stage = clutter.Stage()<br />

stage.set_size(300,200)<br />

stage.set_color(blue)<br />

Eine Frage des Timings<br />

Die Clutter-Bibliothek nutzt Timeline-<br />

Objekte. Damit kann man fast alles<br />

erledigen, was gemacht werden muss,<br />

während eine Anwendung gerade läuft.<br />

Die Timeline-Objekte sind der Herzschlag<br />

Ihres Skripts, sie sorgen dafür,<br />

dass alles möglichst gut zusammen<br />

läuft. Timelines werden vielfach dafür<br />

benutzt, um Animationen und Effekte<br />

innerhalb von Clutter zu kontrollieren,<br />

aber Sie können Sie auch als eigene<br />

Interrupts verwenden und damit Routinen<br />

aufrufen, und zwar mithilfe von<br />

Signalen, die ausgesandt werden, um<br />

Ereignisse wie started oder completed<br />

hervorzurufen. Die Signale können<br />

auch mit einer Callback-Funktion<br />

verbunden werden, um damit noch<br />

etwas anderes zu steuern. Dies ist<br />

ein kurzes Beispiel-Skript, das Sie in<br />

die Python-Shell eintippen können:<br />

stage.connect(‘key-press-event’, parseKeyPress)<br />

intext=clutter.Text()<br />

intext.set_font_name(“Sans 30”)<br />

intext.set_color(green)<br />

stage.add(intext)<br />

outtext=clutter.Text()<br />

outtext.set_font_name(“Sans 30”)<br />

outtext.set_color(red)<br />

stage.add(outtext)<br />

stage.show_all()<br />

t=clutter.Timeline()<br />

t.set_duration(5000)<br />

t.set_loop(True)<br />

t.connect(‘completed’, updatespeed, intext, outtext)<br />

t.start()<br />

clutter.main()<br />

Hier haben wir nun sämtliche besprochenen Elemente zusammengefügt.<br />

Wir haben eine Bühne aufgebaut, sie mit<br />

Schauspielern bevölkert und anschließend die Timeline-Objekte<br />

von Clutter dazu benutzt, diese sich selbst aktualisieren<br />

zu lassen. Doch all das kratzt gerade mal an der Oberfläche<br />

der Möglichkeiten, die Clutter Ihnen in puncto Grafik<br />

bietet. Auf den folgenden Seiten gehen wir jedoch einen<br />

Schritt weiter.<br />

>>> import clutter<br />

>>> t=clutter.Timeline()<br />

>>> t.set_duration(2000)<br />

>>> t.set_loop(True)<br />

>>> def ping(caller):<br />

... print caller<br />

...<br />

>>> t.connect(‘completed’,ping)<br />

9L<br />

>>> t.start()<br />

>>> <br />

Hierbei handelt es sich um eine einfache<br />

Funktion namens ping, die lediglich<br />

den Parameter ausgibt, mit dem es<br />

angesprochen wurde. Wir verbinden<br />

das completed-Signal mit der ping-<br />

Funktion und starten die Timeline. Ohne<br />

weitere Interaktion wird die ping-Funktion<br />

nun alle 2 Sekunden aufgerufen.<br />

Leider bietet<br />

die Clutter-Website<br />

http://blogs.<br />

gnome.org/<br />

clutter/ Python-<br />

Anwendern nicht<br />

viel Hilfreiches,<br />

aber es gibt viele<br />

Hintergrundinfos<br />

und eine gute C-<br />

Dokumentation.<br />

129


Coding<br />

Python: Clutter-<br />

Gute Nachrichten: Wir kombinieren einen einfachen<br />

RSS-Reader mit professionellen Clutter-Animationen.<br />

Nicht alle Nachrichten sind gute Nachrichten. Mit diesem<br />

Feed kommen sie immerhin aus einer guten Quelle.<br />

In diesem Tutorial betrachten wir einige der mächtigen<br />

Animationstechniken von Clutter, gruppieren Objekte<br />

und lernen etwas über TextActors. Zu diesem Zweck entwickeln<br />

wir einen RSS-Reader und hübschen diesen auf. Der<br />

Platz wird nicht ausreichen, um alle Features eines Multi-<br />

Stream-Readers zu implementieren und um die Technik des<br />

Animierens exakt zu beleuchten, aber wir zeigen, wie man<br />

Daten aus einem Feed ausliest und wie man diese zu Clutter-<br />

Objekten macht. Damit bekommen Sie alle notwendigen<br />

Grundlagen, um selbst ein solchen Monstrum entwickeln zu<br />

können.<br />

Wer noch nicht mit Clutter experimentiert haben sollte,<br />

dem empfehlen wir, so viel wie möglich im interaktiven<br />

Modus von Python zu experimentieren. Da Sie in diesem<br />

Modus beliebigen Code sofort ausführen können, liefert diese<br />

Umgebung weitaus schneller Ergebnisse und<br />

Fehlermeldungen, als es der sonst übliche Normalmodus<br />

könnte. Die Listings in diesem Tutorial zeigen die Python-<br />

Eingabeaufforderung >>> am Anfang jeder Zeile, wenn Sie<br />

etwas eingeben sollen. Wenn die Listings hingegen eine<br />

Ausgabe zeigen, dann steht >>> nicht am Zeilenanfang –<br />

sondern genau so, wie Sie es auf Ihrem Bildschirm sehen.<br />

Fütterungszeit<br />

Bei einem News-Reader stellt sich zuallererst die Frage, wie<br />

wir an die News aus einem Feed herankommen. Dazu kann<br />

man das Rad immer wieder neu erfinden, einfacher ist aber<br />

die Verwendung einer bereits bestehenden Bibliothek – in<br />

unserem Fall verwenden wir Feedparser.<br />

In jedem Fall benötigen wir die URL eines Feeds. Um an<br />

eine solche Web-Adresse zu gelangen, besuchen Sie einfach<br />

Ihre Lieblingsseiten im Internet und halten nach dem orangefarbenen<br />

RSS-Syndication-Symbol Ausschau. Meist ist dieses<br />

Symbol ein direkter Link auf einen Nachrichten-Feed,<br />

dessen Adresse Sie aus dem Browser in Ihre Anwendung<br />

kopieren können. Um beispielsweise den TuxRadar-Feed einzulesen,<br />

verwenden Sie die Adresse http://www.tuxradar.<br />

com/rss. In unserem Beispiel verwenden wir hingegen den<br />

News-Feed der BBC. Dies hat zwei Gründe: Erstens liefert er<br />

eine Bildreferenz, die sich für unsere Clutter-Experimente<br />

bestens eignet. Und zweitens wird der Feed regelmäßig mit<br />

neuen Nachrichten aktualisiert, was wiederum die Tests vereinfacht.<br />

Der BBC-Feed hat die Adresse http://newsrss.bbc.<br />

co.uk/rss/newsonline_uk_edition/world/rss.xml.<br />

>>> import feedparser<br />

>>>f= feedparser.parse(‘http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/world/rss.xml’)<br />

>>>f<br />

{‘feed’: {‘lastbuilddate’: u’Wed, 30 Dec 2010 19:11:25 GMT’, ‘sub-<br />

Die Clutter-Website wird regelmäßig mit verbesserten<br />

Dokumentationen und neuen Softwareversionen<br />

aktualisiert. Regelmäßiger Besuch ist daher Pflicht.<br />

130


Coding<br />

Animationen<br />

title’: u’Get the latest BBC World News: international news, features<br />

and analysis from Africa, Americas, South Asia, Asia-Pacific,<br />

Europe and the Middle East.’, ‘language ...<br />

Wenn wir mit f Python veranlassen, die soeben zugewiesene<br />

Variable anzuzeigen, dann wird der komplette<br />

Containerinhalt ausgegeben – wir mussten ihn am Ende<br />

abschneiden, da er den Heftumfang gesprengt hätte. Um an<br />

einzelne, für uns interessante Bits zu gelangen, verwenden<br />

daher wir Indizes und Schlüssel. Die einzelnen Nachrichten<br />

befinden sich in einer Liste namens „entries“ und bestehen<br />

aus Details wie Zusammenfassung (summary),<br />

Zeitstempeln, Link-URL etc.<br />

>>> f.entries[0].title<br />

u’Nokia expands claim against Apple’<br />

>>> f.entries[0].link<br />

u’http://news.bbc.co.uk/1/hi/technology/8434132.stm’<br />

>>> f.entries[0].updated_parsed<br />

time.struct_time(tm_year=2009, tm_mon=12, tm_mday=29, tm_<br />

hour=18, tm_min=0, tm_sec=46, tm_wday=2, tm_yday=364, tm_<br />

isdst=0)<br />

>>> f.entries[0].updated<br />

u’Wed, 30 Dec 2009 18:00:46 +0000’<br />

>>> f.entries[0].summary<br />

u’Nokia ramps up its legal fight against Apple, claiming that almost<br />

all of its products infringe its patents.’<br />

Wie Sie sehen, können wir aus diesen Elementen alles<br />

herauslesen, was ein guter RSS-Reader braucht. Zusätzlich<br />

möchten wir nun aber auch das Feed-Bild anzeigen. Die RSS-<br />

Spezifikationen erlauben ein (optionales) Bild, mit dem sich<br />

der Nachrichtenkanal selbst präsentieren kann. Dieses Bild<br />

wird mit URL, Beschreibungstext und einigen weiteren<br />

Details im Feed mitgeliefert (genau genommen im XML-<br />

Element „image“); Feedparser findet diese Daten und macht<br />

sie für uns zugänglich. Im obigen Beispiel wäre die Adresse<br />

des Bildes in der Eigenschaft f.feed.image.href gespeichert.<br />

Da wir das Bild anzeigen werden, ist es sinnvoll, es auf den<br />

RSS != RSS<br />

Ein RSS-Feed enthält die unterschiedlichsten Elemente. Neben<br />

dem Feed-Symbol nutzen wir nur solche Elemente, die es auch<br />

garantiert in jedem Feed gibt. Wenn Sie herausfinden möchten,<br />

was ein Feed sonst noch enthält, dann sehen sich den<br />

Seitenquelltext an. Unangenehmerweise gibt es mittlerweile<br />

zahlreiche Standards, da etliche Entwicklergruppen mit sehr<br />

unterschiedlichen Ideen diverse RSS-Formate definiert haben.<br />

Immerhin nimmt Ihnen das Feedparser-Modul den größten Teil<br />

der daraus resultierenden Mehrarbeit ab.<br />

Auf der Website der Universität Harvard findet sich ein<br />

Tutorial, wie Sie selbst einen RSS-Feed erstellen können –<br />

gleichzeitig beschreibt es, wie Sie einen solchen Feed in seine<br />

Bestandteile zerlegen.<br />

http://cyber.law.harvard.edu/rss/rss.html.<br />

lokalen Rechner herunterzuladen. Dazu bietet sich das herausragende<br />

Python-Modul urllib an, das neben vielen anderen<br />

nützlichen Werkzeugen die urlretrieve-Methode enthält.<br />

Diese Methode erhält eine Web-Adresse, speichert die dort<br />

zu findenden Daten im temporären Verzeichnis (meist /tmp<br />

auf der lokalen Festplatte) und liefert einen Dateinamen und<br />

einige http-Informationen zurück. Die gespeicherte Datei<br />

wird automatisch gelöscht, sobald der Speicherplatz knapp<br />

wird. Wenn wir sauber arbeiten möchten, kann unser<br />

Programm die Datei nach Gebrauch aber auch selbst wieder<br />

löschen.<br />

>>> import urllib<br />

>>> img, data =urllib.urlretrieve(f.feed.image.href)<br />

>>> img<br />

‘/tmp/tmpTsCyDc.gif’<br />

In wenigen Augenblicken werden wir mit dieser Datei etwas<br />

Sinnvolles anstellen.<br />

Schauspieler und Bühnen<br />

Doch zuvor beschäftigen wir uns mit Clutter. Wenn Sie<br />

noch nichts mit dieser Bibliothek zu tun hatten: Es handelt<br />

sich um eine Bibliothek zur Erstellung von schnellen, grafisch<br />

anspruchsvollen und vor allem animierten<br />

Benutzeroberflächen. Wie fast alle Animationssysteme verwendet<br />

auch Clutter Elemente wie Actors und Timelines –<br />

sollten Sie tiefer in diese Materie eintauchen wollen, dann<br />

legen wir Ihnen dringend die Lektüre der offiziellen<br />

Dokumentation auf http://Clutter-project.org ans Herz.<br />

Zum Hineinschnuppern in die Materie soll folgende<br />

Kurzzusammenfassung genügen: Ein Clutter-Fenster nennt<br />

sich „Stage“ (englisch für Bühne) und ist die Zeichenfläche<br />

für alle Elemente und Animationen. In der Python-Variante<br />

PyClutter ist die Stage ein normales GTK-Fenster, uns erwarten<br />

also keine Überraschungen. Alle Elemente auf der Stage<br />

nennen sich Actors (englisch für Schauspieler), egal ob es<br />

sich um Texte, Formen oder Texturen handelt.<br />

Es gibt viele<br />

Quellen für RSS-<br />

Feeds. Halten<br />

Sie einfach die<br />

Augen nach dem<br />

orangefarbenen<br />

Symbol mit<br />

den drei Bögen<br />

Ausschau.<br />

131


Coding<br />

Lesen bildet<br />

In diesem Tutorial benötigen wir natürlich diese<br />

Textelemente zur Darstellung der Nachrichtentexte, aber vor<br />

allem interessieren uns die Texturen. Clutter gestattet es,<br />

Texturen ohne Umwege aus einer Bilddatei zu erzeugen –<br />

und wie es der Zufall will, haben wir vor wenigen Zeilen eine<br />

solche Datei erstellt. Um zu zeigen, wie gut all dies zusammenspielt,<br />

öffnen wir eine Stage und lassen das Bild auftreten:<br />

>>> import clutter<br />

>>> black=clutter.color(0,0,0,255)<br />

>>> white=clutter.color(255,255,255,255)<br />

>>> stage= clutter.Stage()<br />

>>> stage.set_size(400,60)<br />

>>> stage.set_color(white)<br />

>>> stage.show_all()<br />

>>> ident =clutter.texture_new_from_file(img)<br />

>>> stage.add(ident)<br />

Der Code gibt uns eine Referenz auf ein Stage-Objekt, legt<br />

dessen Größe fest und gibt dem Hintergrund eine weiße<br />

Farbe. Dann wird aus dem Bild eine Textur erzeugt und diese<br />

der Stage hinzugefügt. Hier zeigt sich eine Besonderheit von<br />

Clutter: Im Gegensatz zu vielen anderen Grafik-Toolkits darf<br />

ein Actor auch dann noch erzeugt und gezeigt werden, wenn<br />

die Stage bereits in Verwendung ist. Jedenfalls sollten Sie<br />

nun in einem Fenster das altehrwürdige BBC-Logo sehen.<br />

<strong>Das</strong>s das Logo perfekt in das Fenster passt, ist kein Zufall<br />

– wir wussten bereits, dass das Logo 60 <strong>Pi</strong>xel hoch ist und<br />

haben die Stage entsprechend dimensioniert. Und da wir der<br />

Logo-Textur keine Position zugewiesen haben, verwendet<br />

Clutter die Standardwerte (0,0), die der linken oberen<br />

Fensterecke entsprechen.<br />

Clutter ist grandios. <strong>Das</strong> Python-Modul<br />

ist großartig. Die Dokumentation ist<br />

erbärmlich. Zwar sind die Klassen und<br />

Methoden des Python-Moduls identisch<br />

mit denen der C-Implementierung von<br />

Clutter, dennoch gibt es einige subtile<br />

Unterschiede, die den Programmierer in<br />

den Wahnsinn treiben und sich nicht in<br />

der Dokumentation finden. In solchen<br />

Fällen sind Pythons Introspektionswerkzeuge<br />

hilfreich, insbesondere die<br />

dir()-Funktion. Sie zeigt alle verfügbaren<br />

Klassen, Eigenschaften und Methoden<br />

des jeweiligen Objekts dir(Clutter) oder<br />

einer Methode dir(Clutter.Text).<br />

In Bewegung setzen<br />

Bevor wir unseren RSS-Reader fertigstellen, ein paar<br />

Worte zum Begriff „Animation“. Im wirklichen Leben steht<br />

dieser Begriff für die Illusion von flüssigen<br />

Bewegungsabläufen (oder für die professionelle<br />

Unterhaltung von Hotelgästen). In der Welt der<br />

Computergrafik ist der Begriff etwas weiter gefasst: Er steht<br />

für die Veränderung beliebiger Objekteigenschaften im<br />

Zeitverlauf. Bei diesen Eigenschaften kann es sich um Farben<br />

handeln oder um die Sichtbarkeit, aber natürlich auch um die<br />

klassischen Bewegungseigenschaften Rotation und Position.<br />

Ein Actor in Clutter hat eine Animate-Methode. Deren<br />

Argumente geben den Animationsmodus an, gefolgt von der<br />

Dauer in Millisekunden und schließlich die Eigenschaften und<br />

Werte, die animiert werden. Der Animationsmodus legt fest,<br />

wie schnell sich der jeweilige Eigenschaftswert im Zeitverlauf<br />

ändert, also ob die Bewegung linear ist oder beschleunigt/<br />

verzögert wird. Ein Modus kann jederzeit selbst definiert werden,<br />

Clutter hat die wichtigsten Modi aber bereits eingebaut<br />

und stellt diese mit Konstanten bereit. Hier nur eine Auswahl:<br />

CLUTTER_LINEAR<br />

CLUTTER_EASE_IN_QUAD<br />

CLUTTER_EASE_OUT_QUAD<br />

CLUTTER_EASE_IN_OUT_QUAD<br />

CLUTTER_EASE_IN_CUBIC<br />

CLUTTER_EASE_OUT_EXPO<br />

CLUTTER_EASE_IN_OUT_EXPO<br />

CLUTTER_EASE_IN_OUT_CIRC<br />

Der lineare Modus stellt eine gleichmäßige Bewegung dar,<br />

die Ease-Modi sind natürlich wirkende Kombinationen aus<br />

Beschleunigung und Verzögerung, jeweils mit unterschiedlicher<br />

Stärke dieses Effekts. Angenommen, wir haben ein<br />

Objekt an Position 0,0 und wollen es in exakt 2.000<br />

Millisekunden zu Position 100,0 bewegen. Nur mit einer linearen<br />

Animation wäre es nach einer Sekunde genau an Position<br />

50,0 – Sie dürfen hier also fleißig experimentieren, um den<br />

für Sie optimalen Modus zu finden.<br />

Die animate-Funktion nimmt den aktuellen<br />

Eigenschaftswert als Startwert und das übergebene<br />

Argument als Zielwert für die ebenfalls angegebene<br />

Eigenschaft. Sie können beliebig viele Eigenschafts-Wert-<br />

Paare übergeben. Nicht übergebene Eigenschaften werden<br />

nicht animiert.<br />

Zur besseren Vorstellung ein paar Beispiele – hoffentlich<br />

ist Ihre Stage noch offen:<br />

>>> ident.set_anchor_point(60,30)<br />

>>> ident.set_position(60,30)<br />

>>> ident.animate(clutter.LINEAR,2000,’rotation-angle-y’,720)<br />

<br />

>>> ident.animate(clutter.LINEAR,2000,’rotation-angle-y’,720)<br />

<br />

Beim zweiten Aufruf der Rotation ist nichts passiert. Dies<br />

liegt daran, dass der übergebene Wert nicht angibt, um wie<br />

viel sich eine Eigenschaft ändert, sondern mit welchem Wert<br />

die Animation endet. Beim zweiten Aufruf war der gewünschte<br />

Wert bereits erreicht – die Animation wurde zwar ausgeführt<br />

und dauerte exakt zwei Sekunden, aber sie hatte keinen<br />

sichtbaren Effekt. Sie können auch mehrere Eigenschaften<br />

gleichzeitig animieren. Versuchen Sie Folgendes:<br />

>>> ident.animate(clutter.LINEAR,2000,’x’,100, ‘rotation-angle-y’,<br />

360 )<br />

<br />

>>> ident.animate(clutter.EASE_IN_SINE,2000,’x’,0, ‘rotation-angle-y’,<br />

0 )<br />

<br />

In diesem Beispiel tanzt das Logo vor sich hin und kehrt<br />

dann an die Ursprungsposition zurück.<br />

Gruppendynamik<br />

Mit einem drehenden Logo sind wir bereits halb am Ziel; uns<br />

fehlen nur noch die Nachrichtenüberschrift und die<br />

Zusammenfassung, die beide neben dem Logo angezeigt<br />

werden sollen. Damit hätten wir drei Actors auf der gemeinsamen<br />

Bühne.<br />

Clutter kann durchaus jeden einzelnen Actor gleichzeitig<br />

animieren, bei aufwendigen Animationen und bei zahlreichen<br />

132


Coding<br />

Actors steigt der Programmieraufwand aber schnell ins<br />

Unermessliche. Glücklicherweise unterstützt Clutter<br />

Gruppen, in denen mehrere Actors zusammengefasst und<br />

dann als einzelner Actor behandelt werden. Wir erstellen also<br />

zuerst eine solche Gruppe, definieren dann die tatsächlichen<br />

Elemente, fügen diese der Gruppe hinzu und senden dann<br />

die Gruppe auf die Stage. Der Einfachheit halber erzeugen wir<br />

im Folgenden eine neue ident-Textur:<br />

>>> group1= clutter.Group()<br />

>>> ident1=clutter.texture_new_from_file(img)<br />

>>> head1=clutter.Text()<br />

>>> head1.set_position(130, 5)<br />

>>> head1.set_color(blue)<br />

>>> head1.set_text(f.entries[0].title)<br />

>>> body1=clutter.Text()<br />

>>> body1.set_max_length(75)<br />

>>> body1.set_position(130, 22)<br />

>>> body1.set_size(250, 100)<br />

>>> body1.set_line_wrap(True)<br />

>>> body1.set_text(f.entries[0].summary)<br />

>>> group1.add(ident1, head1, body1)<br />

>>> group1.show_all()<br />

>>> stage.add(group1)<br />

In diesem Code haben wir eine Textur und zwei<br />

Textobjekte erzeugt – eins repräsentiert die Titelzeile der<br />

Nachricht (head1) und eins die Zusammenfassung (body1).<br />

Die Texte stammen aus dem ersten Eintrag, den das Feed-<br />

Objekt enthält. Beide Textobjekte wurden linksbündig neben<br />

die Logo-Textur gesetzt. Es sieht zwar so aus, als hätten wir<br />

für die drei Actors absolute Koordinaten verwendet, tatsächlich<br />

aber beziehen sie sich auf die linke obere Ecke des<br />

Group-Objekts: Mit group1.add() werden die Actors Kinder<br />

der Gruppe und alles, was für die Gruppe gilt, gilt auch für<br />

deren Kinder – in diesem Fall die Position der Gruppe, die<br />

zunächst den Standardwert (0,0) hat.<br />

Daher gilt Folgendes:<br />

>>> head1.get_position()<br />

(130,5)<br />

>>> group1.set_position(10,10)<br />

>>> head1.get_position()<br />

(130,5)<br />

>>> group1.set_position(0,0)<br />

Wenn Sie die Position der Gruppe verändern, dann sehen<br />

Sie, wie sich Textur und Text bewegen – aber Vorsicht: Die<br />

Kindelemente wissen von dieser Bewegung nichts! Deren<br />

Positionseigenschaften haben sich nicht verändert, denn diese<br />

beziehen sich ja auf die Position innerhalb ihrer Gruppe<br />

– und es war die Gruppe, deren Positionseigenschaft sich<br />

geändert hat.<br />

Dies hat den angenehmen Nebeneffekt, dass wir nur noch<br />

diese eine Gruppe animieren müssen, um sämtliche<br />

Bildschirmelemente zu bewegen.<br />

>>> group.animate(clutter.LINEAR,2000,”x”,200,”y,”30”)<br />

<br />

>>> group.animate(clutter.LINEAR,2000,”x”,0,”y,”0”)<br />

<br />

Hier bewegen sich alle Elemente synchron, als ob sie nur<br />

ein einzelnes Element wären (was sie aus Code-Sicht auch<br />

sind). Wir könnten dennoch beispielsweise den Text oder die<br />

Position einzelner Elemente verändern, nur dass diese<br />

Änderungen relativ zur Gruppe und nicht zur Bühne wären.<br />

Wir erstellen nun eine zweite Gruppe und zwei<br />

Animationsmodi, um einen schönen Übergang von einer<br />

Nachricht zur nächsten zu erzeugen:<br />

>>> group2= clutter.Group()<br />

>>> ident2=clutter.texture_new_from_file(img)<br />

>>> head2=clutter.Text()<br />

>>> head2.set_position(130, 5)<br />

>>> head2.set_color(blue)<br />

>>> head2.set_text(f.entries[1].title)<br />

>>> body2=clutter.Text()<br />

>>> body2.set_max_length(75)<br />

>>> body2.set_position(130, 22)<br />

>>> body2.set_size(250, 100)<br />

>>> body2.set_line_wrap(True)<br />

>>> body2.set_text(f.entries[1].summary)<br />

>>> group2.add(ident2, head2, body2)<br />

>>> group2.hide()<br />

>>> stage.add(group2)<br />

>>> group1.animate(clutter.EASE_OUT_EXPO,4000,’x’,800,’ y’,0,’rotation-angle-y’,180)<br />

<br />

>>> group2.animate(clutter.EASE_OUT_<br />

EXPO,1,’x’,400,’y’,100,’rotation-angle-y’,720)<br />

<br />

>>> group2.show()<br />

>>> group2.animate(clutter.EASE_OUT_<br />

EXPO,3000,’x’,0,’y’,0,’rotation-angle-y’,0)<br />

<br />

Bevor wir die neue Gruppe zur Stage hinzufügen, haben<br />

wir sie unsichtbar gemacht. Dann wurde sie aus dem sichtbaren<br />

Bereich herausanimiert und wieder sichtbar gemacht.<br />

Auf diese Weise stört sie nicht die Darstellung der ersten<br />

Gruppe. Um eine zweite Nachricht zu zeigen, animieren wir<br />

einfach die zweite Gruppe zurück in den Bildschirm hinein<br />

und lassen die (nun überdeckte) erste Gruppe verschwinden.<br />

Nächste Schritte<br />

Mit diesem Wissen können Sie nun einen sehenswerten RSS-<br />

Reader erstellen. Ganz wichtig sind Tests auf potenzielle<br />

Fehler: Was, wenn der Feed nicht erreichbar ist oder keinen<br />

Eintrag hat? Außerdem könnte die jeweils sichtbare News<br />

alle paar Sekunden automatisch durch eine andere ersetzt<br />

werden. Und jeder bessere RSS-Reader fasst mehrere Feeds<br />

zusammen und möglicherweise möchten Sie anstelle des<br />

Feed-Logos das Bild der Nachricht selbst anzeigen.<br />

Mit solchen<br />

Animationen<br />

werten auch<br />

professionelle<br />

News-Portale<br />

und TV-Sender<br />

den endlosen<br />

Strom ihrer<br />

Nachrichten auf.<br />

133


Programmiersprachen<br />

134


Programmiersprachen<br />

Sprachen<br />

Nun ist es Zeit für weitere Fortschritte - der<br />

<strong>Raspberry</strong> <strong>Pi</strong> bietet sich dafür an, denn auf ihm<br />

laufen perfekt die Sprachen Python und<br />

Scratch. Mit dem ARM-Rechner können Sie sogar<br />

noch weitere Sprachen lernen.<br />

Andere Sprachen......................................................................................136<br />

Begeisterung für OpenEuphoria...................................................138<br />

Ein kurzer Lehrgang in Go.................................................................142<br />

Listig mit Lisp..............................................................................................146<br />

C++: So geht’s...........................................................................................150<br />

Fortan Fortran.............................................................................................154<br />

Lua: Erste Schritte..................................................................................158<br />

135


Programmiersprachen<br />

Andere Sprachen<br />

Für den Fall, dass Sie gerne eine andere Programmiersprache als Python<br />

auf dem <strong>Raspberry</strong> <strong>Pi</strong> ausprobieren möchten, stellen wir Ihnen hier eine<br />

Auswahl vor.<br />

Für die ersten Schritte als angehender Programmierer<br />

auf dem <strong>Raspberry</strong> <strong>Pi</strong> sind die Sprachen Scratch (insbesondere<br />

auch für Kinder) sowie Python gut geeignet.<br />

Speziell mit Python lässt sich eine ganze Menge anstellen.<br />

Wer damit bereits ein bisschen Erfahrung gesammelt hat,<br />

könnte vielleicht Lust bekommen, seinen Sprachenhorizont<br />

zu erweitern. Auf den folgenden Seiten möchten wir Ihnen<br />

einige alternative Programmiersprachen genauer vorstellen.<br />

In diesem Beitrag hier geht es jedoch zunächst darum, wie<br />

man diese Sprachen auf dem <strong>Raspberry</strong> <strong>Pi</strong> installiert, um<br />

damit arbeiten zu können.<br />

Euphoria<br />

Um Euphoria installieren zu können, benötigen Sie zunächst<br />

die auf Ihre Distribution zugeschnittene Version von OpenEuphoria.<br />

Hinsichtlich der Operationen auf Gleitkommazahlen<br />

ist es ferner wichtig, ob die Distribution Hard Float oder Soft<br />

Float unterstützt, das heißt, ob sie die Gleitkommaeinheit in<br />

der <strong>Hardware</strong> des <strong>Raspberry</strong> <strong>Pi</strong> nutzt oder nicht. Wir spielen<br />

das Ganze einmal für die Raspbian-Distribution durch. Tippen<br />

Sie<br />

wget http://openeuphoria.org/eubins/linux/4.1.0/arm-32-bit/<br />

eubin-arm-cortex-a8-2012-01-13-ee49c6b8a340.tar.gz<br />

in die Kommandozeile. Dann entpacken Sie die Binärdistribution,<br />

erstellen einen Ordner dafür, ändern die Benutzerrechte<br />

und kopieren Euphoria in den Ordner:<br />

gunzip eubin-arm-cortex-a8-2012-01-13-ee49c6b8a340.tar.gz<br />

tar -xvf eubin-arm-cortex-a8-2012-01-13-ee49c6b8a340.tar<br />

sudo mkdir -p /usr/share/euphoria/bin<br />

sudo chown -R pi.users /usr/share/euphoria/<br />

mv *.tar ../.<br />

cp * /usr/share/euphoria/bin/.<br />

Damit die entsprechenden Tools verwendet werden können,<br />

wo immer sie benötigt werden, muss Euphoria noch der<br />

PATH-Variablen hinzugefügt werden. Öffnen Sie dazu die<br />

.bashrc-Datei mit<br />

nano ~/.bashrc<br />

und hängen Sie Folgendes ans Ende der Datei, bevor Sie sie<br />

speichern:<br />

PATH=$PATH:/usr/share/euphoria/bin<br />

export PATH<br />

Um sicherzugehen, dass der Pfad korrekt eingerichtet ist und<br />

Euphoria funktioniert, führen Sie noch folgende Kommandos<br />

aus:<br />

source ~/.bashrc<br />

echo $PATH<br />

eui -v<br />

Wenn alles in Ordnung ist, können Sie mithilfe von wget die<br />

Quelldateien sowie Beispiele von http://sourceforge.net/<br />

projects/rapideuphoria/files/Euphoria/4.0.5/<br />

euphoria-LINUX-4.0.5-src.tar.gz herunterladen. Nähere<br />

Infos zum Problem Hard Float versus Soft Float bekommen<br />

Sie unter http://openeuphoria.org/wiki/view/<br />

EuphoriaAnd<strong>Raspberry</strong><strong>Pi</strong>.wc.<br />

Go<br />

Auch bei Go besteht das Gleitkommaproblem. Damit der<br />

Code funktioniert, muss er für den <strong>Raspberry</strong> <strong>Pi</strong> kompiliert<br />

sein. Immerhin ist es kein Problem, Programme, die auf dem<br />

<strong>Raspberry</strong> <strong>Pi</strong> geschrieben und kompiliert worden sind, auf<br />

anderen Plattformen auszuführen.<br />

Euphoria: Sie können den Code mit Syntaxhervorhebung<br />

bearbeiten und im Hintergrund laufen lassen.<br />

136


Programmiersprachen<br />

Die Installation von Go ist ziemlich simpel. Öffnen Sie dazu<br />

Ihre .bashrc-Datei und fügen Sie die nachfolgenden Variablen<br />

ein:<br />

GOARM=5<br />

GOOS=linux<br />

GOARCH=arm<br />

GOPATH= (your package root)<br />

Die erste Zeile ist die wichtigste, denn diese legt fest, dass für<br />

einen ARMv5-Chip kompiliert werden soll.<br />

Holen Sie sich dann die relevanten Pakete vom Go-Repository<br />

auf Google Code und kompilieren Sie sie (Letzteres dauert<br />

etwa eine Stunde):<br />

sudo apt-get install mercurial<br />

sudo apt-get install git<br />

hg clone -u tip https://code.google.com/p/go<br />

cd go/src<br />

./all.bash<br />

Wenn Sie einen <strong>Raspberry</strong> <strong>Pi</strong> mit 256 MB RAM benutzen,<br />

stellen Sie sicher, dass in der Konfigurationsdatei raspi-config<br />

die Speicheraufteilung so gewählt ist, dass der Anteil, der für<br />

die CPU reserviert ist, möglichst groß ist.<br />

C++<br />

C++ ist eine tolle, raffinierte Programmiersprache, aber leider<br />

auch sehr kompliziert. Es kann Ihnen passieren, dass Sie sich<br />

schon bald nach Python zurücksehnen. Falls Sie sich an C++<br />

herantrauen, ist aber zumindest die Installation einfach.<br />

Wenn Sie bereits die Entwicklungsumgebung Geany (siehe<br />

Seite 96) auf Ihrem <strong>Raspberry</strong> <strong>Pi</strong> haben, brauchen Sie gar<br />

nichts weiter zu tun, sondern können sofort mit C++ loslegen.<br />

Es lohnt sich, darüber hinaus die Bibliothek BCM2835<br />

von Mike McCauley zu holen, denn damit können Sie im Rahmen<br />

Ihrer C- und C++-Projekte die GPIO-<strong>Pi</strong>ns des <strong>Raspberry</strong><br />

<strong>Pi</strong> steuern. Sie finden alle nötigen Anleitungen unter<br />

www.raspberry-projects.com/pi/programming-in-c/<br />

c-libraries/bcm2835-by-mike-mccauley.<br />

Lisp<br />

Die Polnische Notation (oder Präfixnotation) mag insbesondere<br />

für Einsteiger eine Herausforderung darstellen, doch<br />

Lisp lohnt dennoch die Anstrengung. Falls Sie Raspbian auf<br />

Ihrem <strong>Raspberry</strong> <strong>Pi</strong> verwenden, können Sie ohne Umwege<br />

CLISP, eine Implementierung von Common Lisp, verwenden.<br />

Geben Sie dazu lediglich folgendes Kommando:<br />

sudo apt-get install clisp<br />

Damit holen Sie sich das komplette Paket. Common Lisp,<br />

eine objektorientierte Programmiersprache, erschien zuerst<br />

im Jahr 1984. Ab Seite 146 in diesem <strong>Handbuch</strong> erfahren Sie<br />

mehr darüber.<br />

Go: Datei gelöscht und beim nächsten Durchlauf wiederhergestellt. Es läuft<br />

auch outputDone().<br />

Fortran<br />

Um Fortran laufen zu lassen, brauchen Sie keine speziellen<br />

Tools, sondern nur einen Compiler. Es gibt eine Auswahl<br />

möglicher Compiler für den <strong>Raspberry</strong> <strong>Pi</strong>, allerdings spielt es<br />

aus technischer Sicht keine große Rolle, welchen Sie verwenden,<br />

außer vielleicht bei sehr umfangreichen Programmen.<br />

Holen Sie sich zum Beispiel den Compiler gfortran mit<br />

dem Paket-Manager.<br />

Lua<br />

Lua, eine tolle Skriptsprache, ist auf einem Raspbian-System<br />

kinderleicht zu installieren. Tippen Sie apt-get install lua in<br />

ein Terminal, und Sie erhalten die Kommandozeilenversion.<br />

Es sind aber auch grafische Benutzeroberflächen und interessante<br />

Tools erhältlich. Wir empfehlen GameCake, bei dem<br />

Sie zusätzlich zu den normalen Bibliotheken 2D-Grafik und<br />

Joystick-Unterstützung bekommen. GameCake können Sie<br />

auf http://cake.4lfa.com/gamecake herunterladen.<br />

Lua: Den Code<br />

ein paarmal<br />

laufen lassen,<br />

dann die Datei<br />

ausgeben, um zu<br />

sehen, ob alles in<br />

Ordnung ist.<br />

Lisp: Addition, Listen, Variablendefinition in Slime.<br />

137


Programmiersprachen<br />

Begeisterung für<br />

OpenEuphoria<br />

Wir begeben uns nach Euphoria und entdecken eine gut lesbare,<br />

leicht erlernbare und überaus schnelle Sprache.<br />

Die Programmiersprache Euphoria kam im Jahre 1993<br />

als Shareware auf den Markt. Mittlerweile steht sie<br />

unter einer Open-Source-Lizenz, wird ständig weiterentwickelt<br />

und ist für die unterschiedlichsten Plattformen<br />

inklusive Linux erhältlich. Obwohl Euphoria eine Interpreter-<br />

Sprache ist, ist sie extrem schnell. Zudem kann sie in C übersetzt<br />

und anschließend kompiliert werden. Und mit einem<br />

Minimum an Interpunktionszeichen sowie mit knapp gehaltenen<br />

Schlüsselwörtern ist Euphoria auch noch schnell zu<br />

schreiben.<br />

Wer sich der Objektorientierten Programmierung verschrieben<br />

hat, wird dennoch keine Freude an dieser Sprache<br />

haben: Mit dem prozedurale Aufbau, der kaum vorhandenen<br />

Typenüberprüfung und den reduzierten<br />

Funktionsdefinitionen entspricht Euphoria nicht mehr den<br />

Paradigmen der heutigen Zeit. Und da die zahlreichen<br />

Schlüsselwörter meist englischen Begriffen entsprechen,<br />

erinnert ein Listing stets an Pseudocode – aber es ist<br />

Pseudocode, der tatsächlich funktioniert.<br />

Sie finden den Download auf der OpenEuphoria-Webseite<br />

http://www.openeuphoria.org. Die derzeit stabile Version<br />

hat die Nummer 4.0.5 und ist für Debian und Windows sowie<br />

als generisches tar.gz verfügbar. Der Quellcode sowie<br />

Nightly-Builds stehen ebenfalls zum Download bereit.<br />

Wenn Sie das tar.gz-Paket installieren, dann sollten Sie es<br />

im Verzeichnis /usr/local entpacken. Anschließend editieren<br />

Sie /etc/profile oder erstellen eine eu.cfg-Datei; beides<br />

mit folgendem Inhalt:<br />

/pfad/zu/euphoria/include<br />

Damit teilen Sie Euphoria mit, wo die<br />

Standardbibliotheken zu finden sind. Alternativ können Sie<br />

auch die Umgebungsvariable $EUINC definieren.<br />

/path/to/euphoria/include<br />

Dies informiert Euphoria über den Ort der unterschiedlichen<br />

Standardbibliotheken. Die Umgebungsvariabel $EUINC<br />

liefert übrigens das gleiche Ergebnis.<br />

Hello World<br />

Wir starten mit dem Programm Hello World. Dazu erstellen<br />

wir eine Datei helloworld.ex (Konsolenprogramme verwenden<br />

gewöhnlich die Erweiterung .ex, GUI-Anwendungen<br />

die Erweiterung .exw und importierte Dateien und<br />

Bibliotheken die Erweiterung .e):<br />

puts(1, “Hello, World\n”)<br />

Sie starten das Programm mit eui helloworld.ex und sollten<br />

nun die zu erwartende Ausgabe sehen.<br />

puts() steht für „put string“ und begegnet Ihnen in auch<br />

vielen anderen Programmiersprachen. Hier erwartet es zwei<br />

Argumente: <strong>Das</strong> erste Argument sagt Euphoria, wohin die<br />

Ausgabe gehen soll (1 ist das Datei-Handle der<br />

Standardausgabe), das zweite ist der auszugebende String.<br />

printf() wird ebenfalls unterstützt und eignet sich für komplexere<br />

oder formatierte Ausgaben.<br />

Um in eine echte Datei zu schreiben, öffnen wir zuerst die<br />

Datei und weisen das erhaltene Datei-Handle einer Integer-<br />

Variablen zu:<br />

integer myfile<br />

constant STDERR = 2<br />

constant STDOUT = 1<br />

myfile = open(“myfile.txt”, “w”)<br />

if myfile = -1 then<br />

puts(STDERR, “couldn’t open myfile\n”)<br />

else<br />

puts(STDOUT, “file opened\n”)<br />

puts(myfile, “Hello, World\n”)<br />

close(myfile)<br />

end if<br />

In Euphoria gibt es nur vier Dateitypen, integer ist eine<br />

davon. Hier deklarieren wir die die Variable myfile als integer,<br />

anschließend versuchen wir, die Datei mit Schreibzugriff<br />

zu öffnen. Wenn dies gelingt, dann erhalten wir eine positive<br />

Ganzzahl als Datei-Handle. Wenn es fehlschlägt, dann erhalten<br />

wir -1. Wir prüfen den Erfolg (die if/then-Syntax birgt keinerlei<br />

Überraschungen, aber achten Sie auf das abschließende<br />

end if) und handeln entsprechend. Wir schreiben nicht<br />

nur in die Datei, sondern auch in die Standardausgabe oder<br />

in die Standardfehlerausgabe, deren Datei-Handles 1 und 2<br />

immer verfügbar sind. Nach getaner Arbeit schließen wir die<br />

Datei.<br />

Typen und Unterprogramme<br />

Nun wagen wir uns an eine größere Aufgabe. Wir entwickeln<br />

ein Programm für die Zeitmanagementmethode Pomodoro,<br />

das uns nach einer vorgegebenen Zeitspanne an etwas erinnert.<br />

In der ersten Programmversion lassen wir uns nur wenige<br />

Sekunden warten:<br />

include std/os.e<br />

global integer Seconds = 5<br />

global object Message = “Time’s up!\n”<br />

procedure ring_alarm(object alarm_text)<br />

puts(1, alarm_text)<br />

end procedure<br />

procedure run_alarm()<br />

sleep(seconds)<br />

ring_alarm(message)<br />

end procedure<br />

138


Programmiersprachen<br />

run_alarm()<br />

In der ersten Zeile importieren wir eine<br />

Standardbibliothek, mit der wir unter anderem Zugriff auf die<br />

systemeigene sleep()-Funktion haben. Dann deklarieren wir<br />

zwei Variable. Wie bereits erwähnt, stehen uns dafür nur vier<br />

Typen zur Auswahl:<br />

object (kann jeden Wert annehmen);<br />

sequence (eine Sequenz beliebiger Objekte);<br />

atom (Zahlen aller Art);<br />

integer (Ganzzahlen zwischen -1073741824 und<br />

+1073741823; für größere Ganzzahlen muss atom verwendet<br />

werden)<br />

Die Definition eigener Datentypen ist ebenfalls möglich, würde<br />

den Rahmen dieses Tutorials aber sprengen.<br />

Da numerische Operationen mit integer sind schneller als<br />

die gleichen Operationen mit atom sind, wählen wir für die<br />

Seconds-Variable den Typ integer.<br />

Ein Euphoria-Unterprogramm ist entweder eine Prozedur<br />

(procedure) oder eine Funktion (function). Eine Prozedur<br />

kann Parameter entgegennehmen. Eine Funktion kann dies<br />

auch, zusätzlich gibt sie einen Wert zurück. Sowohl<br />

Prozeduren als auch Funktionen werden mit end<br />

[procedure|function] abgeschlossen und wie üblich werden<br />

beide durch ihren Namen aufgerufen.<br />

In unserem Beispiel haben wir den Programmcode auf<br />

zwei sehr einfache und sehr kurze Prozeduren verteilt. Dies<br />

vereinfacht die Erweiterung unseres Programms – immerhin<br />

wissen wir bereits jetzt, dass der Code in den nächsten<br />

Schritten weiter anwachsen wird. Speichern Sie den Code in<br />

der Datei pomodoroalarm.ex und starten Sie das Programm<br />

mit eui pomodoroalarm.ex. Nach fünf Sekunden sollten<br />

Sie in der Konsole eine Meldung sehen.<br />

Coding-Standards<br />

Fünf Sekunden sind zum Testen okay, aber die Pomodoro-<br />

Technik schreibt 25 Minuten vor. Also passen wir das<br />

Programm entsprechend an:<br />

global atom Seconds<br />

function set_alarm(atom minutes)<br />

return minutes * 60<br />

end function<br />

procedure run_alarm()<br />

Seconds = set_alarm(25)<br />

-- rest of procedure as before<br />

end procedure<br />

Wenn Sie das Programm starten, dann werden Sie nach<br />

25 Minuten den Alarm sehen. Für weitere Tests empfehlen<br />

wir, die 25 mit einem kleinen Wert wie 0.1 zu ersetzen.<br />

Beachten Sie, dass minutes den Typ atom hat, ansonsten<br />

wären wir auf ganze Minuten beschränkt. Auch Seconds hat<br />

nun diesen Datentyp, da es sonst Fehlermeldungen hageln<br />

Euphoria in Editoren<br />

würde: Würden wir set_alarm(0.01) aufrufen, dann wäre das<br />

Ergebnis die Zahl 0.6, die wiederum nicht einer integer-Variable<br />

zugewiesen werden kann.<br />

Ein Hinweis auf Coding-Standards: In Euphoria ist es<br />

üblich, dass der Name lokaler Variablen kleingeschrieben<br />

wird, Konstantennamen nur aus Großbuchstaben bestehen,<br />

globale Variablen mit Großbuchstaben beginnen und dass<br />

Unterstriche einzelne Namensbestandteile trennen.<br />

Sie können sich an diese Standards halten, eine technische<br />

Notwendigkeit dafür besteht jedoch nicht. Beachten Sie<br />

aber, dass Euphoria zwischen Groß- und Kleinschreibung<br />

unterscheidet.<br />

Zurück zu Pomodoro: Nach 25 Minuten Arbeit schreibt<br />

das System eine Pause von fünf Minuten vor. Um unser<br />

Programm entsprechend anzupassen, legen wir die beiden<br />

Zeitspannen in einer sequence ab und bearbeiten diese in<br />

einer Schleife:<br />

global object Work_message = “Arbeitszeit beendet\n”<br />

global object Break_message = “Pause beendet!\n”<br />

global atom Work_minutes = 25<br />

global atom Break_minutes = 5<br />

procedure run_alarm()<br />

sequence pomodoro = {Work_minutes, Break_minutes}<br />

sequence pomodoro_message = {Work_message, Break_message}<br />

for i=1 to length(pomodoro) by 1 do<br />

sleep(set_alarm(pomodoro[i]))<br />

ring_alarm(pomodoro_message[i])<br />

end for<br />

end procedure<br />

Dieser Code ist ziemlich selbsterklärend. Wir erstellen<br />

zwei Sequenzen; eine für die Zeitspannen und eine für die<br />

Alarmmeldungen. Dann verwenden wir die eingebaute length()-Funktion,<br />

um über die Sequenzen zu iterieren und für<br />

jeden Eintrag sleep() und ring_alarm() aufzurufen. Beachten<br />

Sie, dass Euphoria den Indexwert 1 für den ersten Eintrag<br />

verwendet.<br />

Der Code ist fehleranfällig: Was wäre, wenn pomodoro<br />

und pomodoroMessage unterschiedliche Längen hätten?<br />

Diesen potenziellen Absturz können wir umgehen, wenn wir<br />

eine Sequenz von Sequenzen verwenden, um die<br />

Zeitspannen und Nachrichten zu verwalten:<br />

procedure run_alarm()<br />

sequence pomodoro = {{Work_minutes, Work_message},<br />

{Break_minutes, Break_message}}<br />

for i=1 to length(pomodoro) by 1 do<br />

sleep(set_alarm(pomodoro[i][1]))<br />

ring_alarm(pomodoro[i][2])<br />

end for<br />

end procedure<br />

Ein ähnliches Ergebnis erhielten wir auch, wenn wir andere<br />

globale Variable definieren würden:<br />

Schnelltipp<br />

Um den Programmablauf<br />

zu verfolgen<br />

(also ihn Anweisung<br />

für Anweisung zu<br />

durchschreiten),<br />

schreiben Sie an den<br />

Anfang Ihres Programms<br />

diese<br />

zwei Zeilen:<br />

with trace<br />

trace(1)<br />

Euphoria wird mit dem speziell angepassten<br />

Editor ed.ex ausgeliefert. Um diesen zu verwenden,<br />

fügen Sie das Euphoria-bin-Verzeichnis dem<br />

PATH in .bashrc hinzu:<br />

PATH=$PATH:/usr/share/euphoria/bin<br />

Um den Editor zu starten, tippen Sie<br />

PATH=$PATH:/usr/share/euphoria/bin<br />

To use it, type<br />

eui ed.ex file.ex<br />

Im Vergleich zu Editoren wie Vim oder Emacs ist<br />

macht ed einen schlichten Eindruck, aber immerhin<br />

verfügt er über Syntax-Highlighting. Mit einer<br />

Besonderheit ist er diesen beiden Konkurrenten<br />

überlegen: Wenn Sie direkt nach einem Euphoria-<br />

Fehler ed ohne Argumente starten, dann liest er<br />

die ex.err-Datei aus und springt direkt zu derjenigen<br />

Code-Stelle, an der der Fehler aufgetreten<br />

ist.<br />

In der Praxis werden Sie jedoch schnell aus ed<br />

herauswachsen und sich nach Alternativen<br />

umsehen. Im OpenEuphoria-Wiki sind weitere<br />

Editoren aufgelistet.<br />

Um Vim wenigstens Syntax-Highlighting und<br />

Einrückungen beizubringen, installieren Sie die<br />

vom eu-editor bereitgestellten Dateien in die<br />

geeigneten Vim-Verzeichnisse und fügen Sie diese<br />

Zeile der Datei filetype.vim hinzu:<br />

au BufNewFile,BufRead *.ex setf euphoria<br />

Auch für MicroEmacs, Nano und andere stellt<br />

das eu-editor Projekt ähnliche Features bereit<br />

139


Programmiersprachen<br />

global sequence Work_settings = {Work_minutes, Work_message}<br />

global sequence Break_settings = {Break_minutes, Break_message}<br />

procedure run_alarm()<br />

sequence pomodoro = {Work_settings, Break_settings}<br />

-- for-Schleife wie zuvor<br />

end procedure<br />

Wie Sie sehen, führen in Euphoria viele Wege zum gleichen<br />

Ziel. Welchen Weg Sie wählen, bleibt Ihren persönlichen<br />

Vorlieben überlassen.<br />

Als Nächstes werden wir den Benutzer fragen, wie lange<br />

er arbeiten und pausieren möchte. Dazu erzeugen wir eine<br />

Funktion, die den Benutzer zur Eingabe auffordert:<br />

include std/io.e<br />

include std/get.e<br />

procedure get_alarm_times()<br />

puts(STDOUT, “Please enter work minutes: “)<br />

sequence result = get(STDIN)<br />

Work_minutes = result[2]<br />

puts(STDOUT, “Please enter break minutes: “)<br />

sequence result = get(STDIN)<br />

Break_minutes = result[2]<br />

end procedure<br />

procedure run_alarm()<br />

get_alarm_times()<br />

-- rest is as before<br />

end procedure<br />

Die Bibliothek std/io.e definiert für uns die Konstanten<br />

STDOUT, STDIN und STDERR. get() (aus der Bibliothek<br />

std/get.e) liest einen String aus einer Datei bzw. von der<br />

Standardeingabe und konvertiert ihn in eine Zahl. Wir hätten<br />

auch andere Funktionen wie gets() verwenden können, aber<br />

diese hätten nicht die automatische Umrechnung in eine<br />

Zahle für uns übernommen. get() nimmt folgende Parameter<br />

entgegen:<br />

get(integer file, integer offset = 0, integer answer = GET_SHORT_<br />

ANSWER)<br />

file ist das Datei-Handle, aus dem gelesen werden soll.<br />

offset ist die Stelle innerhalb dieser Datei, ab der gelesen<br />

wird. answer legt fest, welche Werte get() zurückliefern<br />

soll:<br />

GET_SHORT_ANSWER : {integer return_status, object value_read}<br />

GET_LONG_ANSWER : {integer return_status, object value_read,<br />

integer num_characters_read, integer initial_whitespace}<br />

Der return_status kann GET_SUCCESS, GET_EOF,<br />

GET_FAIL oder GET_NOTHING sein. Der Einfachheit halber<br />

werten wir den Status nicht aus – in dem Wissen, dass fehlerhafte<br />

Eingaben das Programm zum Absturz bringen werden.<br />

Da wir aus STDIN lesen, können wir auf die Angabe von offset<br />

und answer verzichten und erhalten den kürzeren der<br />

beiden Rückgabewerte. Den gesuchten Wert finden wir an<br />

zweiter Stelle der Sequenz und speichern ihn in Work_minutes<br />

bzw. Break_minutes.<br />

Wenn Sie das Programm nun starten, dann müssen Sie<br />

feststellen, dass die neuen Werte offenbar ignoriert werden.<br />

Was passiert hier?<br />

<strong>Das</strong> Problem ist, dass sich die Zeitspannen-Variablen<br />

zwar verändern, diese Änderungen aber nicht automatisch<br />

an Work_settings und Break_settings weitergereicht werden.<br />

Es gibt mehrere Lösungen dafür:<br />

-- Option 1<br />

procedure get_alarm_times()<br />

-- as above<br />

Work_settings[1] = Work_minutes<br />

Break_settings[1] = Break_minutes<br />

end procedure<br />

-- Option 2<br />

procedure run_alarm()<br />

get_alarm_times()<br />

sequence pomodoro = {{Work_minutes, workMessage},<br />

{Break_minutes, breakMessage}}<br />

-- as before<br />

end procedure<br />

Ein Zwischenkommentar über Kommentare: Euphoria<br />

verwendet -- für einzeilige Kommentare und /* … */ für<br />

mehrzeilige.<br />

Externe Musik<br />

Wenn Sie gerade tief in Ihrer Arbeit versunken sind, dann<br />

werden Sie die kleine Textmeldung im Konsolenfenster vermutlich<br />

nicht bemerken. Ein Alarmsound wäre die Lösung,<br />

doch leider gibt es nur in der Windows-Version von Euphoria<br />

Zugriff auf Systemklänge, nicht aber für Linux. Also werden<br />

wir ein externes Programm starten und dieses eine MP3-<br />

Datei abspielen lassen:<br />

global object Play_alarm_command = “mpg123 -q alarm.mp3”<br />

procedure ring_alarm(object alarm_text)<br />

puts(1, alarm_text)<br />

system(Play_alarm_command, 2)<br />

end procedure<br />

Wir haben die Anwendung mpg123 gewählt, da sie ein<br />

einfaches Kommandozeilenprogramm ist, welches ganz<br />

ohne eigene Textausgabe laufen kann (die Option -q).<br />

Wenn Sie eine andere Anwendung bevorzugen, dann<br />

können Sie diese natürlich auch verwenden – die system()-Funktion<br />

wird sie in jedem Fall starten. Der Modus<br />

2 besagt, dass der Grafikmodus nach Programmende<br />

nicht wiederhergestellt wird. Da mpg123 den Bildschirm<br />

nicht verwendet, müssen wir uns um den Grafikmodus<br />

nicht sorgen.<br />

Wenn Sie dieses Programm starten, dann wird<br />

irgendwann die Musik anfangen zu spielen. Erst nach-<br />

Weitere Features von Euphoria<br />

OpenEuphoria enthält in der aktuellen Version<br />

zahllose APIs, die für nahezu jeden Einsatzzweck<br />

effiziente und bestens dokumentierte Funktionen<br />

bereitstellen. So gibt es APIs für Mathematik und<br />

für internetspezifische Techniken wie HTTP, DNS<br />

und URLs, für die Unterstützung von lokalisierten<br />

Anwendungsoberflächen und für vieles mehr.<br />

Euphoria ermöglicht auch echtes Multitasking,<br />

was insbesondere die Entwickler von Spielen<br />

oder lange andauernden Hintergrundaufgaben<br />

interessieren dürfte. Für die Sicherheitsexperten<br />

gibt es mit dem Import std/unittest.e und dem<br />

Programm eutest automatisierte Unit-Tests zum<br />

Überprüfen des korrekten Programmablaufs.<br />

Wenn Sie den grafischen Weg einschlagen möchten,<br />

dann haben Sie mit std/graphics.e Zugriff<br />

auf Cross-Plattform-Konsolengrafiken und mit<br />

std/image.e auf Bitmaps. Alternativ gibt es auch<br />

eine GTK-Grafikbibliothek auf http://eugtk.wikispaces.com,<br />

die sogar Glade unterstützt.<br />

Die Nutzung von C-Code ist ebenfalls möglich:<br />

Mit open_dll(), Funktionsdeklarationen und c_<br />

func() oder c_proc() steht dem Zugriff auf beliebige<br />

.dll- und .so-Dateien nichts im Weg.<br />

Selbst für Datenbankaufgaben ist die Sprache<br />

geeignet: Sie kann jede Standarddatenbank<br />

ansprechen und liefert für die etwas kleineren<br />

Projekte mit dem Euphoria Database System<br />

auch eine eigene, Euphoria-orientierte Datenbank<br />

mit.<br />

140


Programmiersprachen<br />

dem Sie mit [Strg]-[C] die Musik beenden, läuft das<br />

Programm weiter. In diesem Fall dürfte das der<br />

gewünschte Ablauf sein, in anderen Fällen möchten Sie<br />

aber vielleicht, dass Ihr Hauptprogramm während der<br />

Musikwiedergabe weiterläuft. Dieses sogenannte<br />

Multitasking starten Sie mit dem fork()-Befehl. Weitere<br />

Informationen zum Multitasking finden Sie in der<br />

Euphoria-Dokumentation.<br />

Ein Nachtrag zur if/else-Syntax in Euphoria: Auch dieser<br />

Blocktyp wird mit einem end * abgeschlossen. Wenn Sie<br />

einen else-Zweig benötigen, dann wird dieser auf folgende<br />

Weise verwendet:<br />

if a = b then<br />

-- - Anweisungen<br />

elseif a = c then<br />

-- andere Anweisungen<br />

else<br />

-- ganz andere Anweisungen<br />

end if<br />

Wir machen noch schnell eine weitere<br />

Programmverbesserung: Wir fragen den Benutzer, wie<br />

viele Wiederholungen der Arbeit/Pause-Kombinationen<br />

(die Pomodoros) er haben möchte oder ob er alternativ<br />

die 25/5-Minuten-Intervalle ändern möchte. Die Abfrage<br />

findet in der Funktion get_number_pomodoros() statt<br />

und die Fallunterscheidung in set_timing().<br />

Wenn der Benutzer 0 gewünschte Pomodoros angibt,<br />

dann lassen wir ihn seine eigenen Zeitintervalle festlegen.<br />

In jedem Fall aber verwenden wir in run_alarm() zwei<br />

for-Schleifen, um über die gewünschte Pomodoro-Anzahl<br />

und über die beiden Zeitspannen zu iterieren.<br />

Operationen & Sequenzen<br />

Die verschachtelten for-Schleifen machen einen unaufgeräumten<br />

Eindruck. Ein Blick in das Euphoria-<strong>Handbuch</strong> zeigt<br />

zahllose Möglichkeiten, mehrere Sequenzen miteinander zu<br />

verbinden oder einzelne Sequenzen zu wiederholen. Da gibt<br />

es unter anderem den &-Operator sowie die Funktionen<br />

append() und repeat(). Damit sollten wir eine Alarm-<br />

Sequenz wie diese erzeugen können:<br />

{{Work_minutes, Work_message}, {Break_minutes, Break_message},<br />

{Work_minutes, Work_message}, {Break_minutes, Break_message}}<br />

In der Praxis stellt sich dieses Unterfangen als recht kompliziert<br />

heraus, da jede Verkettungsmethode ihre ganz speziellen<br />

Eigenheiten hat:<br />

append({a, b}, {c, d}) = {a, b, {c, d}}<br />

append({Work_minutes, Work_message}, {Break_minutes, Break_<br />

message})<br />

= {Work_minutes, Work_message, {Break_minutes, Break_message}}<br />

{a, b} & {c, d} = {a, b, c, d}<br />

{Work_minutes, Work_message} & {Break_minutes, Break_message}<br />

= {Work_minutes, Work_message, Break_minutes, Break_message}<br />

repeat({a, b, c, d}, 2) = {{a, b, c, d}, {a, b, c, d}}<br />

repeat({Work_minutes, Work_message, Break_minutes, Break_<br />

message}, 2)<br />

= {{Work_minutes, Work_message, Break_minutes, Break_message}<br />

{Work_minutes, Work_message, Break_minutes, Break_message}}<br />

repeat({a, b, {c, d}}, 2) = {{a, b, {c, d}}, {a, b, {c, d}}<br />

repeat({Work_minutes, Work_message, {Break_minutes, Break_<br />

message}}, 2)<br />

= {{Work_minutes, Work_message, {Break_minutes, Break_message}}<br />

{Work_minutes, Work_message, {Break_minutes, Break_message}}}<br />

Damit bleiben uns zwei Möglichkeiten, unsere<br />

Alarmsequenz mit Sequenz-Operationen zu erzeugen:<br />

procedure set_timing()<br />

Number_pomodoros = get_number_pomodoros()<br />

if Number_pomodoros = 0 then<br />

get_alarm_times()<br />

Number_pomodoros = 1<br />

end if<br />

Alarm_sequence = repeat(Work_settings & Break_settings,<br />

Number_pomodoros)<br />

/* Alarm_sequence now looks like {{W_min, W_mess, B_min, B_<br />

mess},<br />

{W_min...}, ... } */<br />

end procedure<br />

procedure run_alarm()<br />

set_timing()<br />

for i=1 to Number_pomodoros by 1 do<br />

sleep(set_alarm(Alarm_sequence[i][1]))<br />

ring_alarm(Alarm_sequence[i][2])<br />

sleep(set_alarm(Alarm_sequence[i][3]))<br />

ring_alarm(Alarm_sequence[i][4])<br />

end for<br />

end procedure<br />

Dies erzeugt eine Sequenz einer vierteiligen Sequenz. Die<br />

Alternative dazu lautet:<br />

procedure set_timing()<br />

-- as above<br />

Alarm_sequence = repeat({Work_settings, Break_settings},<br />

Number_pomodoros)<br />

/* Alarm_sequence now looks like {{{W_min, W_mess}, {B_min,<br />

B_mess}},<br />

{{W_min...}, {B_min..}}, ... }*/<br />

end procedure<br />

procedure run_alarm()<br />

set_timing()<br />

for i=1 to Number_pomodoros by 1 do<br />

sleep(set_alarm(Alarm_sequence[i][1][1]))<br />

ring_alarm(Alarm_sequence[i][1][2])<br />

-- could also use another for loop here<br />

sleep(set_alarm(Alarm_sequence[i][2][1]))<br />

ring_alarm(Alarm_sequence[i][2][2])<br />

end for<br />

end procedure<br />

Beide Varianten sind nicht lesbarer als eine doppelte for-<br />

Schleife. Es bleibt Ihrem Geschmack überlassen, welche<br />

Lösung Sie wählen.<br />

Und weiter geht’s!<br />

Wie immer gibt es viele unterschiedliche Möglichkeiten und<br />

Ansätze, das jeweilige Programm zu verbessern.<br />

Beispielsweise könnten Sie mit einem Countdown Minute für<br />

Minute herunterzählen, oder Sie könnten eine hübsche und<br />

aufgeräumte Programmoberfläche mit großen Start-/Stop-<br />

Schaltern entwickeln. In diesem Tutorial sollten Sie jedenfalls<br />

jetzt bereits gelernt haben, dass Euphoria eine schnelle<br />

Sprache mit klaren Fehlermeldungen ist, in die man sich<br />

leicht einarbeitet.<br />

141


Programmiersprachen<br />

Ein kurzer<br />

Lehrgang in Go<br />

Go ist schnell und typsicher, bereinigt den Speicher automatisch<br />

und ist nebenläufig. Ein kurzer Blick auf die Sprache.<br />

Go, auch als Golang bekannt, ist eine Open-Source-<br />

Sprache mit statischer Typisierung. Der von Google<br />

entwickelte Compiler wurde entwickelt, um mit<br />

Nebenläufigkeit (also Multitasking) die Entwicklung beliebig<br />

skalierbarer Systeme zu ermöglichen und trotz aller Features<br />

einer modernen Sprache die Programme schnell zu kompilieren<br />

und ablaufen zu lassen. Solche Features sind insbesondere<br />

die Typsicherheit, die Reflexion und die Garbage<br />

Collection. Auch Objektorientierung wird unterstützt, allerdings<br />

ohne das übliche Klassenkonzept.<br />

Erste Schritte<br />

Um in die Go-Programmierung einzusteigen, installieren wir<br />

den Linux-Tarball, den wir von http://golang.org/doc/<br />

install herunterladen und mit sudo tar -C /usr/local/-<br />

zxf go1.1.1.linux-386.tar.gz im Verzeichnis /usr/local installieren.<br />

Anschließend passen wir die $PATH-<br />

Umgebungsvariable in .bashrc oder .profile an, damit<br />

auch /usr/local/go/bin im Suchpfad enthalten ist.<br />

Alternativ könnten wir auch den Quellcode selbst kompilieren<br />

und das Kompilat installieren. Anschließend<br />

erstellen wir uns eine Verzeichnisstruktur, die laut den<br />

Go-Richtlinien folgendermaßen aussehen muss:<br />

my_go_dir/<br />

bin/


Programmiersprachen<br />

möglich gewesen, was uns die Angabe des Zeilenumbruchs<br />

erspart hätte. Wie Sie sehen, fängt der Funktionsname mit<br />

einem Großbuchstaben an. Im Gegensatz zu vielen anderen<br />

Sprachen ist die richtige Groß- und Kleinschreibung von<br />

Bedeutung, beispielsweise werden nur Funktionen mit<br />

Großbuchstaben exportiert.<br />

Ihnen ist vermutlich auch aufgefallen, dass die einzelnen<br />

Zeilen nicht mit einem Semikolon abgeschlossen wurden.<br />

Tatsächlich sieht die Sprachdefinition diese Semikolons vor,<br />

aber der Compiler setzt diese im Normalfall selbst an die<br />

richtige Stelle. Wenn der Compiler ohne weitere<br />

Informationen auf einen Zeilenumbruch stößt, dann vermutet<br />

er ein logisches Zeilenende und setzt das Semikolon.<br />

Daher muss beispielsweise die öffnende Klammer einer<br />

Ein richtiges Programm<br />

Hello World ist unverzichtbar, um in einer neuen Sprache die<br />

ersten Schritte zu erlernen. Nun aber wollen wir etwas<br />

Nützlicheres schreiben. Wenn Sie bereits in der<br />

Vergangenheit Programmiersprachen erlernt haben, haben<br />

Sie vermutlich bereits die eine oder andere To-do-Liste entwickelt.<br />

Für unseren nächsten Schritt machen wir das exakte<br />

Gegenteil: Wir programmieren einen Schon-erledigt-<br />

Anwendung. Sie fragt den Benutzer, was er gerade gemacht<br />

hat, und speichert dies. Zunächst wird das Programm nach<br />

Input fragen und die Eingabe gleich wieder ausgeben.<br />

Erstellen Sie ein neues Verzeichnis src/repo.com/name/<br />

donelist und erzeugen Sie die Datei donelist.go:<br />

// Package runs a program to record items done and output them.<br />

package main<br />

import “fmt”<br />

var (<br />

done string<br />

)<br />

func main() {<br />

getDone()<br />

outputDone()<br />

}<br />

// getDone fragt den Benutzer nach einer erledigten Aufgabe func<br />

getDone() {<br />

fmt.Printf(“What did you do? “)<br />

fmt.Scan(&done)<br />

}<br />

// outputDone gibt die Aufgabe aus<br />

func outputDone() {<br />

fmt.Println(“You did:”)<br />

fmt.Println(done)<br />

}<br />

Kommentare dienen in Go auch dazu, mittels godoc automatisch<br />

eine Dokumentation zu erstellen. Daher sollten am<br />

Form- und Namenstandards<br />

if-Anweisung immer in der gleichen Zeile wie das if selbst<br />

stehen:<br />

if j < 1 {<br />

beliebige Anweisungen<br />

}<br />

// not....<br />

if j < 1<br />

{ // Upps. Der Compiler hat an das Ende der obigen Zeile ein<br />

Semikolon gesetzt<br />

}<br />

Zurück zu Hello World. Um das Programm zu kompilieren<br />

und auszuführen, wechseln Sie mit cd in das Verzeichnis<br />

repo.com/name/hello und tippen go install – gefolgt<br />

von $GOPATH/bin/hello – ein.<br />

Anfang jedes Paket ein paar erklärende Worte stehen, ebenso<br />

sollte über jeder öffentlichen Funktion deren<br />

Verwendungszweck und Anforderungen genannt sein.<br />

Im var-Block werden Variablen deklariert und gegebenenfalls<br />

mit einem Startwert initialisiert. Für Konstanten würde ein<br />

const-Block dienen. Da wir done in mehreren Funktionen dieses<br />

Pakets verwenden, wurde done im globalen var-Block definiert.<br />

fmt.Scan() liest aus der Standardeingabe in eine<br />

Variable. Beachten Sie das Et-Zeichen in &done: Wenn in<br />

Go eine Variable an eine Funktion übergeben wird, dann<br />

erhält die Funktion eine Kopie dieser Variable.<br />

Änderungen an dieser Kopie ändern nicht das Original.<br />

Hätten wir also fmt.Scan(done) aufgerufen, dann hätte sich<br />

nach Beendigung von getDone() nichts geändert, das Originaldone<br />

wäre noch immer leer. Um auch Originale an Funktionen<br />

zu übergeben, behilft man sich mit Verweisen (auch Zeiger,<br />

Referenzen oder Pointer genannt): Verweise zeigen auf den<br />

Speicherbereich, an dem die Variable liegt. In Go liefert &done<br />

also die Speicheradresse der Variablen done (beispielsweise<br />

12345678). fmt.Scan() dereferenziert diesen Verweis (mit<br />

*done), um an den Variablenwert zu gelangen. <strong>Das</strong> heißt, dass<br />

der Verweis &done für den Funktionsaufruf kopiert wurde,<br />

aber da die Kopie von 12345678 noch immer 12345678 ist,<br />

zeigt auch die Kopie an die richtige Adresse und Scan() kann<br />

das Original verändern.<br />

Kompilieren Sie das Programm mit go install und starten<br />

Sie es mit donelist. Sie werden nun nach einer Eingabe<br />

gefragt. Geben Sie zunächst ein einzelnes Wort ein und erfreuen<br />

Sie sich an der originalgetreuen Ausgabe. Wenn Sie es aber<br />

mit mehreren Wörtern versuchen, dann wird das Programm<br />

scheitern. Der Grund dafür ist die Funktion fmt.Scan(), deren<br />

Einsatzzweck das Einlesen eines einzelnen Wortes ist. Für<br />

mehrere Wörter brauchen wir also eine andere Lösung.<br />

Schnelltipp<br />

Sie werden häufig<br />

ein library.go-<br />

Paket im /lib-<br />

Verzeichnis erstellen,<br />

das mit<br />

package library<br />

beginnt, und eine<br />

application.<br />

go-Datei im /<br />

src-Verzeichnis.<br />

Letzteres startet<br />

package main und<br />

importiert library.<br />

Mit Go wird ein Tool namens gofmt ausgeliefert,<br />

das Ihren Code einliest und mit Standard-<br />

Einrückungen versieht. Bevor Sie Ihren Code<br />

anderen zeigen, sollten Sie ihn unbedingt durch<br />

dieses Tool laufen lassen. Auch die<br />

Namenskonventionen gilt es zu beachten:<br />

Paketnamen sind kurz und bestehen aus einem<br />

Wort in Kleinbuchstaben. Variablen und<br />

Funktionen in Kleinbuchstaben werden nicht<br />

außerhalb ihrer Paketgrenzen exportiert (sie sind<br />

also privat), Variable und Funktionen mit<br />

Großbuchstaben hingegen schon (sie sind daher<br />

public). Sie sollten dies stets beachten, wenn Sie<br />

sich für Ihre Variablen und Funktionen einen Namen<br />

ausdenken. Für lange Namen oder Zusammensetzungen<br />

mehrerer Wörter sind Binnenmajuskel<br />

(FunktionsName) sogar mit kleinem<br />

Anfangsbuchstaben (funktionsName) möglich.<br />

143


Programmiersprachen<br />

Schnelltipp<br />

Die eingebaute<br />

Funktion println()<br />

eignet sich zur<br />

Fehlersuche, für<br />

die Ausgabe zum<br />

Benutzer sollten<br />

Sie aber fmt.<br />

Println()<br />

verwenden.<br />

println() schreibt<br />

auf stderr und<br />

nicht auf stdout,<br />

zudem wird die<br />

Funktion möglicherweise<br />

aus der<br />

Sprache entfernt.<br />

Die erste<br />

Programm<br />

version läuft.<br />

Ignorieren Sie<br />

unbedingt den<br />

Compiler-Fehler<br />

in diesem Bild.<br />

Puffer in Go<br />

Eine Lösung des Multi-Wort-Problems wäre ein Array, das<br />

wir in einer Schleife mit fmt.Scan() befüllen. Der Aufwand<br />

wäre allerdings unverhältnismäßig hoch – immerhin würden<br />

wir fmt.Scan() zu etwas benutzen, wofür es nicht gedacht<br />

war. Stattdessen verwenden wir Buffer.IO aus dem<br />

bufio-Paket. Hier ist ein erster Ansatz, getDone() umzuschreiben<br />

(wir zeigen nur die Code-Änderungen):<br />

import (<br />

“bufio”<br />

“fmt”<br />

“os”<br />

)<br />

const delimiter = ‘\n’<br />

func getDone() {<br />

fmt.Printf(“What did you do? “)<br />

r := bufio.NewReader(os.Stdin)<br />

done, err := r.ReadString(delimiter)<br />

if err != nil {<br />

println(err)<br />

os.Exit(1)<br />

}<br />

}<br />

Der Versuch, dies zu kompilieren, endet mit einer<br />

Fehlermeldung:<br />

$ go install<br />

# repo.com/juliet/donelist<br />

./donelist.go:28: done declared and not used<br />

Deklaration in Go<br />

Woher kommt diese Fehlermeldung? Die Ursache ist hinter<br />

der :=-Zuweisung verborgen. In Go verwendet man :=, um<br />

Variablen in einer Anweisung zu deklarieren und zuzuweisen.<br />

Man kann := auch verwenden, um einer Variablen einen neuen<br />

Wert zuzuweisen – aber nur wenn diese Variable aus dem<br />

aktuellen Gültigkeitsbereich stammt und wenn mindestens<br />

eine andere Variable in dieser Anweisung neu deklariert wird.<br />

Der folgende Code würde daher funktionieren:<br />

func getDone() {<br />

fmt.Printf(“What did you do? “)<br />

r := bufio.NewReader(os.Stdin)<br />

myDone := “ping”<br />

myDone, err := r.ReadString(delimiter)<br />

if err != nil {<br />

println(err)<br />

os.Exit(1)<br />

}<br />

println(myDone)<br />

}<br />

Wenn Sie dies ausführen, dann würde jede Eingabe<br />

zunächst in myDone gespeichert und mit der Println()-<br />

Anweisung ausgegeben werden.<br />

Warum funktioniert es also für myDone, aber nicht für<br />

done? Weil done aus dem globalen Gültigkeitsbereich<br />

kommt und := daher eine neue, lokale Variable namens done<br />

erstellt. Mit folgendem Code umschiffen wir diese Klippe:<br />

func getDone() {<br />

fmt.Printf(“What did you do? “)<br />

r := bufio.NewReader(os.Stdin)<br />

line, err := r.ReadString(delimiter)<br />

if err != nil {<br />

println(err)<br />

os.Exit(1)<br />

}<br />

outputDone(line)<br />

}<br />

func outputDone(done string) {<br />

println(“You did:”)<br />

fmt.Println(done)<br />

}<br />

Dieser Code zeigt, wie man eine Funktion mit Argumenten<br />

deklariert: func funktionsName (variablenName variablenTyp).<br />

Außerdem kommt dieser Code ganz ohne globale<br />

Variable aus – gleichzeitig ist er aber recht unordentlich, da<br />

er nicht sauber zwischen Dateneingabe und -ausgabe trennt.<br />

Eine weitere Variante mit globaler Variante wäre Folgendes:<br />

func get_done() {<br />

fmt.Printf(“What did you do? “)<br />

r := bufio.NewReader(os.Stdin)<br />

line, err := r.ReadString(delimiter)<br />

if err != nil {<br />

println(err)<br />

os.Exit(1)<br />

}<br />

done = line<br />

}<br />

// And go back to calling output_done() with no arguments in<br />

main()<br />

Und noch eine Version:<br />

var err error<br />

done, err = r.ReadString(delimiter)<br />

Hier deklarieren wir zuerst die lokale err-Variable und verwenden<br />

anschließend das klassische = als Operator für die<br />

Zuweisung von r.ReadString() zu den beiden globalen und<br />

lokalen Variablen.<br />

Mit jeder der genannten Varianten sollte Ihr Programm<br />

nun mehrere Worte entgegennehmen und ausgeben können.<br />

Dateien in Go<br />

Wenn wir die Benutzereingaben in eine Datei speichern<br />

möchten, um sie eventuell später wiederzuverwenden,<br />

erwarten uns mit Go keine großen Überraschungen:<br />

import (<br />

“io/ioutil”<br />

)<br />

func main() {<br />

getDone()<br />

writeToFile()<br />

}<br />

func writeToFile() {<br />

t := []byte(done)<br />

err := ioutil.WriteFile(“>>output.txt”, t, 0644)<br />

if err != nil { panic(err) }<br />

}<br />

Dies ist die einfachste von zahllosen Möglichkeiten, Daten<br />

in eine Datei zu schreiben. Vorsicht: Bei großen<br />

Datenmengen wird dieser Ansatz fehlschlagen. Wir verwandeln<br />

done in einen byte-Slice und verwenden ioutil.<br />

WriteFile, um den Slice in eine Datei zu speichern. Und da<br />

wir gerade dabei sind, setzen wir die Dateiberechtigungen auf<br />

144


Programmiersprachen<br />

0644.Beachten Sie die Fehlerbehandlung, die auf Probleme<br />

beim Schreiben der Datei prüft.<br />

Zur Auflockerung ein kurzer Überblick über Slice: Ein Slice<br />

ist einem Array sehr ähnlich, hat aber keine feste Größe. Im<br />

obigen Beispiel haben wir den byte-Slice auf Basis des done-<br />

Strings erstellt. Man kann einen Slice auch mit der<br />

make-Funktion erstellen, man kann ihn re-slicen (also verkleinern),<br />

kopieren und vergrößern.<br />

Wenn Sie den Code testen und anschließend die output.<br />

txt-Datei öffnen, dann scheint das Programm korrekt zu<br />

funktionieren. Nach einem weiteren Programmstart zeigt<br />

sich jedoch, dass der alte Dateiinhalt überschrieben wurde.<br />

Da WriteFile() keinen Anhänge-Modus hat, verwenden wir<br />

eine andere Funktion:<br />

func writeToFile() {<br />

f, err := os.OpenFile(“output.txt”, os.O_APPEND|os.O_WRONLY,<br />

0644)<br />

if err != nil { panic(err) }<br />

defer f.Close()<br />

if _, err = f.WriteString(done); err != nil {<br />

panic(err)<br />

}<br />

}<br />

Hier öffnen wir zuerst die Datei mit os.OpenFile(), da wir<br />

in dieser Funktion den Dateimodus angeben können. In unserem<br />

Fall verwenden wir O_APPEND, um neue Daten an das<br />

Ende der bestehenden Datei anzuhängen, und O_WRONLY<br />

für den Schreibzugriff. Wieder geben wir<br />

Dateiberechtigungen an, die aber nur beim ersten Erstellen<br />

der Datei angewendet werden.<br />

Mit der defer-Anweisung vereinfacht Go die notwendigen<br />

Aufräumarbeiten. Die Anweisung legt die übergebene<br />

Funktion f.Close() auf einen Stapel und arbeitet diesen nach<br />

dem Ende der aktuellen Funktion ab. <strong>Das</strong> hat den Vorteil,<br />

dass f.Close() auch dann die Datei schließt, wenn in der<br />

Funktion ein schwerer Fehler auftritt (beispielsweise wenn<br />

WriteString() fehlschlägt).<br />

Der Code enthält eine weitere Form der<br />

Fehlerbehandlung: WriteString() ist in einem if-Statement<br />

eingebettet und die Funktion würde entsprechend verzweigen.<br />

Aber sobald wir output.txt löschen würden, scheitert<br />

dieser Ansatz. Also erstellen wir eine Funktion, welche die<br />

Existenz einer Datei testet und sie gegebenenfalls erstellt:<br />

func checkFileExists(file string) {<br />

if _, err := os.Stat(file); os.IsNotExist(err) {<br />

f, err := os.Create(file)<br />

if err != nil { panic(err) }<br />

f.Close()<br />

}<br />

}<br />

In diesem Code fällt der Unterstrich auf: _. Sie können ihn<br />

wie eine Variable in einer Zuweisung verwenden, wenn Sie an<br />

dem Wert nicht weiter interessiert sind. Im obigen Fall gibt<br />

os.Stat() eine FileInfo-Struktur und einen Fehlerwert<br />

zurück. Da wir nur an diesem Fehlerwert interessiert sind,<br />

schreiben wir die FileInfo-Struktur in _ und kümmern uns<br />

nicht mehr um diesen Wert.<br />

Da die Go-Erfinder all dies vorhergesehen haben, gibt es<br />

einen weitaus kürzeren Weg – wir verwenden einen zusätzlichen<br />

Flag für OpenFile():<br />

f, err := os.OpenFile(“output.txt”, os.O_APPEND|os.O_<br />

WRONLY|os.O_CREATE, 0644)<br />

Wenn Sie nun output.txt löschen und das Programm<br />

starten, dann wird output.txt automatisch neu erzeugt. Wenn<br />

Sie hingegen die Datei nicht löschen, dann wird die vorhandene<br />

Datei weiterverwendet.<br />

Datei gelöscht<br />

und neu erzeugt<br />

– nun muss nur<br />

noch outputDone()<br />

funktionieren.<br />

Einen Slice anzeigen<br />

Nun, da unsere Aufgaben in der Datei gespeichert sind, benötigen<br />

wir noch eine Methode, sie da wieder herauszuholen.<br />

Hier ist eine kurze Funktion dafür:<br />

func main() {<br />

outputWholeList()<br />

}<br />

var (<br />

outputFile = “output.txt”<br />

)<br />

func outputWholeList() {<br />

fileContent, err := ioutil.ReadFile(outputFile)<br />

if err != nil { panic(err) }<br />

allDones := strings.Split(string(fileContent), string(delimiter))<br />

for i, v := range allDones {<br />

fmt.Printf(“%d: %s \n”, i, v)<br />

}<br />

}<br />

ReadFile() rgibt den Dateiinhalt als byte-Slice zurück. Wir<br />

konvertieren die Bytes in einen String und verwandeln diesen<br />

mit string.Split() in einen String-Slice und speichern das<br />

Ergebnis in allDones. Schließlich verwenden wir das<br />

Schlüsselwort range, um über allDones zu iterieren. i ist<br />

dabei die Indexnummer (beginnend mit 0) und v der<br />

Schleifenwert. Printf() formatiert schließlich beides zu<br />

einem hübschen String.<br />

Wie Sie dies mit der main()-Funktion verknüpfen und<br />

in welcher Reihenfolge Sie die Unterfunktionen aufrufen,<br />

überlassen wir Ihnen. Bevor Sie aber ein großer Fan<br />

dieser jungen Programmiersprach werden, legen wir<br />

Ihnen noch ein Wort der Warnung ans Herz: Go ist nach<br />

wie vor in Entwicklung und etliche Sprachelemente dürften<br />

sich in den nächsten Monaten verändern.<br />

<strong>Das</strong> Programm<br />

läuft gut, aller<br />

dings ist die Leer<br />

zeile ein echter<br />

Schönheitsfehler.<br />

145


Programmiersprachen<br />

Listig mit Lisp<br />

Mit der Programmiersprache Lisp werden Sie lernen, anders zu<br />

denken und Klammern zu lieben.<br />

Lisp erblickte 1958 das Licht der Welt und ist damit<br />

(nach dem ein Jahr älteren Fortran) die zweitälteste<br />

Hochsprache, die noch immer in Gebrauch ist. Der<br />

Name leiten sich ab von LISt Processing, da der Code und die<br />

Daten in weiten Teilen auf Listen basieren. Streng genommen<br />

sind Code und Daten in Lisp sogar austauschbar.<br />

Lisp wurde in den letzten 60 Jahren stetig weiterentwickelt<br />

und an neue Gegebenheiten angepasst. So gibt es heutzutage<br />

drei weitverbreitete Dialekte::<br />

Common Lisp,gewann mit einem großen Standardwortschatz<br />

und einem Objektsystem seine alte Popularität zurück.<br />

Scheme, teilt sich wegen des eher minimalistischen und<br />

klaren Aufbaus nur wenige Features mit Common Lisp.<br />

Clojure, kompiliert direkt in den Bytecode der Java<br />

Virtual Machine und hat unter Java-Programmierern<br />

Freunde gefunden.<br />

Es gibt sogar Lisp-Dialekte, die als Skriptsprache verwendet<br />

werden. So gibt es beispielsweise Emacs-Lisp und Gimp<br />

Script-fu.<br />

Zum Einstieg in die Sprache eignen sich alle drei großen<br />

Dialekte. Im Folgenden werden wir Common Lisp verwenden,<br />

welcher nicht auf Klein- und Großschreibung achtet.<br />

Einstieg in Lisp<br />

Addition, Listen<br />

und Variablendefinition<br />

in<br />

Slime.<br />

Starten Sie SBCL/Slime (siehe Kasten auf dieser Seite), um<br />

zur Eingabeaufforderung zu gelangen (* oder CL_USER). Um<br />

die Syntax kennenzulernen, versuchen wir uns an einer einfachen<br />

Addition:<br />

* (+ 2 2)<br />

4<br />

* (+ 2 2 2)<br />

6<br />

* (+ 1 2 3 4)<br />

10<br />

Diese Zeilen zeigen zwei Grundlagen von Lisp. Da sind<br />

zum einen die runden Klammern, die jede Liste umschließen.<br />

Zum anderen stehen Funktionsnamen stets am Anfang einer<br />

Liste. Für die Addition darf die Liste beliebig lang sein.<br />

Und wie sieht das Standardprogramm Hello World aus?<br />

* (print “Hello World”)<br />

“Hello World”<br />

“Hello World”<br />

Der Interpreter zeigt den String zweimal an. Dies ist nichts<br />

Ungewöhnliches, denn wie andere Interpreter auch führt Lisp<br />

die Funktion aus (daher die erste Ausgabe) und zeigt anschließend<br />

deren Rückgabewert an (daher die zweite Ausgabe).<br />

Programme dauerhaft ablegen<br />

Bis jetzt haben wir den Code direkt in den Interpreter eingegeben.<br />

Sobald wir ihn beenden, wären unsere Programme also verschwunden.<br />

Um eine Programmdatei zu erstellen, verwenden Sie einen<br />

beliebigen Editor und erstellen die Datei hello.lisp mit dem Inhalt<br />

(print “Hello World”)<br />

Sie können das Programm nun mit sblc --script hello.lisp<br />

ausführen. Es wird den Text inklusive der Anführungszeichen<br />

und ohne Zeilenumbruch ausgeben. Verwenden Sie princ<br />

anstelle von print, um die Anführungszeichen zu unterdrücken.<br />

Und mit WRITE-LINE erhalten Sie einen Zeilenumbruch.<br />

Common Lisp installieren<br />

Um den Beispielen zu folgen, sollten Sie<br />

sich SBCL (Steel Bank Common Lisp, die<br />

populärste Linux-Installation) installieren.<br />

Sie installieren die Sprache mit Ihrem<br />

Paketmanager oder laden sie selbst von<br />

der SBCL-Webseite http://www.sbcl.org<br />

herunter. Zusätzlich sollten Sie Emacs<br />

und Slime installieren (ebenfalls mittels<br />

Paketmanager oder Download) und diese<br />

Kombination als Entwicklungsumgebung<br />

verwenden. Slime bringt Emacs eine<br />

Befehls-Chronik, Tab-Autokomplettierung<br />

und eine Funktionsdokumentation<br />

um unteren Bildrand bei. Fügen Sie<br />

diese Zeilen zu ~/.emacs hinzu:<br />

;; Set up Common Lisp<br />

(add-to-list ‘load-path “/usr/share/common-lisp/source/slime/”)<br />

(setq inferior-lisp-program “/usr/bin/sbcl”)<br />

(require ‘slime)<br />

(slime-setup)<br />

;; Use highlight colors<br />

(global-font-lock-mode t)<br />

Starten Sie nun Emacs, geben Sie M-x<br />

slime ein und schon erhalten Sie eine<br />

CL-USER-Eingabeaufforderung.<br />

So sieht Slime beim ersten Programmstart aus.<br />

146


Programmiersprachen<br />

Atome, (Listen), car und cdr<br />

Werfen wir einen Blick auf die Grundlagen der Lisp-Syntax.<br />

Alles in Lisp ist eine sogenannte S-Expression, bei der es sich<br />

um Atome (Zahlen, Strings, Symbole) oder um Listen handeln<br />

kann. Atome geben sich selbst zurück:<br />

* 2<br />

2<br />

* “hello”<br />

“hello”<br />

Ein Symbol entspricht in etwa dem Namen einer<br />

Variablen. Namen dürfen keine Leerzeichen enthalten oder<br />

mit Zahlen anfangen. Weder 3 noch 3e4 sind gültige Namen<br />

und würden vom Interpreter als Zahlen (die letztere mit<br />

So speichert Lisp eine Liste mit vier Einträgen: Jeder<br />

Eintrag ist das car eines cons-Paares<br />

Ein erstes Lisp-Programm<br />

<strong>Das</strong> erste richtige Lisp-Programm soll eine kleine<br />

Fotodatenbank sein. Wir definieren für jedes Foto ein paar<br />

Daten und erstellen dann eine Liste aller Bilder. Wie oben<br />

beschrieben, können Sie die Code-Abschnitte entweder<br />

direkt im SBLC/Slime starten oder sie als separate<br />

Programmdatei ausführen<br />

Zunächst definieren wir einen einzelnen Eintrag. Dafür<br />

werden wir eine Hashtabelle verwenden, einen Datentyp, der<br />

eine Reihe von Schlüssel-/Wert-Paaren verwaltet.<br />

Hier ist der Code, der die Hashtabelle photo erzeugt und<br />

mit drei Schlüssel-/Wert-Paaren “category”, “tag” und “location”<br />

füllt:<br />

* (setq photo (make-hash-table :test ‘equal))<br />

* (setf (gethash “category” photo) “pets”)<br />

* (setf (gethash “tag” photo) (list “dog” “sunset” “beach”))<br />

* (setf (gethash “location” photo) “Camber Sands”)<br />

Wir übergeben :test ‘equal an die MAKE-HASH-TABLE-<br />

Funktion, damit sie einen Gleichheitstest durchführen kann.<br />

Ohne dieses Argument wüsste die Hashtabelle nicht, wie es<br />

die Schlüssel mit Hash-Werten abgleichen sollte<br />

Um einen Eintrag zu erstellen, verwenden wir GETHASH,<br />

um diesen (wertfreien) Eintrag zu erhalten. Dann setzen<br />

Exponent) verwendet werden. Die Konventionen schreiben<br />

vor, dass man meine-variable anstatt meine_variable verwendet,<br />

dass globale Variable von *sternen* und dass<br />

Konstanten mit +plus-zeichen+ eingerahmt werden.<br />

Listen<br />

Listen bestehen aus zwei Teilen: Dem ersten Listenelement,<br />

das aus historischen Gründen car genannt wird (Contents of<br />

Address Register), und dem Rest der Liste, der cdr genannt<br />

wird (Contents of Decrement Register). car muss entweder<br />

ein Symbol, eine Funktion oder ein Lambda-Ausdruck (mehr<br />

dazu später) sein. Wenn es ein Symbol ist, dann wendet Lisp<br />

es auf den gesamten Rest der Liste an:<br />

* (* 2 3 6)<br />

36<br />

* (list 3 4 5)<br />

(3 4 5)<br />

* (cons 5 6)<br />

(5 . 6)<br />

<strong>Das</strong> *-Symbol multipliziert den Rest der Liste. Die<br />

list-Funktion macht aus dem Rest der Liste eine neue<br />

Liste und die cons-Funktion macht aus zwei<br />

Listenelementen ein Paar (das keine Liste ist – beachten<br />

Sie den Punkt, der die Elemente trennt).<br />

Unter der Haube sind Listen eigentlich miteinander verknüpfte<br />

Paare. In jedem dieser Paare ist car der Wert des<br />

Listenelements und cdr ein Verweis auf das nächste Paar.<br />

<strong>Das</strong> Paar mit dem cdr-Wert NIL ist das Ende der Liste.<br />

NIL hat in Lisp mehrere Aufgaben. Als Atom entspricht es<br />

dem logischen FALSCH (jeder andere Wert entspricht dem<br />

logischen WAHR) und als Liste entspricht es einer leeren<br />

Liste. Somit wird () als NIL interpretiert. Wenn Sie ein logisches<br />

WAHR benötigen, dann gebieten die Konventionen die<br />

Verwendung von T.<br />

wir den Wert dieses Schlüssel-/Wert-Paars mit SETF auf<br />

einen neuen Wert. Da ja zum Zeitpunkt der ersten<br />

GETHASH-Aufrufe noch kein entsprechendes Paar existiert,<br />

erzeugt Lisp automatisch neue, uninitialisierte Paare.<br />

Um einen Wert aus der Hashtabelle auszulesen, verwenden<br />

wir GETHASH:<br />

* (gethash “category” photo)<br />

“pets”<br />

T<br />

Dies zeigt den unter “category” gespeicherten Wert an,<br />

gefolgt von einem T (dem logischen WAHR, da der Eintrag<br />

existiert).<br />

Nun machen wir uns das Leben etwas einfacher, indem<br />

wir eine Funktion definieren, welche category, taglist und<br />

location in eine neue Hashtabelle speichert:<br />

(defun make-photoinfo (location taglist category)<br />

(setf photo (make-hash-table :test ‘equal))<br />

(setf (gethash “location” photo) location)<br />

(setf (gethash “tag” photo) taglist)<br />

(setf (gethash “category” photo) category)<br />

photo)<br />

<strong>Das</strong> Symbol DEFUN gibt an, dass wir nun eine<br />

Schnelltipp<br />

Lisp ist eine funktionale<br />

Programmiersprache<br />

und dürfte<br />

daher keine<br />

Funktion besitzen,<br />

welche „Seiteneffekte“<br />

verursachen<br />

– wie etwa die<br />

PRINT-Funktion,<br />

die einen Text auf<br />

dem Bildschirm<br />

ausgibt. Einer 60<br />

Jahre alten<br />

Sprache macht<br />

man aber keine<br />

entsprechenden<br />

Vorwürfe, außerdem<br />

haben alle<br />

praxisnahen funktionalen<br />

Sprachen<br />

Seiteneffekte. Wer<br />

eine „rein funktionale“<br />

Sprache<br />

sucht, wird mit<br />

XSLT, Miranda und<br />

Clean fündig.<br />

147


Programmiersprachen<br />

Schnelltipp<br />

Schnelltipp<br />

Um eine Programmdatei<br />

direkt auszuführen,<br />

fügen Sie ihr<br />

die Shebang- Zeile<br />

#!/usr/bin/sbcl<br />

--script<br />

hinzu und machen<br />

die Datei ausführbar.<br />

Funktion definieren. Anschließend folgt der Name<br />

make-photoinfo der Funktion und anschließend die<br />

Parameterliste. Danach kommt der Funktionsrumpf und<br />

eine weitere Zeile: das photo am Funktionsende. Dies ist<br />

der Rückgabewert der Funktion, der in Lisp stets an letzter<br />

Stelle der Definition stehen muss. Hätten wir diese<br />

Zeile weggelassen, würde die Funktion den category-Wert<br />

zurückgeben,<br />

Grundsätzlich hat eine Funktionsdefinition folgende<br />

Struktur::<br />

(DEFUN name (parameter_liste)<br />

(funktions_koerper)))<br />

Beachten Sie, dass es sich hier um eine Liste handelt. Die<br />

Reihenfolge der Elemente ist erfreulicherweise die gleiche,<br />

wir in jeder anderen Programmiersprache, aber es ist dennoch<br />

eine echte Lisp-Liste.<br />

Da wir mehr als nur ein Foto speichern wollen, benötigen<br />

wir nun eine globale Liste, die alle Fotos aufnimmt:<br />

(defvar *photolist* nil)<br />

DEFVAR definiert eine Variable, und mit den Sternchen<br />

zeigen wir, dass *photolist* eine globale Variable ist.<br />

Schleifen<br />

Beachten Sie, dass DEFVAR nur für die erste<br />

Variablendefinition gültig ist – um eine Variable neu<br />

zuzuweisen, verwenden Sie DEFPARAMETER.<br />

Vorausplanung<br />

Um dieser Liste ein Foto zuzuweisen, könnten wir die PUSH-<br />

Funktion verwenden. Es ist aber einfacher und zukunftssicherer,<br />

für diesen Zweck eine add-photoinfo-Funktion zu<br />

erstellen:<br />

(defun add-photoinfo (photo) (push photo *photolist*))<br />

Die add-photoinfo-Funktion ist recht einfach: Sie hat nur<br />

einen einzigen Parameter und fügt diesen mit PUSH der Liste<br />

*photolist* hinzu. Nun können wir in unserer Fotodatenbank<br />

mehrere Einträge speichern:<br />

(add-photoinfo (make-photoinfo “London” ‘(dog park) “pets”))<br />

(add-photoinfo (make-photoinfo “London” ‘(baby park)<br />

“family”))<br />

(add-photoinfo (make-photoinfo “Venice” ‘(canal building) “holidays”))<br />

Geben Sie *photolist* ein, um den Inhalt der Liste zu sehen.<br />

Lisp behandelt<br />

„Buchstaben in<br />

doppelten<br />

Anführungszeichen“<br />

als Strings.<br />

Ein einzelnes<br />

Anführungszeichen<br />

veranlasst Lisp,<br />

den folgenden Wert<br />

nicht auszuwerten,<br />

sondern ihn als<br />

Datum zu behandeln.<br />

‘dies gibt<br />

daher dies zurück<br />

und ist besonders<br />

in Funktionen und<br />

Makros nützlich.<br />

Wenn Sie nun *photolist* eintippen, dann sehen Sie nur eine<br />

Liste von Hashtabellen-Beschreibungen. Für eine sinnvollere<br />

Ausgabe entwickeln wir daher eine Funktion, die mit einer<br />

Schleife über die Liste iteriert und die einzelnen Werte der<br />

Hashtabelle ausgibt. In Lisp sind die häufigsten Konstrukte<br />

für diesen Zweck Makros und basieren auf der sehr einfachen<br />

und meist kompliziert zu verwendenden DO-Funktion:<br />

DOLIST und DOTIMES.<br />

DOLIST iteriert über die<br />

Listeneinträge und wendet<br />

den Funktionsrumpf auf diese<br />

Einträge an – ähnlich wie<br />

foreach in anderen<br />

Sprachen. DOTIMES ist eine<br />

Zählerschleife, welche den Funktionsrumpf mit der angegebenen<br />

Häufigkeit ausführt. Hier ist eine mathematische<br />

Anwendung von DOTIMES:<br />

(dotimes (i 5)<br />

(print (* i i)))<br />

0 1 4 9 16 NIL<br />

Beachten Sie, dass der angegebene Vergleichswert 5 nicht<br />

erreicht wird.<br />

DOLIST hingegen iteriert über eine Liste. In unserer Funktion<br />

show-photo-details durchläuft sie *photolist* und stellt<br />

dabei jeden Eintrag in der Variable photo bereit:<br />

(defun show-photo-details ()<br />

(dolist (photo *photolist*)<br />

(setf photoinfo nil)<br />

(push (gethash “category” photo) photoinfo)<br />

(push “category” photoinfo)<br />

(push (gethash “tag” photo) photoinfo)<br />

(push “tag” photoinfo)<br />

(push (gethash “location” photo) photoinfo)<br />

(push “location” photoinfo)<br />

(format t “~{~a - ~a~%~}” photoinfo)))<br />

Im Schleifenrumpf von DOLIST erstellen wir eine temporäre<br />

Liste namens photoinfo und verwenden GETHASH, um den<br />

entsprechenden Wert dieser Liste hinzuzufügen. Darüber<br />

hinaus erhält die Liste auch noch die Namen dieser Werte.<br />

„DOLIST entspricht etwa der<br />

foreach-Schleife anderer<br />

Sprachen“<br />

Die FORMAT-Funktion selbst mag hässlich sein, sie verpasst<br />

der Ausgabe aber ein sehenswertes Format. Alle FORMAT-<br />

Direktiven fangen mit dem Tildezeichen ~ an. <strong>Das</strong> ~{ ... ~} iteriert<br />

über die eine Liste (in unserem Fall photoinfo). ~a gibt<br />

das nächste Argument aus, gefolgt von einem Bindestrich<br />

und gefolgt vom nächsten Argument. Damit erhalten wir<br />

als Ausgabe mehrere „Name - Wert“-Paare.<br />

Diesen Code könnten wir<br />

schöner gestalten, wenn<br />

wir die MAPHASH-<br />

Funktion verwenden würden.<br />

Diese ist dazu da, aus<br />

einer Hashtabelle eine Liste<br />

zu erzeugen. Außerdem<br />

teilen wir den Code in mehrere Funktionen auf:<br />

(defun print-hash (key value)<br />

(format t “~5t~S - ~S~%” key value))<br />

(defun show-single-photo (photo)<br />

(maphash #’print-hash photo))<br />

(defun show-photo-details-2 (mylist)<br />

(setf pageno 1)<br />

(dolist (photo mylist)<br />

(write-line (concatenate ‘string “Photo “ (write-to-string pageno)))<br />

(show-single-photo photo)<br />

(incf pageno)))<br />

print-hash legt mittels FORMAT fest, wie ein Name/Wert-<br />

Paar angezeigt werden soll (~S ist der Platzhalter für die<br />

Argumente key und value hinter dem Formatstring).<br />

show-single-photo übergibt diese Funktion an MAPHASH,<br />

die sie auf ihren Rückgabewert anwendet.<br />

Nun packen wir das alles in showphoto-details-2 in eine<br />

DOLIST-Schleife und verschönern die Ausgabe ein wenig:<br />

Jedes Foto erhält eine Nummer und einen Titel. Beachten<br />

Sie, dass Sie CONCATENATE mitteilen müssen, welcher Typ<br />

zurückgegeben werden soll – in diesem Beispiel ist es ‘string.<br />

148


Programmiersprachen<br />

Makros: Code schreibt sich selbst<br />

Makros sind in Lisp ein mächtiges Hilfsmittel,<br />

doch leider reicht der Platz für eine eingehende<br />

Betrachtung nicht aus. Daher die grundlegende<br />

Idee in aller Kürze: Ein Makro macht aus Lisp-<br />

Code Lisp-Code (im Gegensatz zu Funktionen,<br />

die aus Lisp-Datenwerten andere Lisp-<br />

Datenwerte berechnen). Bevor ein Programm<br />

ausgeführt wird, sucht der Compiler im gesamten<br />

Code nach solchen Makros und „führt sie<br />

aus“, genau genommen expandiert er sie. Der<br />

ermittelte Lisp-Code ersetzt nun die ehemaligen<br />

Makro-Aufrufe und der Compiler kann das<br />

Programm erstellen. Sie können sich ein Makro<br />

wie eine Vorlage für immer wiederkehrende,<br />

meist kurze Code-Fragmente vorstellen, die keine<br />

oder nur geringe Unterschiede aufweisen.<br />

<strong>Das</strong> von Lisp bereitgestellte WHEN-Makro hat<br />

folgenden Code:<br />

(defmacro new-when (condition &rest body)<br />

`(if ,condition (progn ,@body)))<br />

Beachten Sie das einzelne Anführungszeichen.<br />

Es sagt dem Compiler, dass alles Folgende<br />

kopiert anstatt ausgewertet wird – sofern es<br />

nicht mit einem Komma beginnt. Daher werden<br />

condition und @body beim Expandieren des<br />

Makros ausgewertet (es werden also die an das<br />

Makro übergebenen Parameterwerte verwendet),<br />

if und progn aber unverändert kopiert.<br />

Aus diesem Code<br />

(new-when (= x 3)<br />

(setq x 4))<br />

wird also dieser:<br />

(if (= x 3)<br />

(progn (setq x 4)))<br />

Auch in diesem Tutorial haben wir bereits<br />

Makros eingesetzt: DEFVAR, PUSH und DOLIST<br />

sind Makros. Mit DEFMACRO könnten Sie jederzeit<br />

neue Versionen dieser Makros definieren,<br />

Sie können aber auch Wrapper für jedes beliebige<br />

Code-Konstrukt schreiben, das sich nicht als<br />

Funktion darstellen lässt. Auf diese Weise lässt<br />

sich Lisp nach Lust und Laune erweitern – auf<br />

effizienteste Weise, da der resultierende Code ja<br />

dorthin kopiert wird, wo er benötigt wird.<br />

Lambda-Funktionen<br />

Zum Abschluss wenden wir uns einem letzten Lisp-ismus zu:<br />

Den Lambda-Funktionen. Hierbei handelt es sich einerseits<br />

um ein Modewort (keine Programmiersprache, die etwas auf<br />

sich hält, darf derzeit auf Lambda-Ausdrücke verzichten),<br />

andererseits einfach nur um Funktionen, die als Parameter<br />

an andere Funktionen übergeben werden. Und da sie dazu<br />

keinen Funktionsnamen benötigen, nennt man sie auch anonyme<br />

Funktionen.<br />

Hier ist ein einfaches Beispiel:<br />

* (remove-if-not #’oddp ‘(1 2 3 4 5))<br />

(1 3 5)<br />

* (remove-if-not #’(lambda (x) (= 3 x)) ‘(1 2 3 4 5))<br />

(3)<br />

Die obere Version zeigt lediglich, wie REMOVE-IF-NOT<br />

funktioniert: Es gibt eine Liste mit Elementen zurück, die dem<br />

ersten Funktionsparameter entsprechen – in diesem Fall<br />

ODDP, das nur für ungerade Zahlen WAHR ist. Die<br />

#-Notation verrät Lisp, dass nun ein Funktionsname folgt.<br />

Die zweite Version macht prinzipiell das Gleiche, nur dass<br />

anstelle von ODDP eine Lambda-Funktion verwendet wird. In<br />

unserem Fall vergleicht sie jeden Listeneintrag mit 3, daher<br />

wird nur der Listeneintrag 3 zurückgegeben.<br />

Eine Lambda-Funktion ist also eine temporäre Funktion,<br />

der wir keinen Funktionsnamen gaben und die wir an andere<br />

Funktionen weiterreichen können. Wie hilft uns das bei unserer<br />

Fotodatenbank?<br />

(remove-if-not<br />

#’(lambda (x) (equal (gethash “category” x) “pets”)) *photolist*)<br />

Dateneingabe und Funktionsabläufe in Slime.<br />

Diese Konstruktion iteriert über *photolist*, speichert<br />

jeden Eintrag in x und gibt nur diejenigen Bilder zurück, die<br />

der Kategorie “pets” angehören.<br />

Wir können die Funktion show-photo-details-2 aus dem<br />

vorherigen Abschnitt entsprechend erweitern:<br />

(show-photo-details-2<br />

(remove-if-not<br />

#’(lambda (x) (equal (gethash “category” x) “pets”)) *photolist*))<br />

Blog entry 1<br />

category - pets<br />

tag - (DOG PARK)<br />

location - London<br />

Damit sind wir fast am Ziel. Wir erstellen nun noch eine<br />

weitere Funktion und übergeben ihr als Paramater den<br />

gewünschten Schlüssel und den gewünschten Wert:<br />

(defun show-photo (key value)<br />

(show-photo-details-2<br />

(remove-if-not<br />

#’(lambda (x) (equal (gethash key x) value)) *photolist*)))<br />

(show-photo “category” “family”)<br />

Blog entry 1<br />

category - family<br />

tag - (BABY PARK)<br />

location - London NIL<br />

Wie in Lisp üblich, ist der Programmcode am einfachsten<br />

zu verstehen, wenn man ihn von hinten nach vorne liest: Die<br />

REMOVE-IF-NOT-Funktion vergleicht den übergebenen<br />

Schlüssel und den übergebenen Wert und erstellt eine<br />

Liste mit allen zu diesen Kriterien passenden Bildern.<br />

Diese wird an die alte show-photo-list-details-Funktion<br />

übergeben. Dieses Aneinanderreihen von Funktionen ist sehr<br />

typisch für Lisp.Bei genauem Hinsehen fällt auf, dass die<br />

Suche nach einem bestimmten Wert im tag nicht funktioniert<br />

– der tag-Hashwert ist ja eine Liste und GETHASH prüft auf<br />

völlige Gleichheit des Suchstrings mit diesem Hashwert. Eine<br />

Suche nach der Liste (BABY PARK) wird also erfolgreich<br />

sein, eine Suche nach dem String BABY hingegen nicht.<br />

Wenn Sie die Suchfunktion selbst umprogrammieren möchten,<br />

werden Sie vermutlich IF und PROGN nachschlagen wollen.<br />

Zu diesem Zweck legen wir Ihnen ist das kostenlose Online-<br />

Buch Practical Common Lisp ans Herz, das sich als gut lesbare<br />

Informationsquelle zum Thema Lisp erwiesen hat.<br />

Schnelltipp<br />

Denken Sie daran,<br />

dass in Lisp<br />

Funktionsparameter<br />

nicht in<br />

Klammern stehen<br />

dürfen – es sei<br />

denn, der<br />

Parameter ist eine<br />

einzelne Liste.<br />

Daher hieße es<br />

(print „hallo“) und<br />

nicht (print(„hallo“)).<br />

Wenn Sie<br />

eine Fehlermeldung<br />

wie „illegal function<br />

call“ erhalten, dann<br />

sind meist diese<br />

überzähligen<br />

Klammern schuld.<br />

149


Programmiersprachen<br />

C++: So geht’s<br />

Eine kleine Einführung in die Programmiersprache samt Klassen,<br />

Objekten und Vererbung.<br />

In diesem Tutorial werden wir einen kleinen Blick auf das<br />

1998 und 2003 standardisierte „klassische“ C++ werfen.<br />

Wahrscheinlich sind Sie sich bewusst, dass es mittlerweile<br />

eine aktuellere Version – C++ 11 – gibt, aber wir werden uns<br />

erst einmal mit einigen grundlegenden Ideen und der Syntax<br />

auseinandersetzen, die bei jeder Version funktionieren.<br />

C++ leiht sich viele Ideen und seine Struktur bei C aus.<br />

Daher wird Erfahrung mit C oder einer anderen mit C verwandten<br />

Sprache Ihren Lernprozess bei C++ beschleunigen.<br />

Doch Vorsicht: Es gibt kleine, aber feine Unterschiede zwischen<br />

C und C++.<br />

Selbst wenn Sie noch nie mit C oder dem Konzept von<br />

objektorientiertem Programmieren in Berührung gekommen<br />

sind, sollten Sie ohne Weiteres in der Lage sein, sich erfolgreich<br />

durch dieses Tutorial durchzuarbeiten.<br />

Falls Sie dieses Tutorial direkt am Rechner ausprobieren<br />

möchten, muss g++ installiert sein. Sind Sie sich nicht sicher,<br />

ob dies der Fall ist, geben Sie einfach g++ in die Befehlszeile<br />

ein. Ist es installiert, wird es nach ausführbaren Dateien fragen,<br />

ist es nicht installiert, wird das System Sie darüber informieren.<br />

Wir erstellen zunächst ein einfaches C++-Programm:<br />

#include <br />

int main()<br />

{<br />

std::cout


Programmiersprachen<br />

werfen Sie einen Blick auf die Dateien im Verzeichnis Person.<br />

Erschaffen und führen Sie das Programm so aus, wie es dort<br />

durch den Code vorgegeben wird. Kommentieren Sie die<br />

Zeile in main.cpp aus, welche Ihnen den Zugriff eines privaten<br />

Nutzers ermöglicht. Sie können dies durch das Weglassen<br />

von // in der Zeile erreichen. Versuchen Sie nun, mit<br />

dem Build-Befehl die Datei auszuführen, achten Sie auf die<br />

daraus resultierende Fehlermeldung. Alles klar? Beheben Sie<br />

den fehlerhaften Code nun wieder durch das Einfügen der<br />

fehlenden // Zeichen.<br />

Formen zeichnen<br />

Lassen Sie uns ein anderes Beispiel nehmen. Gesetzt den<br />

Fall, wir möchten ein Programm schreiben, das verschiedene<br />

Formen auf dem Bildschirm zeichnet. Dieses Programm<br />

könnte ein 2D-Malwerkzeug sein oder ein Werkzeug, mit dem<br />

Sie Diagramme erschaffen und editieren können. Hierbei<br />

würde es sich sehr wahrscheinlich um Figuren wie Rechtecke<br />

und Kreise handeln. Diese Figuren hätten allesamt eine bestimmte<br />

Position in der zweidimensionalen Welt und würden<br />

für gewöhnlich innerhalb der Begrenzung eines Fensters dargestellt.<br />

Solche Positionen werden üblicherweise angezeigt,<br />

indem man der Figur einen Ort zuweist, der im Verhältnis zu<br />

ihrem Mittelpunkt im Koordinatensystem des Fensters steht.<br />

Eine Klasse, die eine allgemeine Form repräsentiert, könnte<br />

so aussehen:<br />

class Shape<br />

{<br />

public:<br />

Shape(int x, int y);<br />

void draw() const;<br />

int get_x() const;<br />

int get_y() const;<br />

private:<br />

int x;<br />

int y;<br />

};<br />

Unsere spezifischen Figuren – Kreise und Rechtecke – würden<br />

als verschiedene Arten der Klasse Shape dargestellt werden,<br />

indem wir folgende Syntax verwenden:<br />

class Circle : public Shape<br />

{<br />

public:<br />

Circle(int x, int y, int radius);<br />

void draw() const;<br />

private:<br />

int r;<br />

};<br />

Diese Syntax<br />

Class : public Base Class<br />

{<br />

…<br />

definiert unsere Klasse, Class, als eine Ableitung von unserer<br />

Basisklasse. Als eine solche hat sie alle Elemente (Datenelemente<br />

und Elementfunktionen) unserer Basisklasse plus einige<br />

zusätzliche, die wir noch näher definieren können. Hierdurch<br />

erreichen wir eine gewisse Flexibilität bei den<br />

abgeleiteten Klassen, solange wir nicht übermäßig gegen die<br />

Semantik der Basisklasse mit Ihren Modifikationenen<br />

verstoßen.<br />

(Nebenbei bemerkt: Const-Elementfunktionen. Wir haben<br />

mehrere unserer Elementfunktionen und ihre entsprechenden<br />

Definitionen mit dem Schlüsselwort const beendet. Dies<br />

fügt eine Sicherheitsüberprüfung zu den Funktionen hinzu,<br />

die read-only sind. Dadurch wird der Compiler veranlasst, die<br />

Funktionen daraufhin zu überprüfen, dass sie nicht das Objekt,<br />

das sie aufruft, direkt oder indirekt verändern.)<br />

Wir könnten das Beispiel um Klassen weiterer bestimmter<br />

Formen, wie Rechtecke oder Pfeile, erweitern, belassen es<br />

aber fürs Erste hierbei.<br />

Konstruktoren und Destruktoren<br />

Objekte werden durch einen Aufruf an eine Konstruktor-<br />

Elementfunktion aufgerufen. Wird eine solche Definition der<br />

Klasse nicht vom Anwender zur Verfügung gestellt, so<br />

springt der Compiler ein. Die Compilervariante wird jedoch<br />

nur dem Objekt Speicher zur Verfügung stellen. Bei einem<br />

nicht-statischen Objekt bleiben alle Datenelemente<br />

uninitialisiert.<br />

Da es oft notwendig ist, dass Objekte einen bestimmten<br />

Wert haben, werden Konstruktoren größtenteils dafür verwendet,<br />

genau dies zu ermöglichen. Zusätzlich können sie<br />

aber alles erledigen, was Sie wünschen – sich mit Datenbanken<br />

verbinden, ihre Initialisierung in einem Log festhalten und<br />

vieles mehr. Konstruktoren werden nach ihrer Klasse benannt<br />

und als nicht-zurückkehrende Gattung definiert.<br />

Derjenige in unserer Shape-Klasse wurde folgendermaßen<br />

definiert:<br />

Shape(int x, int y);<br />

Dies weist darauf hin, dass der Konstruktor int beidesmal als<br />

Argument annimmt. Wie dies verwendet wird, wird über unsere<br />

Implementierungsdatei gesteuert (shape.cpp in unseren<br />

Code-Beispielen).<br />

Analog dazu, wenn ein Objekt gelöscht wird, kommt ein<br />

Destruktor ins Spiel. Wie zuvor wird auch hier einer vom<br />

Compiler zur Verfügung gestellt (dieser gibt den Speicher<br />

des Objekts einfach wieder frei). Möchten Sie mehr als diese<br />

grundlegende Funktion verwenden, müssen Sie dem Destruktor<br />

vorschreiben, was zu tun ist (eine Verbindung kappen,<br />

den Soundchip deaktivieren und so weiter). Für gewöhnlich<br />

wird ein Objekt gelöscht, wenn es seinen<br />

Aufgabenbereich überschreitet (ein solches Beispiel wäre die<br />

geschlossene spitze Klammer eines Blocks).<br />

Um einige dieser Konzepte zu veranschaulichen, können<br />

wir die Konstruktion und Destruktion unseres Shape-Klassen-Objekts<br />

arrangieren. Dies können wir dadurch erreichen,<br />

dass wir die Zeile<br />

cout


Programmiersprachen<br />

Schnelltipp<br />

Denken Sie daran,<br />

jede Definition einer<br />

Klasse mit einem ;<br />

zu beenden, da<br />

Sie sonst einen<br />

Programmierfehler<br />

begehen, der bei<br />

manchen Compilern<br />

zu seltsamen<br />

Fehlermeldungen<br />

führt.<br />

und<br />

~Circle();<br />

zusätzliche Zeilen in die relevanten .h-Dateien einfügen.<br />

Eine Möglichkeit wäre zum Beispiel:<br />

Shape::~Shape()<br />

{<br />

cout


Programmiersprachen<br />

dann die Funktion auf, um x mit einer einer const-Referenz<br />

für j zu initialisieren.<br />

Mit anderen Worten, innerhalb der Funktion ist x ein anderer<br />

Name für j, aber keiner der es erlaubt, j zu verändern. Die<br />

zurückgegebene Aussage der Funktion verhält sich wie<br />

zuvor. Jeder Versuch jedoch, x, und damit j, zu verändern,<br />

verursacht einen Fehler beim Kompilieren.<br />

Somit haben wir alles gleichzeitig. Die Kosteneffektivität<br />

durch die Initialisierung von Referenzen bei gleichzeitiger<br />

Sicherheit durch die Weitergabe des Werts.<br />

Als Faustregel kann man sagen, dass kleine Parameter<br />

(char, int, double und so weiter) über ihren Wert und größere<br />

Parameter wie Objekte per const-Referenz weiterzugeben<br />

sind.<br />

C++ erlaubt es im Allgemeinen, seine Funktionen zu<br />

überlasten. <strong>Das</strong> bedeutet, dass es in der Lage ist, mehrere<br />

Funktionen eines Namens zu haben, welche sich aber über<br />

unterschiedliche Sequenzen von Aussagegattungen unterscheiden.<br />

Basierend auf den Aussagen sucht sich der<br />

Compiler die richtige Version heraus.<br />

Es ist allgemein üblich, eine Vielzahl an Versionen von Klassenkonstruktoren<br />

zu haben. Eine Klasse kann zum Beispiel<br />

einen – oder mehrere – normale Konstruktoren haben und<br />

zusätzlichen einen Konstruktor für Kopiervorgänge. Dieser<br />

wird immer dann Verwendung finden, wenn wir ein Objekt<br />

der gleichen Art aus einem anderen erschaffen wollen. Für<br />

die Klasse C wird der Kopie-Konstruktor folgendermaßen<br />

definiert:<br />

C( const C& c);<br />

Hiermit wird ein Objekt der gleichen Art über die const-<br />

Referenz weitergegeben und etwa so definiert:<br />

C:: C( const C& c)<br />

{<br />

…<br />

}<br />

Falls dieser Artikel Sie auf C++ neugierig gemacht haben<br />

sollte, finden Sie auf http://www.a-train.co.uk/c++_<br />

books.html eine weiterführende Bibliographie.<br />

Code-Beispiele kompilieren und ausführen<br />

1 Kompilieren und starten<br />

Suchen Sie die Dateien in Ihrem Hello-Verzeichnis. Führen Sie die<br />

vorgeschlagene Datei aus, um Ihr Build-Setup zu testen.<br />

2 Benutzen Sie eine einfache Klasse<br />

An den Dateien im Person-Verzeichnis sehen Sie, wie Interface- und<br />

Implementationsdateien einer Klasse geschrieben und im Client-Code<br />

verwendet werden.<br />

3 Nutzen Sie Vererbung<br />

Verwenden Sie die Dateien im Shapes_1-Verzeichnis, um sich näher<br />

anzuschauen, wie die Syntax verwendet wird, um eine Klasse<br />

abzuleiten (Vererbung).<br />

4 Nutzen Sie Referenzparameter<br />

Konstruktoren, das Hinzufügen eines Kopie-Konstruktors, das<br />

Verwenden von const-Referenzparametern. Benutzen Sie die<br />

Dateien im Reference-Verzeichnis.<br />

153


Programmiersprachen<br />

Fortran: Fortran<br />

Fortran ist die älteste aller Hochsprachen und mit ihrem Fokus auf<br />

mathematische Berechnungen aktueller als je zuvor.<br />

Fortran Fortran wurde zwischen 1954 und 1957 entwickelt<br />

und ist damit die älteste höhere<br />

Programmiersprache überhaupt. Trotz des hohen<br />

Alters ist Fortran noch immer in Verwendung, beispielsweise<br />

berechnen Investmentbanken und Versicherungen ihre komplexen<br />

mathematischen Modelle damit. Da Fortran<br />

(FORmula TRANslation) ursprünglich für die Berechnung<br />

numerischer Modelle entwickelt wurde, fand sie schnell in<br />

allen physikalischen und mathematischen Disziplinen<br />

Verwendung. Daher füttern auch die Wissenschaften ihre<br />

Supercomputer gerne mit dieser Sprache und so erfreut sich<br />

die Sprache auch nach mehr als 50 Jahren noch immer<br />

höchster Beliebtheit – obwohl ihr seit mehreren Jahrzehnten<br />

der Untergang vorausgesagt wird.<br />

Selbst ein 35 Jahre alter Fortran-Code läuft noch immer in<br />

seiner ursprünglichen Form. Aber auch moderne Konzepte<br />

sind längst umsetzbar, da Fortran stetig weiterentwickelt<br />

wird. Nur für Web-Anwendungen und grafische<br />

Benutzeroberflächen ist Fortran nach wie vor ungeeignet.<br />

Installation und erste Schritte<br />

In diesem Tutorial werden wir die Sprachfeatures von Fortran<br />

90 verwenden, daher benötigen Sie einen Fortran-Compiler<br />

gleicher oder jüngerer Version. Wir empfehlen den kostenlosen<br />

GNU-Compiler gfortran, aber andere Compiler wie G95<br />

(ebenfalls kostenlos) oder NAG (kostenpflichtig) eignen sich<br />

ebenso. Einige Compiler bringen eigene Sprachvarianten mit<br />

und eignen sich damit für spezielle Einsatzgebiete, allerdings<br />

verzichten sie auf Code-Kompatibilität zu anderen<br />

Compilern. Wir benötigen derlei Erweiterungen nicht und<br />

beschränken uns auf den offiziellen Sprachstandard. gfortran<br />

finden Sie auf der GNU-Webseite oder als optionales Paket in<br />

den meisten Linux-Distributionen. Unter Debian starten Sie<br />

den Compiler mit gfortran oder F95; im folgenden Text werden<br />

wir F95 verwenden.<br />

Erstellen Sie eine Textdatei namens hello.f95 und geben<br />

Sie diesen Code ein.<br />

Ein F95-<br />

Programm,<br />

das nach<br />

Ihrem Namen<br />

fragt und Sie<br />

dann begrüßt.<br />

Dahinter die F77-<br />

Version von Hello<br />

World.<br />

Fortran-Versionen<br />

Fortran (beziehungsweise der erste verfügbare<br />

Compiler) erschien im Jahr 1957 für<br />

Mainframe-Computer als Alternative zu<br />

Assembler. Der Code war eine Kombination von<br />

insgesamt 32 Anweisungen und wurde auf<br />

Lochkarten gespeichert. Da die Sprache schnell<br />

an Popularität gewann, entwickelten die<br />

Mainframe-Hersteller bald eigene, auf ihre<br />

<strong>Hardware</strong> abgestimmte Versionen. So entstand<br />

die erste echte Cross-Plattform-Sprache.<br />

Fortran II, III und IV erschienen, aber erst mit<br />

Fortran-66 wurde die Sprache durch die ISO<br />

standardisiert.<br />

Ein Jahrzehnt später wurden mit Fortran-77<br />

die gröbsten Fehler von F66 behoben, weshalb<br />

Fortran-77 heutzutage die wichtigste und meistverbreitete<br />

Sprachversion ist. Selbst für<br />

modernste Computer gibt es noch immer<br />

Fortran-77-Compiler und Code für diese Version<br />

ist in Firmen, Forschungseinrichtungen und<br />

natürlich im Internet zu finden. Nach langer<br />

Wartezeit erschien mit Fortran 90 eine völlig neu<br />

entwickelter Compiler-Version, die einerseits<br />

rückwärtskompatibel zu Fortran-77 ist und andererseits<br />

moderne Sprachkonzepte wie beispielsweise<br />

optionale Parameter und weitere mathematische<br />

Fähigkeiten wie Matrix-Operationen in<br />

Fortran integriert. Mit Fortran 2003 kam die<br />

Unterstützung der Objektorientierten<br />

Programmierung und mit Fortran 2008 wurden<br />

parallelisierte (also nebenläufige und synchronisierte)<br />

Funktionen möglich.<br />

154


Programmiersprachen<br />

Freies und festes Zeilenformat<br />

Vor Fortran 90 waren für Fortran-Programme<br />

– um auf Lochkarten gestanzt zu werden – feste<br />

Zeilenformate vorgeschrieben:<br />

Maximal 72 Zeichen je Zeile.<br />

Für Zeilenumbrüche muss die Folgezeile um<br />

sechs Spalten eingerückt sein. Die ersten 6<br />

Spalten müssen leer sein, sofern man sie nicht<br />

für Kommentare oder Fortsetzungszeichen verwendet.<br />

Kommentare müssen in der ersten Spalte ein<br />

* oder ein c haben.<br />

Darüber hinaus haben Leerzeichen keine<br />

Bedeutung.<br />

Ein Hello-World-Programm sähe also folgendermaßen<br />

aus:<br />

c Hello World<br />

program hello<br />

print *,’Hello World’<br />

end program hello<br />

Erst seit F90 existiert das freie Zeilenformat, das<br />

in allen Beispielen dieses Tutorials verwendet<br />

wird. Dennoch gilt es, einige Regeln einzuhalten:<br />

Zeilen dürfen höchstens 132 Zeichen lang sein.<br />

Um eine Zeile umzubrechen, verwendet man das<br />

&-Zeichen am Zeilenende. Wenn der Umbruch<br />

innerhalb eines Bezeichners auftritt, dann benötigt<br />

der Anfang der Folgezeile ebenfalls das<br />

&-Zeichen:<br />

character :: name*100<br />

name = “diese lange Zeile braucht hier &<br />

&und hier ein Et-Zeichen<br />

! kommentar<br />

Kommentare beginnen mit einem !<br />

Leerzeichen werden beachtet, beispielsweisedarf<br />

in Variablennamen oder Zahlen keines vorkommen.<br />

In bestimmten Bezeichnern wie END<br />

IF darf auf das Leerzeichen verzichtet werden.<br />

Einrückungen werden ignoriert.<br />

Mehrere Anweisungen in einer Zeile werden<br />

durch Semikolons ; voneinander getrennt.<br />

Wenn der Dateiname mit .f90 oder .f95 endet,<br />

geht der GCC-Compiler von einem freien Format<br />

aus; bei der Dateiendung .for von einem festen<br />

Zeilenformat. Mit -ffixed-form oder -ffree-form<br />

wird diese Automatik überschrieben.<br />

! Hello World<br />

program hello<br />

print *,”Hello World”<br />

end program hello<br />

Sie kompilieren das Programm mit f95 -o hello hello.f95<br />

und starten es mit ./hello. <strong>Das</strong> Parameterpaar -o hello gibt<br />

die Ausgabedatei an. Ohne diesen Parameter hieße die<br />

Programmdatei a.out. Sie sollten nun das traditionelle Hello<br />

World auf Ihrem Bildschirm erblicken.<br />

Diese Code-Zeilen zeigen einige wichtige Eigenheiten der<br />

Sprache: <strong>Das</strong> Ausrufezeichen ! wird für Kommentare verwendet.<br />

Programme sind mit program name und end program<br />

name umschlossen, wobei name nicht identisch mit<br />

dem Dateinamen sein muss. Die Einrückungen sind nicht<br />

erforderlich und dienen nur der Lesbarkeit.<br />

print gibt Werte auf dem Bildschirm aus. <strong>Das</strong> Sternchen *<br />

ist der Formatbezeichner und weist print an, selber das<br />

geeignete Format für die Ausgabe zu wählen. In F77 wurden<br />

Strings noch mit einfachen Anführungszeichen identifiziert,<br />

seit F90 sind auch die üblicheren doppelten<br />

Anführungszeichen erlaubt.<br />

Sprachgrundlagen<br />

Wir machen unser Programm hello.f95 nun etwas komplizierter:<br />

! Hello Name<br />

program hello<br />

Berechnungen und Schleifen<br />

Da Fortran einen mathematischen Schwerpunkt hat, ist<br />

unser nächstes Beispiel ein mathematische Anwendung: Sie<br />

berechnet Fibanocci-Sequenzen. Eine Fibanocci-Zahl ist die<br />

Summe der beiden vorherigen Fibanocci-Zahlen, beginnend<br />

mit 1 und 1. Fibanocci-Sequenzen begegnen uns überall in<br />

der Natur, beispielsweise lassen sich Schneckenhäuser<br />

damit beschreiben.<br />

Da es sich um einen iterativen Algorithmus handelt (der<br />

Eingabe-Parameter ist der Rückgabewert der vorherigen<br />

Berechnung), können wir ihn elegant in einer Schleife unterbringen:<br />

! Berechnet die ersten 20 Zahlen der Fibonacci-Sequenz<br />

program fibonacci<br />

implicit none<br />

integer :: first, second, a, i<br />

first = 1<br />

implicit none<br />

character :: name*20<br />

print *, “Please enter your name: “<br />

read *,name<br />

print *,”Hello “,name<br />

end program hello<br />

Die Zeile implicit none ist wichtig: Da Fortran für mathematische<br />

Aufgaben konzipiert wurde und Mathematiker von<br />

Variablennamen wie i, j, k, l, m und n erwarten, dass sie<br />

Ganzzahlen repräsentieren, wurde die sogenannte implizite<br />

Typisierung eingeführt: Variablen mit solchem Namen waren stets<br />

Ganzzahlen und alle anderen Variablen waren automatisch<br />

Realzahlen. Nur wenn man Strings oder Zeichen verwenden wollte,<br />

musste man die Variablen explizit deklarieren. Die implizite<br />

Typisierung funktioniert noch immer, aber da sie ein Einfallstor für<br />

Fehler aller Art ist, sollte man sie mit implicit node abschalten und<br />

alle Variablen selbst definieren. Hier deklarieren wir name als Array<br />

der Länge 20 vom Typ character, es ist also ein 20 Zeichen langer<br />

String. read liest Text aus der Standardeingabe ein und speichert<br />

den Text in name.<br />

Die in Fortran eingebauten Datentypen sind INTEGER, REAL<br />

(mit einer Genauigkeit von sechs Dezimalstellen), DOUBLE<br />

PRECISION (13 Dezimalstellen Genauigkeit), LOGICAL (boolesche<br />

Werte .TRUE. oder .FALSE.), COMPLEX (komplexe Zahl), und<br />

CHARACTER (wobei ein String ein Array von CHARACTER ist).<br />

GROSSBUCHSTABEN sieht man in Fortran sehr häufig,<br />

obwohl der Compiler die Groß- und Kleinschreibung ignoriert.<br />

second = 1<br />

print *, first<br />

print *, second<br />

do i = 1, 18, 1<br />

a = first + second<br />

print *, a<br />

first = second<br />

second = a<br />

end do<br />

end program fibonacci<br />

Zuerst deklarieren wir vier Variable und initialisieren first<br />

und second mit 1. i ist die Schleifenvariable und a wird als<br />

temporäre Variable den errechneten Wert einer einzelnen<br />

Fibanocci-Zahl zugewiesen bekommen. Wichtig an diesem<br />

Code ist die for-Schleife, die es erst seit F90 gibt. In F77 und<br />

Schnelltipp<br />

Wenn Sie jemals<br />

den Fortran-Code<br />

eines anderen<br />

Programmierers<br />

debuggen müssen,<br />

dann ist es hilfreich,<br />

den Code<br />

durch mehrere<br />

Compiler zu schicken.<br />

Bei aktivierter<br />

Debug-Option zeigen<br />

sich zahlreiche<br />

Hinweise auf<br />

potenzielle<br />

Probleme.<br />

155


Programmiersprachen<br />

älteren Versionen musste man Schleifen mit der GOTO-<br />

Anweisung bilden, doch deren Einsatz ist fehleranfällig und<br />

mittlerweile verpönt:<br />

do iterator = start, ende, zuwachs<br />

! Hier ist der Schleifenrumpf<br />

end do<br />

Die Schleifenvariable iterator hat anfangs den Wert start<br />

und wird nach jedem Schleifendurchlauf im zuwachs erhöht.<br />

Sobald zuwachs größer als ende ist, wird die Schleife beendet.<br />

Da ein Zuwachs von 1 sehr häufig vorkommt, hätten wir<br />

auf die Angabe verzichten und einfach do i = 1, 18 schreiben<br />

können.<br />

Innerhalb der Schleife berechnen wir die jeweils nächste<br />

Fibanocci-Zahl und zeigen sie an. Dann verschieben wir die<br />

Werte in first und second, um den nächsten Durchlauf vorzubereiten.<br />

So sieht die unser Beispiel der Fibonacci-Sequenz am<br />

Ende aus.<br />

Der Nullpunkt einer Funktion<br />

Wir haben<br />

das intent(in)-<br />

Schlüsselwort<br />

auf einen<br />

Parameter<br />

angewendet<br />

und dessen<br />

Wert im Code<br />

anschließend<br />

verändert (im<br />

Editor zu sehen).<br />

Der Compiler<br />

quittiert dies mit<br />

einem Fehler.<br />

Um weitere Features von Fortran zu zeigen, werden wir nun<br />

den Nullpunkt einer mathematischen Funktion berechnen.<br />

Der Nullpunkt beschreibt den Parameterwert x einer<br />

Funktion f(x), für den sie das Ergebnis Null f(x)=0 erzeugt.<br />

Hier einige Beispiele:<br />

f(x) = x - 2 : the root of this is 2, because 2 - 2 = 0.<br />

f(x) = 3x - 3 : the root of this is 1, because 3 * 1 - 3 = 0.<br />

f(x) = 2x^2 - 8 : the root of this is 2, because 2 * 2 * 2 - 8 = 0.<br />

Solche Nullpunktberechnungen kann man stets manuell<br />

lösen. Wie Sie aber vermutlich noch aus dem<br />

Mathematikunterricht wissen, überlässt man diese Aufgabe<br />

gerne einem anderen – in unserem Fall Fortran.<br />

Ein erster Ansatz für die automatisierte Berechnung von<br />

Nullpunkten ist mit etwa 3.000 Jahren weitaus älter als<br />

Fortran: das Sekantenverfahren. Wir können an dieser Stelle<br />

leider nicht im Detail erklären, wie es funktioniert, und müssen<br />

Interessierte an Wikipedia verweisen. Der folgende Code<br />

implementiert den Algorithmus. Speichern Sie folgenden<br />

Code als secant.f95:<br />

! Berechnung des Nullpunktes von 2x^2-1 mit dem Sekantenverfahren<br />

program secant<br />

implicit none<br />

real, parameter :: error = 1.0e-6<br />

real :: x0, x1, temp<br />

integer :: i = 1, limit = 100<br />

x0 = 0<br />

x1 = 1.0<br />

do<br />

if (i > limit) then<br />

print *, “Keine Konvergenz. Berechnung beendet. ”<br />

exit<br />

endif<br />

if (f(x1) == 0) then<br />

print *, “Nullpunkt ist genau “, x1<br />

exit<br />

else if (abs(x1 - x0) < error) then<br />

print *, “Nullpunkt ist genähert “, x1<br />

exit<br />

end if<br />

temp = secanteq(x0, x1)<br />

call reallocate(x0, x1, temp)<br />

Debuggen<br />

Unglücklicherweise sind die Fehlermeldungen<br />

der meisten Fortran-Compiler bei der<br />

Fehlersuche nur in wenigen Fällen hilfreich.<br />

Überprüfen Sie daher selbst, dass Sie implicit<br />

none angegeben haben. Sie sollten außerdem<br />

print-Anweisungen überall im Code verteilen, um<br />

dem Programmablauf auf die Finger zu sehen.<br />

Danach können Sie sich mit den diversen<br />

Debug-Optionen von GFortran vorantasten:<br />

-O0. weist den Compiler an, auf Optimierungen<br />

zu verzichten. Zwar ist das Programm dann sehr langsam,<br />

die Qualität der Fehlermeldungen wird jedoch<br />

erhöht.<br />

-Og schaltet in GFortran-Versionan ab 4.8 nur solche<br />

Optimierungen ein, die Fehlermeldungen nicht beeinflussen.<br />

-Wall zeigt „alle“ Warnungenen an, während<br />

-Wextra noch ein paar Warnungen mehr anzeigt.<br />

-pedantic warnt vor Sprachfeatures, die von<br />

GFortran, nicht aber vom offiziellen Standard unterstützt<br />

werden.<br />

-g ermöglicht die Verwendung des interaktiven GNU-<br />

Debuggers gdb. Mit gdb programmname starten Sie<br />

den Debugger, mit break main setzen Sie einen<br />

Haltepunkt vor der ersten ausführbaren Anweisung,<br />

mit run starten Sie bis zum ersten Haltepunkt und mit<br />

step führen Sie jede Anweisung einzeln aus.<br />

Für GDB gibt es im Internet ausführliche Anleitungen.<br />

Außerdem gibt es dort weitere, teils bequemere<br />

Fortran-Debugger.<br />

156


Programmiersprachen<br />

i = i+1<br />

!entfernen Sie die folgende Kommentierung, um die Schleife in Aktion zu sehen<br />

!print *, “x0 is “, x0, “x1 is “, x1<br />

end do<br />

contains<br />

function f(x)<br />

real :: f<br />

real, intent(in) :: x<br />

f = 2.0*x*x - 1.0<br />

end function f<br />

function secanteq(x0, x1)<br />

real :: secanteq<br />

real, intent(in) :: x0, x1<br />

secanteq = x1 - (f(x1) * (x1 - x0) / (f(x1) - f(x0)))<br />

end function secanteq<br />

subroutine reallocate(x0, x1, temp)<br />

real :: x0, x1, temp<br />

x0 = x1<br />

x1 = temp<br />

end subroutine reallocate<br />

end program secant<br />

Betrachten wir zuerst die Struktur des Programms. Es<br />

besteht aus einem Abschnitt für die Initialisierung, einer<br />

do-Schleife sowie aus einem contains-Abschnitt.<br />

Hinter dem Schlüsselwort contains erwartet Fortran die<br />

Definition von lokalen Unterprogrammen (function oder subroutine).<br />

Hinter der end program-Zeile können Sie zudem<br />

globale Unterprogramme definieren. Zwischen function und<br />

subroutine bestehen wichtige Unterschiede:<br />

1 function hat einen Rückgabewert, subroutine nicht.<br />

2 function muss mindestens einen Parameter haben,<br />

subroutine darf auch mal keine haben<br />

Erwartungsgemäß steht der Rumpf einer Unterfunktion<br />

zwischen den entsprechenden Schlüsselwörtern function ...<br />

end function und subroutine ... end subroutine.<br />

Sehen wir uns nun an, was in dem Programm passiert. In<br />

den ersten Zeilen werden Variablen definiert, wobei lediglich<br />

das parameter-Schlüsselwort neu ist. Es wird in Fortran verwendet,<br />

um eine Konstante zu definieren. Jeder Versuch, dieser<br />

Konstante im weiteren Programmverlauf einen Wert<br />

zuzuweisen, führt zu einem Compiler-Fehler.<br />

x0 und x1 sind einfache Variablen, die sich im<br />

Programmverlauf immer mehr an den gesuchten Nullpunkt<br />

annähern sollen.<br />

Der größte Teil der Programmlogik ist innerhalb der<br />

do-Schleife enthalten. Da wir im Gegensatz zu oben keine<br />

Laufvariable verwenden, wird die Schleife unendlich oft<br />

durchlaufen. Um das Programm zu beenden, benötigen wir<br />

also mindestens eine solide Abbruchbedingung im<br />

Schleifenrumpf. In diesem Beispiel testen wir daher, ob der<br />

informelle Schleifenzähler i das limit von 100 Durchläufen<br />

erreicht hat, und beenden die Schleife gegebenenfalls mit<br />

exit.<br />

Jeder Schleifendurchlauf betrachtet außerdem die beiden<br />

x-Werte und bricht die Schleife entweder ab oder berechnet<br />

die x-Werte neu.<br />

Direkt nach dem limit-Test überprüfen wir, ob der zuletzt<br />

berechnete x-Wert x1 ein Nullpunkt ist. Dazu übergeben wir<br />

x1 einfach der Funktion f und untersuchen deren<br />

Rückgabewert. Wenn diese Bedingung erfüllt ist, haben wir<br />

den Nullpunkt gefunden und brechen ab. Wir testen auch auf<br />

„fast am Ziel“: Wenn die beiden zuletzt berechneten x-Werte<br />

x0 und x1 nahezu identisch sind, dann haben wir näherungsweise<br />

einen Nullpunkt gefunden und brechen ebenfalls ab.<br />

Die maximale Differenz dieser beiden Zahlen haben wir in der<br />

Konstanten error festgelegt, sie beträgt 0.000001.<br />

Wenn keine Abbruchbedingung erfüllt ist, dann berechnen<br />

wir die Sekante für x0 und x1 und sichern sie in temp.<br />

Anschließend speichert das Unterprogramm swap noch x1 in<br />

x0 und temp in x1, womit wir für den nächsten<br />

Schleifendurchlauf gewappnet sind.<br />

Unterprogramme<br />

Der contains-Abschnitt enthält zwei Funktionen. Bei f(x)<br />

handelt es sich um die Funktion, deren Nullpunkt wir bestimmen<br />

möchten. Die andere Funktion ist secanteq(x0, x1), die<br />

das Sekantenverfahren für die beiden Parameter durchführt.<br />

In der ersten Zeile eines jeden Funktionsrumpfs wird dem<br />

Funktionsnamen ein Typ zugewiesen, außerdem wird der<br />

Funktionsname fortan als Variable verwendet – hierbei handelt<br />

es sich um den Rückgabewert der Funktion. Auf ähnliche<br />

Weise wird der Typ der Parameter festgelegt. Der Versuch,<br />

einen unpassenden Wert als Funktionsparameter zu übergeben,<br />

wird mit einem Compiler-Fehler quittiert.<br />

Eine Fortran-Besonderheit ist das intent(in)-Schlüsselwort.<br />

Es legt fest, dass die Parameter nur als Eingabe verwendet<br />

werden dürfen und ihren (möglicherweise innerhalb<br />

der Funktion veränderten) Wert nach dem Funktionsende<br />

nicht an den Aufrufer zurückgeben.<br />

Für eine subroutine gilt Entsprechendes. Auch hier muss<br />

der Typ jedes Parameters festgelegt werden und mit<br />

intent(in) kann man sie als Eingabeparameter definieren. Im<br />

Fall von reallocate verzichten wir darauf: Wir überschreiben<br />

den alten Wert von x0 mit dem Wert von x1, und x1 erhält<br />

daraufhin den Wert von temp. Nach dem Aufruf dieser<br />

Funktion hat sich der Wert dieser beiden Variablen aus Sicht<br />

des Aufrufers entsprechend geändert.<br />

Dieser kurze Einstieg in Fortran soll genügen, um Ihnen<br />

die Sprache vorzustellen. Für Programmierer modernerer<br />

Sprachen fühlt sich Fortran zunächst etwas verstaubt an, tatsächlich<br />

verfügt aber F90 über alle Elemente einer prozeduralen<br />

Programmiersprache und seit Fortran 2003 kann man<br />

sogar objektorientiert programmieren. Wer sich darauf einlässt,<br />

der findet in Fortran eine ausgereifte und vor allem<br />

schnelle Sprache für mathematische Aufgaben aller Art.<br />

Zudem steht in der 60 Jahre alten Sprache für nahezu jedes<br />

mathematische Problem längst eine Lösung zum kostenlosen<br />

Download aus dem Internet bereit, die sich mit geringem<br />

Aufwand an eigene Bedürfnisse anpassen lässt.<br />

Die Nullpunktbestimmung<br />

für<br />

2x²-1. Wenn Sie<br />

die print-Zeile<br />

im Code entkommentieren,<br />

dann können Sie<br />

wie hier gezeigt<br />

die einzelnen<br />

Näherungsschritte<br />

verfolgen.<br />

157


Programmiersprachen<br />

Lua: Erste Schritte<br />

Lua wird vom Spiele-Scripting bis zur Bildbearbeitung in den<br />

unterschiedlichsten Anwendungen genutzt. Ein Crashkurs.<br />

Die Ausgabe<br />

der Lua-<br />

Installation und<br />

vom Interpreter<br />

selbst.<br />

Lua ist eine schnelle, leichtgewichtige Interpreter-Skript-<br />

Sprache. Bei der Konzeption stand die Integrierbarkeit<br />

in andere Systeme an erster Stelle: Die Sprache und ihr<br />

Interpreter sind schlank, sie können an bestehende<br />

Programme angefügt und mit der einfachen API komplikationslos<br />

integriert werden. Die Sprache selbst hat nur wenige<br />

Features, aber sie kann durch Metamechanismen schnell<br />

passend zum jeweiligen Einsatzzweck erweitert werden<br />

(auch wenn dies den Rahmen diese Tutorials sprengen würde).<br />

Da sie einfach zu erlernen ist, ist sie gleichzeitig sowohl<br />

praxisnah als auch ein perfektes Experimentierfeld.<br />

Holla Lua<br />

Um die aktuellste Version von Lua zu erhalten (Release-<br />

Version 5.2.3 zum Redaktionsschluss), lädt man am besten<br />

den Quellcode herunter und erstellt die Binary selbst:<br />

curl -R -O http://www.lua.org/ftp/lua-5.2.2.tar.gz<br />

tar zxf lua-5.2.2.tar.gz<br />

cd lua-5.2.2/<br />

make linux test<br />

sudo make install<br />

Dies erstellt das Paket und installiert es in /usr/local/bin.<br />

Nun öffnen Sie ein Terminal und geben lua ein. Sie sollten<br />

damit zur Lua-Eingabeaufforderung gelangen, wo Sie<br />

Programmcode direkt eingeben können:<br />

> print(“Hello World”)<br />

Hello World<br />

><br />

Lua: Lecker Häppchen<br />

Die Eingabeaufforderung ist nützlich, um mit einzelnen<br />

Befehlen zu experimentieren. Mit dofile dateiname kann<br />

man aber auch ganze Code-Dateien in den Interpreter laden.<br />

Eine ausführbare Programmdatei für das klassische<br />

„Hello World“ ist entsprechend einfach zu erstellen. Erstellen<br />

Sie eine Datei namens hello.lua mit diesem Inhalt:<br />

print(“Hello World”)<br />

Starten Sie nun das Programm von der Kommandozeile<br />

mit lua hello.lua, dann sehen Sie die zu erwartende Ausgabe.<br />

In Lua haben Funktionen die bewährte funktion(argument)-Syntax.<br />

print() wird verwendet, um einzelne<br />

Textzeilen auszugeben. Die Funktion ruft für jedes Argument<br />

dessen tostring()-Funktion auf und hängt dem<br />

Gesamtergebnis einen Zeilenumbruch an. Wenn Sie mehr<br />

Kontrolle über die Ausgabe benötigen, dann verwenden Sie<br />

die Funktion io.write(), die wir später genauer betrachten.<br />

Ein Mehrzeiler<br />

Nach dem Einzeiler Hello World wagen wir uns nun an etwas<br />

Komplexeres. Wir schreiben ein einfaches<br />

Zeitmanagementprogramm, das die Start- und Endzeiten<br />

einer Aufgabe aufzeichnet. Zuerst benötigen wir eine<br />

Funktion, welche den Startzeitpunkt annimmt. Erstellen Sie<br />

eine Datei time.lua mit folgendem Inhalt:<br />

filename = “timefile.txt”<br />

function recordStart(title)<br />

local timenow = os.time()<br />

io.output(filename)<br />

io.write(string.format(“%s, start %d”, title, timenow)) end<br />

io.stdout:write(“Type project name\n”)<br />

local project = io.stdin:read()<br />

io.stdout:write(“Type s to start timing or c to cancel\n”)<br />

local input = io.stdin:read()<br />

if input == “s” then<br />

recordStart(project)<br />

else<br />

error(“Projektstart abgebrochen”)<br />

end<br />

In Lua ist die Reihenfolge wichtig, in der einzelne<br />

Anweisungen auftauchen. Da Lua interpretiert und nicht<br />

kompiliert wird, kennt es nur die Dinge, die es bereits gesehen<br />

hat. <strong>Das</strong> bedeutet, dass alle Funktionen deklariert und<br />

In Lua ist jeder ausführbare Code ein sogenannter<br />

Chunk – eine Sequenz einzelner<br />

Anweisungen. Dies kann eine ganze Code-Datei<br />

sein, die Befehl für Befehl abgearbeitet wird,<br />

oder eine einzelne, in den Interpreter getippte<br />

Zeile. Es gibt keine main()-Funktion oder<br />

Ähnliches, ein Chunk wird so, wie er ist, interpretiert.<br />

Ein Chunk kann natürlich Funktionen definieren<br />

und ausführen.<br />

Ein nützlicher Tipp zum Debuggen ist, ein paar<br />

Chunks einzulesen und Lua dann direkt in den<br />

interaktiven Modus gehen zu lassen:<br />

lua -i -lfile -lotherfile<br />

Dies liest die Chunks aus datei und anderedatei<br />

ein, führt sie aber nicht aus. Stattdessen öffnet<br />

sich die Eingabeaufforderung. Wenn Sie nun eine<br />

Anweisung – die sich auf die eingelesenen<br />

Chunks beziehen kann – eintippen und [Return]<br />

drücken, dann wird Lua die Anweisung direkt<br />

ausführen. Wenn Lua kein komplettes Chunk<br />

identifizieren kann, dann wartet es auf weitere<br />

Eingaben. So können Sie auch auf der<br />

Kommandozeile Mehrzeiler wie beispielsweise<br />

Funktionen definieren.<br />

158


Programmiersprachen<br />

definiert sein müssen, bevor sie aufgerufen werden können.<br />

Lua-Programme beginnen daher stets mit globalen<br />

Variablen, dahinter stehen die Funktionen und die initiale<br />

Programmlogik folgt zum Schluss. Alle Lua-Variablen wie im<br />

Beispiel filename sind global, sofern sie nicht mit dem<br />

Schlüsselwort local als lokale Variable (im Beispiel local<br />

input und local project) deklariert wurden. Wenn Sie eine<br />

Variable lediglich in dem Block benötigen, in dem sie deklariert<br />

wurde, dann ist es gute Sitte, sie als lokal zu deklarieren.<br />

Dies ist sauberer und verhindert unbeabsichtigte<br />

Seiteneffekte.<br />

Am Ende des Funktionsblocks sehen Sie das bereits<br />

erwähnte io.write() als Alternative zu print(). Denken Sie<br />

daran, an das Ende des Ausgabe-Strings den Zeilenvorschub<br />

\n anzuhängen. io.write() schreibt immer an das „aktuelle“<br />

Datei-Handle, was – sofern Sie es nicht manuell ändern –<br />

stdin/stdout ist. Um ganz sicherzugehen, dass Sie in das<br />

gewünschte Ziel schreiben, verwenden Sie stattdessen<br />

io.stdout:write(). Für Tastatureingaben verwenden Sie<br />

io.stdin:read().<br />

Der Code enthält außerdem if / then / else / end-Statements.<br />

Lua benötigt für ein if-Statement keine Klammern<br />

und das then sollte in der gleichen Zeile stehen. <strong>Das</strong> end<br />

kann hingegen auch hinter einem Befehl stehen.<br />

Zu guter Letzt sehen Sie in recordStart() den<br />

io.output()-Befehl: Dieser setzt das Ziel für folgende io.<br />

write()-Ausgaben auf die genannte Datei. Dort hinein<br />

schrei ben wir nun mit string.format() formatierte Texte.<br />

os.time() liefert die Zeitspanne in Sekunden seit einem intern<br />

festdefinierten Zeitpunkt. Wenn wir die Zeit später dem<br />

Programmbenutzer präsentieren wollen, nutzen wir<br />

Funktionen der time-Bibliothek zur Übersetzung in menschenlesbare<br />

Strings.<br />

Wenn Sie das Programm mit lua time.lua mehrmals starten,<br />

dann wird timefile.txt stets mit neuen Werten überschrieben.<br />

Der Start eines weiteren Projektes (ohne das vorherige<br />

abgeschlossen zu haben) wäre nicht möglich. Daher verändern<br />

wir den Dateizugriff:<br />

function recordStart(title)<br />

local timenow = os.time()<br />

local f = assert(io.open(filename, “a”))<br />

f:write(string.format(“%s, start %d\n”, title, timenow))<br />

f:close()<br />

end<br />

Die Zeile assert(io.open()) ist ein typisches Lua-Idiom.<br />

io.open() öffnet erwartungsgemäß die genannte Datei im<br />

gewünschten Modus (hier a für append/Anhängen). <strong>Das</strong><br />

Ergebnis f ist das Dateihandle, in das wir ähnlich wie bisher<br />

schreiben können. Die assert()-Funktion stellt darüber hinaus<br />

sicher, dass im Ausnahmefall eine Fehlermeldung<br />

gezeigt wird.<br />

Nun sollten Sie in der Lage sein, so viele Projekte zu starten,<br />

wie Sie möchten. Vor dem nächsten Schritt überprüfen<br />

Sie dies in der Ausgabedatei.<br />

Projekt abgeschlossen<br />

Zwar können wir nun viele Projekte beginnen, aber wir können<br />

sie noch nicht beenden. Also brauchen wir eine weitere<br />

Funktion:<br />

function recordEnd(title)<br />

local timenow = os.time()<br />

local f = assert(io.open(filename, “a”))<br />

f.write(string.format(“%s, end %d\n”, title, timenow))<br />

f:close()<br />

end<br />

-- Benutzereingabe wie zuvor<br />

if input == “s” then<br />

recordStart(project)<br />

elseif input == “t” then<br />

recordEnd(project)<br />

else<br />

error(“Projektstart abgebrochen”)<br />

end<br />

Im Hauptprogramm haben wir dem if-Block mit elseif<br />

input == “t” eine weitere Eingabemöglichkeit hinzugefügt.<br />

Die Anzahl der elseif-Anweisungen ist prinzipiell unbegrenzt.<br />

<strong>Das</strong> Programm fügt der Ausgabedatei nun für jedes<br />

Projektende eine neue Textzeile hinzu, besser wäre aber eine<br />

einzelne Zeile für jedes Projekt. Dafür müssen wir die entsprechende<br />

Zeile einlesen und verändern. Also verbessern<br />

wir die recordEnd()-Funktion und brechen sie zugunsten der<br />

besseren Lesbarkeit in kleinere Funktionen auf:<br />

function editLine(line)<br />

local timenow = os.time()<br />

return line .. string.format(“, end %d”, timenow) end<br />

function writeWholeTimeFile(lines, linesRemain)<br />

local f = assert(io.open(filename, “w”))<br />

for i, line in ipairs(lines) do<br />

f:write(line, “\n”)<br />

end<br />

if linesRemain then f:write(linesRemain) end<br />

f:close() end<br />

function recordEnd(title)<br />

local f = assert(io.open(filename, “r”))<br />

local lines = {}<br />

local linesRemain<br />

for line in f:lines() do<br />

if string.find(line, string.format(“^%s”, title)) then<br />

lines[#lines + 1] = editLine(line)<br />

linesRemain = f:read(“*a”)<br />

break<br />

else<br />

lines[#lines + 1] = line<br />

end<br />

end<br />

f.close()<br />

writeWholeTimeFile(lines, linesRemain)<br />

end<br />

Leider bietet Lua keine einfache Möglichkeit, einzelne<br />

Textzeilen einer Datei zu verändern. Stattdessen lesen wir die<br />

komplette Datei ein und geben sie gleich wieder aus, wobei<br />

lediglich die gewünschte Zeile verändert wird.<br />

In recordEnd() öffnen wir die Datei und definieren einige<br />

Variablen. lines ist ein Array, also eine Ansammlung einzelner<br />

Werte. Arrays haben in Lua keine feste Größe, also wird auch<br />

Starten Sie<br />

das Programm<br />

mehrmals und<br />

überprüfen Sie<br />

anschließend<br />

den Inhalt der<br />

Ausgabedatei<br />

Schnelltipp<br />

Lua-Kommentare<br />

beginnen mit -- und<br />

können auch hinter<br />

anderen Anweisungen<br />

stehen.<br />

Die foo:method()-Syntax<br />

ruft die<br />

Funktion method()<br />

des Objekts foo auf.<br />

Beispielsweise ist<br />

io eine Bibliothek<br />

und io.stdin ein<br />

bestimmtes Objekt<br />

(in diesem Fall ein<br />

Datei-Handle),<br />

das mit der Standard-Eingabe<br />

des<br />

Systems korrespondiert..<br />

Schnelltipp<br />

159


Programmiersprachen<br />

Schnelltipp<br />

Wenn Sie mit echten<br />

Uhrzeiten<br />

arbeiten, können<br />

Sie os.date() mit<br />

etlichen Formatoptionen<br />

einsetzen,<br />

um aus den<br />

Sekundenzahlen<br />

benutzerfreundliche<br />

Zeit- und<br />

Datumswerte<br />

erstellen zu lassen.<br />

Mit Zeitspannen<br />

funktioniert dies<br />

leider nicht, für<br />

diese ist Handarbeit<br />

gefordert.<br />

Ein Projekt<br />

endet. Keine<br />

Panik: Die angezeigten<br />

Zahlen<br />

der Ausgabedatei<br />

dürfen sich von<br />

Ihren Werten<br />

unterscheiden.<br />

keine Initialisierung benötigt. <strong>Das</strong> erste Array-Element kann<br />

eine beliebige Index-Nummer haben, die gängige Konvention<br />

ist in Lua die Zahl 1. Die for-Schleife iteriert über die Zeilen in<br />

der Datei, indem sie die lines()-Funktion der Lua-Bibliothek<br />

nutzt. Für jede Zeile line testen wir mit string.find(), ob sie<br />

mit dem gesuchten Projektnamen beginnt. Wenn nicht (der<br />

else-Block), dann hängen wir die aktuelle Zeile an das<br />

lines-Array an. #lines ist die aktuelle Anzahl der Einträge im<br />

lines-Array und da wir mit dem Index 1 zu zählen beginnen,<br />

ist #lines + 1 der nächste leere Eintrag im Array. Wenn die<br />

eingelesene Zeile hingegen mit dem gesuchten Projekttitel<br />

beginnt, dann verändern wir diese mit der Funktion edit-<br />

Line(), die wiederum den ...-Operator zum Verbinden zweier<br />

Strings verwendet. Erneut schreiben wir diese Zeile an das<br />

Ende des lines-Arrays. Anschließend lesen wir alle verbleibenden<br />

Zeilen aus der Datei (*a bedeutet alle) in linesRemain<br />

ein und beenden die Schleife mit break. Nun schließen<br />

wir die Datei und rufen writeWholeTimeFile() auf, um zuerst<br />

lines und dann linesRemain zurückzuschreiben.<br />

In writeWholeTimeFile() verwenden wir w anstatt a, da<br />

wir bewusst die bestehende Datei überschreiben möchten.<br />

Ansonsten ist nur iwrite() neu: Diese Funktion iteriert über<br />

ein Array und gibt zwei Werte zurück: Den Array-Index (der<br />

hier in das ungenutzte i gespeichert wird) und den Array-<br />

Wert (hier line). Bevor linesRemain zurückgeschrieben wird,<br />

testen wir, ob linesRemain überhaupt einen Wert zugewiesen<br />

bekam.<br />

Damit ist unser Programm bereits weitaus besser als<br />

zuvor, aber wir wissen noch nicht, wie lange ein Projekt<br />

gedauert hat. Lassen Sie uns also die Dauer berechnen, ausgeben<br />

und abspeichern. Hierzu müssen wir nur eine Zeile in<br />

editLine() ändern:<br />

function editLine(line)<br />

local timenow = os.time()<br />

local _, _, starttime = string.find(line, “%w+, start (%d+)$”)<br />

local duration = timenow - starttime<br />

print(string.format(“Duration was %d minutes %d seconds”,<br />

duration/60, duration % 60))<br />

return line .. string.format(“, end %d, duration %d”, timenow,<br />

duration)<br />

end<br />

Die Variable _ ist ein Platzhalter. Da wir nicht an den ersten<br />

beiden Rückgabewerten von string.find() interessiert sind<br />

(nämlich der Index, an dem der Treffer beginnt und der<br />

Index, an dem er endet), ignorieren wir diese und speichern<br />

sie in Platzhaltern ab.<br />

Wir berechnen die Dauer und geben sie mittels print() in<br />

benutzerfreundlicher Form aus (% ist der Modulo-Operator,<br />

der für Zeitberechnungen sehr hilfreich ist), zudem hängen<br />

wir den Wert an den Rückgabe-String an.<br />

Wir können nun Projekte starten, beenden und die<br />

Projektdauer bestimmen. Allerdings können wir nur eine<br />

Dauer je Projekt speichern – schöner wäre es, wenn wir je<br />

Projekt mehrere Einträge speichern könnten und wenn die<br />

Dateneingabe bequemer wäre.<br />

Stechuhr<br />

Wir könnten CSV-Dateien nutzen, um solche komplexen<br />

Daten zu speichern. In Lua verwendet man allerdings stattdessen<br />

Arrays von Datensätzen (im Lua-Jargon „Tabelle“).<br />

Tatsächlich sind Datensätze die einzigen Datenstrukturen in<br />

Lua (sogar Arrays sind getarnte Datensätze). Sie sind sehr<br />

flexibel, einfach zu erstellen und zu benutzen. Wir erstellen<br />

eine Tabelle, in der der Schlüssel eine Zahl ist und dessen<br />

Werte Datensätze mit den einzelnen Zeiten sind:<br />

{<br />

1 -> {project = NAME, starttime = TIME, endtime = TIME, duration =<br />

DURATION}<br />

2 -> {project = NAME, starttime = TIME, endtime = TIME, duration =<br />

DURATION}<br />

}<br />

Mit dieser Datenstruktur können wir nun für jeden<br />

Projektnamen beliebig viele Einträge speichern. Wie bereits<br />

erwähnt, ist diese Tabelle ein Array von Datensätzen, weshalb<br />

wir ein paar neue Funktionen benötigen. Wir beginnen<br />

mit einer neuen Methode, um die Startzeiten aufzuzeichnen,<br />

und einer Funktion, um die Tabelle anzuzeigen (nicht notwendig,<br />

aber hilfreich beim Suchen von Fehlern):<br />

timetable = {}<br />

function tableRecordStart(title)<br />

local timenow = os.time()<br />

table.insert(timetable, {project = title, starttime = timenow})<br />

end<br />

function outputTableToScreen()<br />

print “Printing table”<br />

for i, v in ipairs(timetable) do<br />

print(i, v.project, v.starttime, v.endtime, v.duration)<br />

end<br />

end<br />

-- Main code as before, with this edit:<br />

if input == “s” then<br />

Mustererkennung<br />

Dies ist die string.find()-Zeile aus unserem<br />

Code:<br />

local _, _, starttime = string.find(line, “%w+, start<br />

(%d+)$”)<br />

Dieser Ausdruck sucht nach dem zwischen<br />

den Anführungszeichen definierten Muster<br />

%w+, start(%d+)$. Hier kommen sogenannte<br />

Reguläre Ausdrücke zum Einsatz, die sich in Lua<br />

etwas von den Standard-POSIX-RegExp unterscheiden.<br />

Wie in POSIX bedeutet %w+ „ein oder mehrere<br />

alphanumerische Zeichen“, %d+ bedeutet<br />

„eine oder mehrere Zahlen“ und das $ markiert<br />

das Zeilenende. Die Klammern werden verwendet,<br />

um ein Match zu markieren – auf diese<br />

Weise finden wir (neben zwei weiteren Matches)<br />

das gesuchte starttime im line-String.<br />

Die gleiche Syntax wird in string.gsub() und<br />

allen anderen Pattern-Matching-Funktionen von<br />

Lua verwendet.<br />

160


Programmiersprachen<br />

tableRecordStart(project)<br />

elseif ...<br />

-- rest as before outputTableToScreen()<br />

Die globale Variable timetable wird zu Beginn erstellt. Die<br />

Funktion tableRecordStart hängt mittels table.insert() an<br />

das Ende von timetable einen neuen Datensatz an. Mit weiteren<br />

Argumenten hätten wir sogar bestimmen können, an<br />

welcher Position der Datensatz in timetable gespeichert<br />

wird. Beachten Sie, dass wir keine Werte für endtime oder<br />

duration festgelegt haben: In Lua können Datensätze auch<br />

nachträglich verändert werden. In der Ausgabefunktion<br />

nutzen wir wieder ipairs(), um über die Tabelle zu iterieren.<br />

i ist der numerische Schlüssel und v ist der Wert; in<br />

unserem Fall ein ganzer Datensatz. Auch dies zeigt, dass<br />

unser obiges Textzeilen-Array nur ein getarntes<br />

Datensatz-Array ist.<br />

Es gibt mehrere Wege, um Informationen aus einem<br />

Datensatz zu lesen; beispielsweise table.name. Dies ist<br />

gleichbedeutend mit table[„name“], was wiederum nichts<br />

anderes als den Wert eines Arrays am Index [„name“] darstellt.<br />

Würden wir hingegen table[name] schreiben, dann<br />

würde Lua name als Variable interpretieren und den Wert<br />

dieser Variablen als Schlüssel nutzen. Daher sind folgende<br />

Ausdrücke nicht identisch:<br />

name = “foo” table[name] = “bar” --dies entspricht table[“foo”]<br />

table. name = “foo” -- dies entspricht table[“name”]<br />

Wenn wir wie in tableRecordStart() mit der Syntax project<br />

= title einen Datensatz erstellen, dann wird project als<br />

String interpretiert, title als Stringvariable. Achten Sie also<br />

immer auf Ihre Verweise und Indizes!<br />

Wenn wir diesen Code starten, dann können wir<br />

Projektstarts eingeben, die nun als Tabelle angezeigt werden<br />

– und am Programmende verschwinden. Also müssen wir die<br />

Daten noch speichern und laden. An dieser Stelle kommt das<br />

Chunks-Feature von Lua sehr gelegen: Wenn wir die<br />

Datensätze auf folgende Weise abspeichern (serialisieren):<br />

readInTable{project = “test”, starttime = “1383216178”, endtime =<br />

“1383216665”, duration = “487”}<br />

readInTable{project = “test”, starttime = “1383216714”, endtime =<br />

“1383216731”, duration = “17”}<br />

und diesen Dateiinhalt als Lua-Code ausführen, dann wird<br />

eine Funktion namens readInTable() mit den entsprechenden<br />

Argumenten ausgeführt. Wir können unsere Tabelle also<br />

folgendermaßen einlesen:<br />

function readInTable(o)<br />

table.insert(timetable, o)<br />

end<br />

dofile(filename)<br />

dofile(filename) liest die genannte Datei und führt sie als<br />

Lua-Code aus. Die Zeilen werden Stück für Stück eingelesen<br />

und mittels readInTable() (o ist das Datensatzargument) an<br />

das Ende von timetable angehängt. Für diese elegante<br />

Lösung müssen wir die Tabelle lediglich entsprechend serialisieren:<br />

function serialiseTable()<br />

local f = assert(io.open(filename, “w”))<br />

for i, v in ipairs(timetable) do<br />

f:write(string.format(<br />

“readInTable{project = \”%s\”, starttime = \”%d\”, endtime =<br />

\”%d\”, duration = \”%d\”}\n”,<br />

v.project, v.starttime, v.endtime or 0, v.duration or 0))<br />

end<br />

f:close()<br />

end<br />

-- Main code as before<br />

outputTableToScreen()<br />

serialiseTable()<br />

Dieser Code sollte keine Überraschungen beinhalten, da<br />

er nur eine Datei öffnet und schreibt sowie über eine Tabelle<br />

iteriert. Zugegebenermaßen ist der Formatstring sehr hässlich<br />

– beachten Sie die Escape-Zeichen an den<br />

Anführungszeichen. Die einzige Neuerung ist der v.endtime<br />

or 0-Ausdruck. Dieser ist gleichbedeutend mit:<br />

if not v.endtime then v.endtime = 0 end<br />

Dies ist notwndig, da v.endtime and v.duration bei einem<br />

Projektstart nicht initialisiert sind und damit den Wert nil<br />

haben – was wiederum in string.format() zu Problemen führen<br />

würde. Starten Sie den Code und sehen Sie sich die<br />

Ausgabedatei an. Sie sollte nun hübsch formatierte<br />

Datensätze beinhalten. Nun benötigen wir nur noch eine<br />

Funktion, um ein Projektende einzugeben:<br />

function tableRecordEnd(title)<br />

local timenow = os.time()<br />

for i, v in ipairs(timetable) do<br />

if v.project == title and tonumber(v.endtime) == 0 then<br />

d = timenow - v.starttime<br />

table.remove(timetable, i)<br />

table.insert(timetable, i, {project = v.project, starttime = v.starttime,<br />

endtime = timenow, duration = d})<br />

print(string.format(“Duration was %d minutes %d seconds”,<br />

d/60, d % 60))<br />

break<br />

end<br />

end<br />

end<br />

dofile(filename)<br />

-- input lines as before<br />

if input == “s” then<br />

tableRecordStart(project)<br />

elseif input == “t” then<br />

tableRecordEnd(project) 
else<br />

error(“Projektstart abgebrochen”)<br />

end<br />

outputTableToScreen()<br />

serialiseTable()<br />

tableRecordEnd() iteriert über die Datensätze und sucht nach<br />

einer Zeile mit dem richtigen Projektnamen, aber ohne Endzeitpunkt.<br />

Wir verwenden tonumber(), da v.endtime ja aus einer Datei stammt<br />

und dort als String abgelegt wird. Wenn wir einen Treffer erhalten,<br />

verändern wir den Eintrag. In Lua genügt es allerdings nicht, den<br />

aktuellen Iterationswert v zu verändern. Stattdessen löschen wir ihn<br />

aus der Tabelle heraus und fügen einen neuen Datensatz mit gleichem<br />

Schlüssel an. Anschließend verraten wir nur noch dem<br />

Benutzer, wie lange er gearbeitet hat.<br />

Wie üblich kann man den Code an zahllosen Stellen verbessern:<br />

beispielsweise mit einer eine statistische Analyse der Projektzeiten.<br />

Bei den unvermeidlichen Fragen zu Programmfehlern oder<br />

gesuchten Funktionen hilft die ausgesprochen umfangreiche Lua-<br />

Online-Dokumentation, darüber hinaus gibt eine Community gerne<br />

Hilfe zur Selbsthilfe.<br />

Der<br />

Programmablauf<br />

und ein Blick in<br />

die Ausgabedatei.<br />

Wenn die<br />

Datei nicht existiert,<br />

dann tritt<br />

in dofile() ein<br />

Fehler auf.<br />

Schnelltipp<br />

Sie können eine<br />

Lua-Datei direkt<br />

ausführbar<br />

machen: Fügen<br />

Sie die Shebang-<br />

Zeile #!/path/to/<br />

lua print(“Hello<br />

World”) hinzu und<br />

starten Sie sie mit<br />

./hello.lua.<br />

161


<strong>PC</strong> <strong>Games</strong> <strong>Hardware</strong> – <strong>Das</strong> IT-Magazin für<br />

Gamer. Immer aktuell mit Kaufberatung,<br />

Hintergrundartikeln und Praxistipps.<br />

LEIDENSCHAFT FÜR GAMES


www.pcgameshardware.de • www.pcghx.de<br />

DAS HARDWARE-MAGAZIN FÜR <strong>PC</strong>-SPIELER<br />

HARDCORE<br />

FÜR<br />

SCHRAUBER<br />

QR-Code scannen<br />

und hinsurfen!<br />

Neue Ausgabe jetzt am Kiosk erhältlich<br />

oder einfach online bestellen unter:<br />

www.pcgh.de/shop<br />

Auch erhältlich als ePaper bei:


Professionelle Qualität zu attraktiven Preisen!<br />

über 45 Jahre Erfahrung<br />

50.000 Produkte am Lager<br />

über 24-Std.-Versand schneller -<br />

d<br />

kein Mindermengenzuschlag<br />

Kundenbewertungen<br />

<strong>Raspberry</strong><br />

+zubehor<br />

Über 97 % unserer Kunden<br />

sind vom reichelt-Service<br />

überzeugt*<br />

*Quelle: Shopauskunft.de (15.01.2014)<br />

zu einem<br />

Top-Preis!<br />

jetzt<br />

entdecken!<br />

„Eine Hi-tech-Himbeere,<br />

unendlich viele<br />

Möglichkeiten“<br />

<strong>Raspberry</strong> <strong>Pi</strong> - eine kreditkartengroße<br />

Platine mit schier endlos<br />

vielen Einsatzmöglichkeiten<br />

entdecken Sie den Mini-<strong>PC</strong> auf<br />

unserer <strong>Raspberry</strong>-Themenseite.<br />

<strong>Raspberry</strong>-<strong>Pi</strong><br />

Special-Themenseite<br />

<strong>Raspberry</strong> <strong>Pi</strong> Bundle<br />

mit 4-teiligem Kühlsatz!<br />

• Gehäuse im reichelt-Look<br />

• Netzteil, 1,2 A<br />

• NOOBS (Betriebssysteme)<br />

auf 8 GB SD-Karte<br />

• Mini-WLAN-Adapter<br />

• 4-tlg. Kühlsatz<br />

RASPBERRY ALL IN<br />

59,-<br />

Katalog<br />

01.1|2014!<br />

http://rch.lt/b9<br />

Jetzt bestellen:<br />

++NEU+++NEU+++NEU+<br />

Unterbrechungsfreie Stromversorgung<br />

Die USV für Ihren <strong>Raspberry</strong> <strong>Pi</strong><br />

• mit Halterung für 6 AA-Batterien<br />

• Kompatibel mit Arduino<br />

• 3x LED-Anzeige<br />

- Lieferung ohne<br />

<strong>Raspberry</strong> <strong>Pi</strong> -<br />

RASP PI USV 29,95<br />

Leistungsfähige RPI-Erweiterung<br />

NFC-konform mit NFC Karte<br />

• NFC IC auf der Basis des NXP PN512,<br />

erfüllt alle 3 NFC-Modi<br />

• Reader Mode unterstützt 4 NFC Tag Typen<br />

und proprietäre NXP MIFARE Befehle<br />

• Flexible Schnittstellenauswahl (SPI oder I²C)<br />

• Inklusive NXP MIFARE Ultralight NFC Karte<br />

NFC [Near Field Communication]<br />

RASP EXPLORE NFC 22,95<br />

www.reichelt.de<br />

Beste Verbindung!<br />

raspberry Arduino<br />

Gerduino<br />

Bestell-Hotline: +49 (0)4422 955-333<br />

<br />

<strong>Das</strong> Gertduino ist eine Erweiterung für<br />

Ihren <strong>Raspberry</strong> <strong>Pi</strong>, mit der sich viele<br />

Arduino Shields anschließen lassen.<br />

• 2x Atmel Mikrocontroller ( AT328, AT48 )<br />

• RTC • IrDA-Schnittstelle<br />

• RS232-Pegelumsetzer<br />

• Power-Backup für AT48<br />

RASP GERTDUINO 29,95<br />

<strong>Raspberry</strong> <strong>Pi</strong>, Modell B<br />

mit 512 MB RAM<br />

• Broadcom BCM2835<br />

• HDMI-/RCA-Composite-Video<br />

• 700 MHz ARM, Prozessor<br />

• Open GL ES 2.0, OpenVG<br />

• 10/100 BaseT-Ethernet<br />

• SD-Karten-Steckplatz<br />

• 2x USB 2.0<br />

8 )<br />

RASPBERRY PI B<br />

38, 95<br />

Kostenlos –<br />

Jetzt anfordern!<br />

Für Verbraucher: Es gelten die gesetzlichen Widerrufsregelungen. Alle angegebenen Preise in € inklusive der gesetzlichen MwSt., ab Lager Sande,<br />

zzgl. Versandspesen für den gesamten Warenkorb. Es gelten ausschließlich unsere AGB (unter www.reichelt.de/agb, im Katalog oder auf Anforderung).<br />

Zwischenverkauf vorbehalten. Alle Produktnamen und Logos sind Eigentum der jeweiligen Hersteller. Abbildungen ähnlich. Druckfehler, Irrtümer und<br />

Preisänderungen vorbehalten. reichelt elektronik GmbH & Co. KG, Elektronikring 1, 26452 Sande (HRA 200654 Oldenburg)<br />

Preisstand: 11. 03. 2014<br />

Tagesaktuelle Preise:<br />

www.reichelt.de

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!