Raspi-Webzugriff ohne extra Serverinstallation

Wenn man einen Raspberry-Pi remote betreibt, dann bleibt für die Interaktion nicht viel mehr übrig, als die Remote-Shell, ein Web-Frontend oder das Umleiten des X-Servers auf die Host-Maschine. In diesem Beitrag will ich mich auf die zweite Variante konzentrieren und aufzeigen, wie das sehr schnell ohne Installation eines eigenen Webservers, wie den Apache oder Nginx, geht.
Das Setup, welches ich gewählt habe, ist CherryPy, weil mit diesem Framework ein Web-Server mitkommt und außerdem mit der Raspberry-Pi Haus- und Hof-Programmiersprache Python gefüttert wird.
Bei meinen Programmierausflügen mit Python versuche ich immer auf die 3er Version von Python zu setzen, weswegen ich hier auch die Anleitung dafür auslege.
Als erstes muss man sich den Python Package Manager PIP installieren, um damit dann CherryPy zu installieren – das alles habe ich bereits in meinem Artikel PIP für Python 3.x unter Linux installieren beschrieben.
Als nächsten Schritt legt man am besten ein cherryPy-Verzeichnis an und speichert darin die cherryPy-Scripte. Hier darf natürlich das obligatorische Hello-World nicht fehlen. Auf der CherryPy-Seite ist dieses auch gleich an erster Stelle platziert. Ist man mit der graphischen Oberfläche direkt auf dem RasPi unterwegs so funktioniert das auf Anhieb, aber in meinem Fall soll der Zugriff ja remote innerhalb des Hausnetzwerkes erfolgen. Dazu muss das Script noch etwas angepasst werden und zusätzlich noch eine Konfigurationsdatei angelegt werden. Man könnte zwar die Konfiguration auch noch mit in das Python-Script packen, aber wir wollen bei unseren Experimenten ja nicht jedes Mal die selbe Konfiguration mit in das Script packen – das Angeben einer externen Konfigurationsdatei ist hier wohl deutlich komfortabler.
So habe ich das helloWorld-Beispiel folgendermaßen abgewandelt

#!/usr/bin/python3

import cherrypy

class HelloWorld(object):
    def index(self):
        return "Hello World!"
    index.exposed = True

if __name__ == '__main__':
	cherrypy.quickstart(HelloWorld(), config="cherryPy.conf")

und die dazugehörige Konfigurationsdatei cherryPy.conf wie folgt aufgebaut:

[global]
server.socket_host = "192.168.10.17"
server.socket_port = 8080
server.thread_pool = 10

Startet man nun das Script mit python3 cpHelloWorld.py, so sieht man wie der Server aufgesetzt wird.

pi@raspberrypi ~/cherryPy $ python3 cpHelloWorld.py 
[04/Apr/2015:09:52:37] ENGINE Listening for SIGHUP.
[04/Apr/2015:09:52:37] ENGINE Listening for SIGTERM.
[04/Apr/2015:09:52:37] ENGINE Listening for SIGUSR1.
[04/Apr/2015:09:52:37] ENGINE Bus STARTING
[04/Apr/2015:09:52:37] ENGINE Started monitor thread 'Autoreloader'.
[04/Apr/2015:09:52:37] ENGINE Started monitor thread '_TimeoutMonitor'.
[04/Apr/2015:09:52:37] ENGINE Serving on http://192.168.10.17:8080
[04/Apr/2015:09:52:37] ENGINE Bus STARTED

Die Hello-World Seite kann nun von jeder beliebigen Maschine im Netz unter der angegebenen IP-Adresse aufgerufen werden:
cherryPyHelloWorld
Und das tolle an diesem Setup ist, dass das Script nach einer Änderung nicht jedes Mal neu gestartet werden muss, sondern das Framework eine Modifikation der Datei automatisch erkennt und diese neu ausliefert.
Einfach mal ausprobieren und im Script aus „Hello World“ ein „Hello Raspi-World“ machen und die Datei abspeichern. Die Konsolenausgabe zeigt an, dass die Änderung erkannt wurde:

[04/Apr/2015:12:21:55] ENGINE Restarting because /home/pi/cherryPy/cpHelloWorld.py changed.
[04/Apr/2015:12:21:55] ENGINE Stopped thread 'Autoreloader'.
[04/Apr/2015:12:21:55] ENGINE Bus STOPPING
[04/Apr/2015:12:21:55] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('192.168.10.17',8080)) shut down
[04/Apr/2015:12:21:55] ENGINE Stopped thread '_TimeoutMonitor'.
[04/Apr/2015:12:21:55] ENGINE Bus STOPPED
[04/Apr/2015:12:21:55] ENGINE Bus EXITING
[04/Apr/2015:12:21:55] ENGINE Bus EXITED
[04/Apr/2015:12:21:55] ENGINE Waiting for child threads to terminate...
[04/Apr/2015:12:21:55] ENGINE Re-spawning cpHelloWorld.py
[04/Apr/2015:12:21:58] ENGINE Listening for SIGHUP.
[04/Apr/2015:12:21:58] ENGINE Listening for SIGTERM.
[04/Apr/2015:12:21:58] ENGINE Listening for SIGUSR1.
[04/Apr/2015:12:21:58] ENGINE Bus STARTING
[04/Apr/2015:12:21:58] ENGINE Started monitor thread 'Autoreloader'.
[04/Apr/2015:12:21:58] ENGINE Started monitor thread '_TimeoutMonitor'.
[04/Apr/2015:12:21:59] ENGINE Serving on http://192.168.150.175:8080
[04/Apr/2015:12:21:59] ENGINE Bus STARTED

Nun gilt es nur noch im Browser einen Reload zu veranlassen und siehe da, schon erscheint die Änderung im Browser.
cherryPy_helloRaspiWorld
Nun lässt sich das Script beliebig erweitern. Dazu rate ich die Tutorials der cherryPy-Dokumentation genauer zu studieren – evtl. gibt es ja auch noch einen weiteren Beitrag zu diesem Thema. Mal schauen, was die Zeit bringt.
Noch viel Spaß beim Ausprobieren!

Von Linux aus bequem auf Raspi-Dateien remote zugreifen

wer so wie ich mehrere Raspberry-Pis im Einsatz hat, auf diese vornehmlich remote zugreift und daran auch noch Daten produzierende Sensoren hat, der wird sich wohl auch schon das ein oder andere Mal gewünscht haben, bequem auf diese Dateien zugreifen zu können. Ich habe für mich die Lösung mittels SSH-Filesystem gefunden. Dazu muss auf dem Raspberry-Pi SSH aktiviert sein – das kann man über raspi-config erledigen:
sudo raspi-config
Unter dem Menüpunkt 8 Advanced Options befindet sich der Untermenüpunkt A4 SSH, der erlaubt SSH einzuschalten – enable.
raspiconfig-main

raspiconfig-advanced

raspiconfig-ssh

Nach diesem Schritt kann man sich remote über sein Netzwerk auf dem Raspberry-Pi einloggen und diesen damit headless betreiben. Unter Windows geht das z.B. über Putty, unter Linux über das Terminal – nämlich mit dem Kommando:
ssh pi@<ip-adresse/alias> z.B. ssh pi@192.168.10.12
Was nun aber zu nerven beginnt, ist das Eingeben des Passwortes, sobald man sich über SSH auf dem Raspi einlogged. Aber dafür gibt es auch Abhilfe.
Wenn man auf dem Rechner,von dem aus man sich auf dem Raspi einloggen will noch kein SSH-Schlüsselpaar liegen hat, so muss man sich erst mal ein neues SSH-Schlüsselpaar erzeugen.
Ob bereits ein Schlüsselpaar vorhanden ist, kann man einfach überprüfen, indem man sein home-Verzeichnis nach einem .ssh Unterverzeichnis durchsucht.
cd ~
ls -a | grep ssh
Ist das Verzeichnis vorhanden, so sollten sich mindestens folgende Dateien darin befinden (ls .ssh):
id_rsa id_rsa.pub
Ist das nicht der Fall, so kann man gleich ein neues Schlüsselpaar erzeugen:
ssh-keygen -t rsa
Bei der Aufforderung zur Eingabe des Speicherortes und des Passworts einfach Return drücken. Ich habe das mal auf einem frisch aufgesetzten Raspi nachvollzogen:
raspi-ssh-keygen
Und nun gilt es, den public-key (id_rsa.pub) auf den Zielrechner zu bekommen. Und hier kommt bereits das SSHFS zum Einsatz. Ist es noch nicht auf dem Host-Rechner installiert, so kann das ganz einfach über sudo apt-get install sshfs erledigt werden. Nun gilt es noch das Mount-Verzeichnis auf der Host-Seite einzurichten, was der Befehl mkdir <Zielverzeichnis> für uns erledigt. Wer so wie ich mehrere Raspberry-Pis sein Eigen nennt, dem empfehle ich zunächst ein Unterverzeichnis für die Raspberries anzulegen und darunter jedem Raspi sein eigenes Mount-Verzeichnis einzurichten:
mkdir ~/raspberry && cd ~/raspberry
mkdir pi_1 pi_2 pi_n
Nun steht dem SSHFS-Mount nichts mehr im Wege.
sshfs pi@<ip-adresse>:/home/pi ~/raspberry/pi_1
In diesem Fall wird nochmals das Passwort abgefragt, aber mit nachfolgenden Schritten kann das abgestellt werden.
Wenn auf dem Remote-Pi bereits ein .ssh-Verzeichnis im Home-Verzeichnis besteht und in diesem Verzeichnis bereits eine Datei namens authorized_keys liegt, so kann man den neuen Key über folgendes Kommando dazu fügen:
cat ~/.ssh/id_rsa.pub >> ~/raspberry/pi_1/.ssh/authorized_keys
Sollte das .ssh-Verzeichnis im Home-Verzeichnis des „remote-Raspi“ noch nicht existieren, so muss es angelegt werden:
mkdir ~/raspberry/pi_1/.ssh
um anschließend den Public-Key zu kopieren:
cp ~/.ssh/id_rsa.pub ~/raspberry/pi_1/.ssh/authorized_keys
Nun kann der Mount-Point über das Kommando
fusermount -u ~/raspberry/pi_1
ausgehängt werden, um ihn anschließend ohne Angabe des Passwortes wieder einhängen zu können:
sshfs pi@<ip-adresse>:/home/pi ~/raspberry/pi_1
Ich muss wohl kaum erwähnen, dass nun auch bequem über den Dateimanager auf die Files des „remote-Raspies“ zugegriffen werden kann.
Und als kleines Schmankerl kommt nachfolgend noch ein Bash-Script, welches erlaubt, auf einen Rutsch gleich mehrere Raspies zu mounten:

#!/bin/bash

piIpBase=192.168.10.
piIpList="1 2 5"

for piName in $piIpList; do
    ping -c 1 -q $piIpBase$piName
    echo "ping-result: $?"
    if [ $? -eq 0 ]; then
        echo "$piIpBase$piName available - try to mount it."
        sshfs pi@$piIpBase$piName:/home/pi ~/raspberry/pi$piName/
    else
        echo "$piIpBase$piName NOT available!"
    fi
done

Obigen Text einfach in eine Datei speichern (z.B. mount_pi.sh) und nicht vergessen, diese dann ausführbar zu machen:
chmod +x mount_pi.sh
So lassen sich über den Aufruf von mount_pi.sh gleich mehrere (in obigem Fall: drei) RaspberryPies auf einen Rutsch in sein lokales File-System einhängen – vorausgesetzt man hat nicht vergessen die Mount-Verzeichnisse dafür anzulegen.

Auf der Github-Hilfeseite ist auch noch gut beschrieben, wie man sich einen SSH-Key erzeugen kann.