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