Raspberry Pi: Autostart von Programmen einrichten
Auf dem Raspberry Pi kommt häufig Raspbian und folglich Debian Linux zum Einsatz. Bei den Zahlreichen Tutorials, die ich bereits über den kleinen Computer schrieb, kam häufiger die Frage auf, sofern ich es nicht beschrieb, wie man ein bestimmtes Programm in den Autostart packt. Hierfür gibt es mehrere Möglichkeiten. Da sich diese Frage auch bei einem beliebigen Programm, bei dem ich nicht in einem separaten Artikel die genaue Vorgehensweise beschrieb, stellen kann, werde ich im Folgenden beschreiben wie man allgemein Programme in Debian (auf dem Raspberry Pi) automatisch mit dem Boot des Gerätes starten lassen kann.
Voraussetzung: Raspbian oder vergleichbare Distribution installiert
Das Starten eines Programms als sogenannter Dienst über ein Runlevel ist die saubere Lösung. Hierzu legt man ein Start-/Stop-Script im Verzeichnis /etc/init.d/ an, in dem Methoden wie start, stop, restart oder auch status definiert werden. Der Vorteil liegt drain, dass diese Vorgehensweise übersichtlich ist, man das Script auch nach dem Start des Raspberry Pis benutzen und damit die Instanz des Programms entsprechend steuern kann.
Zunächst benötigen wir ein Start-/Stop-Script. Für viele Programme gibt es seitens der Entwickler bereits ein solches, das bei Paketen meist automatisch im Ordner /etc/init.d/ angelegt wird oder, falls manuell installiert, sich in der Dokumentation des Projektes befindet. Gibt es ein solches Script noch nicht, muss man dieses selbst schreiben.
Dazu legen wir eine Datei mit unserem Wunschnamen im Verzeichnis /etc/init.d/ an. Im Beispiel nenne ich das Script skeleton, dessen Startscript ich als Vorlage nehme. Jedes Startscript beginnt mit dem Shebang, der definiert in welcher Sprache es geschrieben wurde. Darauf folgt ein Kopfteil als Kommentar in dem angegeben werden sollte für welches Programm das Script ist (Provides), mögliche Abhängigkeiten (Required-Start, Required-Stop), das Runlevel (Default-Start, Default-Stop; Voreinstellung sollte im Normalfall passend sein) wie auch eine kurze (Short-Description) und eine lange Beschreibung (Description) über die Funktionalität des Scripts. Daraufhin folgen die Aktionen in einer sogenannten switch-case-Anweisung. Hier sind # START, # STOP, # RESTART ggf. usw. durch die entsprechenden Kommandos zu ersetzen, die das Programm starten, stoppen bzw. neustarten.
In dem Editor nano kann man mittels STRG + X, Y und Enter speichern.
sudo nano /etc/init.d/skeleton
#!/bin/sh ### BEGIN INIT INFO # Provides: Für welches Programm ist das Script? # Required-Start: # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Kurze Beschreibung # Description: Längere Beschreibung ### END INIT INFO # Actions case "$1" in start) # START ;; stop) # STOP ;; restart) # RESTART ;; esac exit 0
Nun müssen wir der Datei noch die Rechte zum Ausführen zuweisen. Dies können wir mit folgendem Befehl machen (skeleton durch Name der Datei ersetzen).
sudo chmod +x /etc/init.d/skeleton
Jetzt können wir update-rc.d anweisen das Start-/Stop-Script automatisch in den zuvor definierten Runlevels zu starten und damit auch beim Systemstart.
sudo update-rc.d skeleton defaults
Falls wir im laufenden Betrieb das Start-/Stop-Script manuell verwenden möchten, müssen wir das Script gefolgt von dem entsprechenden Funktionsnamen ausführen. Für das Beispielscript ergäben sich folgende Möglichkeiten.
sudo /etc/init.d/skeleton start
sudo /etc/init.d/skeleton stop
sudo /etc/init.d/skeleton restart
Wenn kein Start-/Stop-Script für die verwendete Software existiert, und dieses nicht unbedingt geschrieben werden soll, kann man auch rc.local verwenden. Diese Datei wird zuletzt im Runlevel-System ausgeführt. Das bietet den Vorteil, dass abhängige Anwendungen (bspw. Webserver), die ein Start-/Stop-Script besitzen, bereits mit Gewissheit ausgeführt sind und somit die in rc.local eingetragenen Anwendungen problemlos starten.
Wir müssen die Datei rc.local mit einem Editor bearbeiten und an deren Ende, jedoch vor exit 0, in der Reihenfolge in der die Anwendungen gestartet werden sollen, deren Startbefehle eintragen. Dabei sollte man mittels su definieren unter welchem Benutzer der Befehl ausgeführt werden soll. Im Beispiel soll der Startbefehl, der über den Parameter -c übergeben wird, von Seafile unter dem Benutzer seafile ausgeführt werden.
sudo nano /etc/rc.local
su seafile -c '/home/seafile/seafile-server-latest/seafile.sh start && /home/seafile/seafile-server-latest/seahub.sh start 8000'
am Ende der Datei jedoch vor folgender Zeile einfügen
exit 0
Der Dienst Cron lässt ein Script zu einer definierten Zeit automatisch ausführen. In unserem Fall lassen wir beim Start des Raspberry Pis (@reboot geschrieben) das gewünschte Script durchstarten. Hier empfiehlt es sich häufig das Programm screen zu verwenden, welches den ausgeführten Prozess laufenlassen kann, auch wenn man nicht mehr eingeloggt ist bzw. in unserem Fall der Aufruf durch Cron eigentlich schon beendet ist. Bei dieser Methode werden, im Gegensatz zum rc.local, nicht (unbedingt) auf Abhängigkeiten aus dem Runlevel-System gewartet.
Mittels folgendem Befehl können wir die Cron Datei des Benutzers (mittels sudo vom User root; auch Crontab genannt) abändern. Dort tragen wir am Ende der Datei in eine neue Zeile zunächst den Zeitpunkt und dann den Befehl zum Starten ein. Im Beispiel starten wir das Programm unter /usr/bin/test
sudo crontab -e
@reboot /usr/bin/test
Falls das Programm nach dem Aufruf nicht als Daemon weiterlaufen sollte, kann man die Instanz in eine Instanz von screen legen. Dabei sollte man der screen-Instanz einen eindeutigen Namen geben.
@reboot screen -dmS NameOfScreenSession /usr/bin/test
Damit die Variante mit screen funktioniert, muss dieses Programm installiert sein. Wenn dem noch nicht der Fall sein sollte, kann man es über den Paketmanager APT mittels folgenden Befehls installieren.
sudo apt-get install screen
So einfach ist es, in Debian Linux ein Programm automatisch zu starten. Dank der Parameter für update-rc.d oder in vereinfachter Form mit der Stelle an der rc.local ausgeführt wird, ist es auch möglich die Programme unter bestimmten Voraussetzungen zu starten und dabei Probleme durch Abhängigkeiten zu verhindern.
Dieses Tutorial wurde am 22. Februar 2015 überarbeitet.
32 Kommentare. Hinterlasse eine Antwort
Hallo Jan,
hatte mich bereits mal an der Geschichte mit dem Cronjob versucht und war gescheitert. Umso erfreulicher, deinen Artikel mit einer weiteren Methode hier zu lesen. Leider habe ich es nicht hinbekommen, meine Programmierkenntnisse sind dann doch ehr begrenzt. In Variante 1 habe ich in der skeleton Datei (bzw. einer Kopie davon) einfach „start /home/seafile/seafile-server-3.0.4/seafile.sh start“ geschrieben, scheint aber nicht zu reichen und das ganze in der update-rc.d wie beschrieben registriert, kein Webinterface da nach Reboot 🙁 Dann bin ich wieder bei Methode 2 gelandet 🙂 und habe im crontab die Zeile „@reboot screen -dmS NameOfScreenSession /home/seafile/seafile-server-3.0.4/seafile.sh start“ ergänzt und das screen nachinstalliert. Hat auch nicht gefunzt, kannst du mir weiterhelfen? LG, Stefan
Schau dir das mal die Umsetzung im Seafile Tutorial an. Neben dem Dienst seafile muss auch seahub laufen, damit das Webinterface erreichbar ist. Nebenbei bemerkt: Hier brauchst du kein screen.
Hallo Jan, es läuft! Das Seafile Tutorial hats gebracht, vielen Dank! LG, Stefan
Geht auch super über die /etc/rc.local , hierbei muss dann nicht auf Abhängigkeiten gewartet werden.
Stimmt. Werde ich als dritte Möglichkeit bei Gelegenheit noch hinzufügen 🙂
[…] Link zum Artikel stuffaboutcode Link zum Artikel Jan Karres […]
Hallo Jan, habe für folgendes keine Erklärung, Du vielleicht ?
Wenn ich folgendes script manuell aufrufe, bin ich bei einer CPU-Last von kleiner 0,7% bezüglich dem script:
count=0
while :
do
#echo „$count“
echo „$count“ > /home/logdir/impulszaehler.log
gpio -g wfi 22 rising
#sleep 1
(( count++ ))
done
Wenn ich dieses aber über die hier genannte Methode 1 oder aber über meine bisher preferierte Methode über die /etc/inittab aufrufe, dann habe ich eine CPU Last bezüglich des scripts von größer 26% ! Keine Ahnung warum…VG, André
aus top:
8549 root 20 0 4824 1280 1112 S 0,3 0,3 0:00.06 impuls.sh
8883 root 20 0 2768 1184 1000 R 27,1 0,3 0:03.14 impuls.sh
Die Last verringert sich, wenn ich in der initab das script als normaler Benutzer starten lasse:
8:23:once:su user -c „/home/bin/impuls.sh &“
immer noch keine Ahnung warum, aber so passt’s für mich…
Wo ist den dort die while loop condition?
„You can also create an infinite loop by putting a colon as the condition:“
http://linux.about.com/od/Bash_Scripting_Solutions/a/How-To-Write-Bash-While-Loops.htm oder http://stackoverflow.com/questions/16489809/emulating-do-while-loop-in-bash
VG, André (die Frage hat sich eigentlich auch erledigt, zumindest konnte ich, wie weiter oben beschrieben, für dieses Problem einen workaround finden)
Hallo Jan, was macht denn das Screen Programm und hat es irgendwelche Nachteile im Hinsicht auf z.B. CPU Last oder Speicher?
Ich erlaube mir aus er deutschen Debian Package description zu zitieren: „GNU Screen ist ein Terminalmultiplexer, der mehrere separate »Bildschirme« auf einem einzelnen, physischen, zeichenbasierten Terminal darstellt.“
In dem Fall wird es dazu genutzt, dass das Programm weiter läuft, auch nach dem einmaligen Aufruf. Auf CPU/RAM sollte sich das kaum niederschlagen.
Danke Jan!
Eine Frage hierzu hätte ich noch und das „man screen“ hat bestimmt die Lösung, doch ich finde sie einfach nicht.
Ich habe ein Python Prozess am laufen, dem ich eine Screen zugeordnet habe. Den Prozess beende ich mit „killall python“. Wenn ich aber danach ein neues Python Script aufrufe und wieder mit einer Screen, dann wird mir der Python Prozess nicht angezeigt (ist ein Bildbetrachter) aber bei screen -list wird die screen aufgeführt. Muss ich die speziell in den Vordergrund bringen?
Das sollte nicht an screen, sondern an dem Python Script legen, wie es mir klingt.
Sehe ich das richtig, dass man in einer der beschriebenen Weisen ein Regelungsprogramm (Abfrage verschiedener Sensoren, Betätigung einiger Aktoren) dauerhaft laufen lassen könnte, das sich dann beispielsweise nach Stromausfall wieder in Gang setzt?
Vollkommen korrekt.
Hallo Jan,
evtl. könntest du das Tutorial noch etwas ausbauen. Ein Beispiel für die Methode 1 wäre nett. Ich kam über Google auf deinen Blog und hatte eigentlich ein „Muster“-Script erwartet. Vllt. mit Pfadangaben und Argumenten. Das ist für Einsteiger schneller verständlich als das kurze Beispiel oben 😉
Ein Muster Script ist oben vorhanden. Konkrete programmspezifische Anweisungen machen jedoch wenig Sinn, da dies von Anwendung zu Anwendung sehr verschieden sein kann.
[…] https://jankarres.de/2014/07/raspberry-pi-autostart-von-programmen-einrichten/ […]
Hallo Jan,
danke für deine tollen Anleitungen, die haben mir schon viel geholfen.
Ich möchte den RPi gern autonom mit einem UMTS-Stick betreiben. Wenn Strom da ist, soll er Daten aufnehmen und verschicken, solange, bis die Stromversorgung wieder weg ist. Den UMTS-Stick (TP-Link MA260) konnte ich anbinden, der RPi ist online. Dazu führe ich die unten stehenden Befehle aus.
Die wollte ich jetzt gern in die rc.local schreiben – aber nach einem reboot war der Stick nicht im online-Modus und entsprechend konnte auch keine online-Verbindung hergestellt werden.
Die zwei Schritte:
sudo usb_modeswitch -v 2357 -p f000 -V 2357 -P 9000 -W -I -n -M ‚555342431….‘ -2 ‚555342431…‘
Wenn lsusb dann für den Stick den online-Modus anzeigt (Bus 001 Device 00x: ID 2357:9000 dann:
sudo wvdial umts
wobei umts die Verbindungskonfiguration enthält…
Kann man die zwei Befehle direkt so in die rc.local schreiben? Oder was mache ich falsch?
Danke schon mal,
Johannes
Das kannst du direkt so in due rc.local schreiben. Das if-Statement musst du dort in Bash schreiben.
Hallo Jan,
ich beginne gerade, mit dem RPi umzugehen. Ich habe in crontab versucht, beim Neustart des RPi eine LED zum Blinken zu bekommen (Blinker.py). Das hat funktioniert, ich habe dann die entsprechende Zeile über „sudo crontab -e“ wieder gelöscht. Leider wird Blinker.py dennoch nach dem Neustart ausgeführt und ich finde keine Möglichkeit, das abzustellen. Ich müßte immer killall eingeben. Somit ist mein „GPIO Pin 18“ immer auf Blinkmoudus. Auch deine oben angeführten Methoden haben mich zur Lösung gebracht. Ich finde den Entrag nirgends, der Blinker.py automatsch ausführen läßt. Gerne würde ich Deine Hilfe in Ansruch nehmen. Danke. Makus
Hallo Jan
Ich habe ein Problem mit crontab.Ich möchte ganz einfach Steckdosen schalten.Dazu habe ich ein Script in Python geschrieben.Diese Script funktioniert einwndfrei.Wenn ich es mit crontab starten will geht gar nichts.
Mein Befehl lautet für einen Test 2 * * * * /etc/init.d/Steckdosen/Schalte.py
Was ist falsch?Es würde mich freuen wenn du mir helfen könntest.
absolut Top Anleitung. Endlich kenne ich die ganzen zusammenhänge. Vielen Dank!!!!!
muss es nicht ;:
sudo nano /etc/init.d/rc.local
sein?
Hallo
Danke für den super Artikel!
Ich habe das Script so erstellt wie in Methode 1, und wenn ich es mit /etc/init.d/script start starte macht es auch alles was es soll. (Kleines C Programm das Daten vom Seriellen Port verarbeitet)
Aber wenn ich reboote, startet das script zwar anscheinend das Programm ( laut $ps axg) aber es macht nichts. Sobald ich aber dann wieder /etc/init.d/script start aufrufe, läuft das Programm doppelt ?!
Zufällig eine Idee?
Danke!
Hi Jan,
Vielen Dank für die vielen verschiedenen guten Anleitungen!
Ich habe nach mehreren Wochen Recherche ein für Laien nicht lösbares Problem:
Ich möchte (am besten über einen cronjob) folgenden Befehl:
cd home/pi/GoogleDrive ; ./grive
automatisch ausführen lassen, und scheitere daran, ihn in eine Schreibweise umzuformulieren die Cronjob tauglich ist. Die Zeile kann ich so wie sie ist ins Terminal eingeben und mein grive wird gesynched.
Irgendwelche Ideen?
Liebe Grüße Jakob
[…] und wie ich finde bessere, Option ist das Schreiben eines Startskriptes wie es auf der Seite jankarres.de beschrieben ist. Dabei ist es nicht zwingend notwendig, dass das Skript alle Aktionen wie Start, […]
[…] https://jankarres.de/2014/07/raspberry-pi-autostart-von-programmen-einrichten/ […]
[…] Raspberry Pi: Autostart von Programmen einrichten […]
[…] Info Autostart: Raspberry Pi: Autostart von Programmen einrichten › Jan Karres […]