HOWTO: Programme automatisch starten und stoppen mit chkconfig

Autor: Marc Nause

Vor allem wenn man einen Computer als Server laufen lässt, möchte man, dass bestimmte Programme beim Hochfahren des Systems gestartet und beim Herunterfahren automatisch wieder beendet werden. Unter Linux ist dies mit chkconfig leicht möglich. Notwendig hierzu ist jedoch für jedes Programm ein kleines Skript, das die Befehle zum Starten und Beenden enthält. Nicht notwendig, aber sehr praktisch, sind Routinen zum Neustarten oder zur Anzeige des Status des Programms. Zahlreiche Programme bringen so ein Skript bereits mit. Wenn dies nicht der Fall ist, muss man selbst Hand anlegen, was aber nicht besonders schwierig ist.

Das Skript beginnt mit einem Header, der zumindest die folgenden Angaben beinhalten sollte:

#!/bin/sh 
# chkconfig: 2345 65 35
# description: Hier kann ein Text stehen
Die erste Zeile sollte klar sein. In der zweiten Zeile werden gleich mehrere Dinge festgelegt. Der erste Zahlenblock (2345) gibt an, innerhalb welcher Runlevels das Programm laufen soll, hier also in den Runlevels 2 bis 5. Die zweite Zahl (65) gibt die Startpriorität, die dritte Zahl (35) die Stoppriorität des Programms beim Hoch- bzw. Herunterfahren an. Dabei gilt, dass je höher die Zahl, desto später wird gestartet bzw. gestoppt. Die Zahl muss sich zwischen 1 und 99 bewegen, wobei zu beachten ist, dass manche Programme eventuell auf andere angewiesen sind, die daher zuvor gestartet werden müssen.

Die dritte Zeile enthält eine Beschreibung des Programms, die unter anderem bei der Administration eines Computers mittels Webmin angezeigt wird. Je aussagekräftiger dieser Text ist, desto dankbarer wird diejenige Person sein, die sich später mit der Administration abquälen muss. Die Beschreibung kann auch länger als eine Zeile sein. Dazu muss an das Ende der zu verlängernden Zeile ein Backslash gehängt werden. Die Leerzeichen vor dem fortgeführten Text werden ignoriert.
# description: Hier kann ein Text stehen \
#              und hier geht er weiter!
Im Header lassen sich noch weitere Informationen unterbringen. Zu beachten ist nur, dass die Zeile mit einer Raute beginnt und nicht mit Schlüsselworten für chkconfig kollidiert.

Nun geht es endlich richtig los. Das Skript soll ja nicht nur das Programm starten, sondern auch stoppen und sonst noch ein paar Dinge machen können. Hierzu muss ein Argument übergeben werden, das dem Skript sagt, was es denn tun soll. Es soll sich also zum Beispiel mit beispielname start aufrufen lassen und daraufhin das Programm auch starten. Hierzu dient folgenden Zeile:
case "$1" in
Nun folgen die einzelnen Abschnitte die das Programm zu starten, stoppen, neu starten oder den Status ausgeben.
  start)
	echo "Programm wird gestartet."
	programm
	echo    
	;;
An der Stelle von programm muss selbstverständlich der Aufruf des zu startenden Programms stehen. Es ist darauf zu achten, dass das Programm vom System auch gefunden wird. Möglicherweise muss der komplette absolute Pfad zum Programm angegeben werden. Außerdem wird das Programm beim Systemstart mit Rootrechten gestartet. Das ist unter Umständen nicht gewollt, kann aber verhindert werden:
	sudo -u low012 programm
Dieser Befehl startet das Programm programm mit den Rechten des Benutzers low012.

Nun folgt der Programmteil, der das Programm auch wieder beendet:
  stop)
	echo "Programm wird gestoppt."
	kill -15 $(ps ax|grep "programm"|grep -v grep|cut -d" " -f2)
	echo
	;;
Das Wort programm muss wieder ersetzt werden. Hier wird nun die Prozessnummer des Programms gesucht und dieses dann mittels kill -15 aufgefordert, sich zu beenden. Das Argument -f2 bezeichent die Spalte der Ausgabe von ps ax, in der sich die IDs der einzelnen Prozesse befindet. Das Format kann sich von System zu System unterscheiden. Werden die IDs in der ersten Spalte angezeigt, müsste das Argument daher durch -f1 ersetzt werden.

Um das Programm zu beenden und gleich danach wieder zu starten, weil etwa die Konfigurationsdatei geändert wurde, muss einfach nur stop und danach wieder start aufgerufen werden. Dies geschieht durch den folgenden Code:
  restart)
	$0 stop
	$0 start
	;;
Der Höhepunkt des Komforts ist der nun folgende Teil, der anzeigt, ob das Programm zur Zeit der Statusabfrage läuft oder nicht.
  status)
	pids=`ps ax|grep "programm"|grep -v grep|cut -d" " -f2`
	if test "$pids"
	then
		for p in $pids
		do
			echo "Das Programm laeuft als Prozess $pids"
		done
	else
		echo "Das Programm ist gestoppt."
	fi
	;;
Wie gewohnt ist programm zu ersetzen. Es wird wie in start die Prozessnummer des Programms rausgesucht. Dann werden alle gefundenen Prozessnummern unter denen das Programm läuft, es kann ja auch mehrmals gestartet worden sein, ausgegeben.

Nun sollte noch der Fall abgefangen werden, dass das Skript ohne oder mit ungültigem Argument aufgerufen wird:
  *)
	echo "So geht das: programm {start|stop|restart|status}"
	exit 1
Es werden einfach alle möglichen Argumente aufgezählt und dann das Skript mit dem Code 1 beendet. Damit ermöglicht man Programmen, die das Skript aufrufen, zu erkennen, dass das Skript nicht ordnungsgemäß aufgerufen wurde und nicht wirklich irgendwas passiert ist.

Wer sich nun über die fehlenden ;; wundert, hat gut aufgepasst, allerdings fehlen sie hier, da nun der Abschluss der Fallunterscheidung kommt:
esac
Damit ist das Skript fast vollständig. Nun noch der Befehl um anzuzeigen, dass das Skript augeführt wurde und es zu beenden:
exit 0
Nun haben wir ein tolles Skript, aber es muss noch dafür gesorgt werden, dass es auch bei jedem Systemstart bzw. Systemstop mit dem passenden Argument aufgerufen wird. Dazu muss das Skript zunächst unter dem richtigen Namen an die richtige Stelle kopiert werden:
cp beispielskript /etc/rc.d/init.d/programm
Das Skript bekommt also den Namen, unter dem es später auch aufgerufen und angezeigt (z.B. in Webmin, aber auch mittels chkconfig) werden kann. Nun muss dem System noch beigebracht werden, dieses Skript zu beachten:
/sbin/chkconfig --add programm
Wenn das Skript irgendwann nicht mehr benutzt werden soll, kann mit
/sbin/chkconfig --del programm 
die Änderung wieder rückgängig gemacht werden.

Um den Computer jetzt nicht neu starten zu müssen, kann nun der erste Start mittels
/etc/rc.d/init.d/programm start
veranlasst werden. Auf die gleich Weise kann das Programm übrigens auch gestoppt (stop) oder neu gestartet werden (restart). Wie die Statusabfrage funktioniert, sollte nun klar sein.

Alle durch chkconfig verwalteten Programme lassen sich mit chkconfig --list anzeigen.

Benutzer von Webmin können unter System -> Bootup and Shutdown das Skript per Klickibunti bedienen.

Hier zur besseren Übersicht das Skript nochmal in einem Stück:
#!/bin/sh 
# chkconfig: 2345 65 35
# description: Hier kann ein Text stehen

case "$1" in
  start)
	echo "Programm wird gestartet."
	programm
	echo    
	;;
  stop)
	echo "Programm wird gestoppt."
	kill -15 $(ps ax|grep "programm"|grep -v grep|cut -d" " -f2)
	echo
	;;  
  restart)
	$0 stop
	$0 start
	;;  
  status)
	pids=`ps ax|grep "programm"|grep -v grep|cut -d" " -f2`
	if test "$pids"
	then
		for p in $pids
		do
			echo "Das Programm laeuft als Prozess $pids"
		done
	else
		echo "Das Programm ist gestoppt."
	fi
	;;
  *)
	echo "So geht das: programm {start|stop|restart|status}"
	exit 1
esac
exit 0


Anmerkung:
Distributionen, die auf Redhat basieren, fahren die Stop-Links unter /etc/rc.d/rcX.d bei einem reboot oder halt nur an, wenn eine Lock-Datei anzeigt, dass der Prozess wirklich schon laeuft. Daher sollte beim Starten dieses Lock-File mit

touch /var/lock/subsys/<mein_programm>

angelegt

und beim Stoppen entsprechend mit

rm -f /var/lock/subsys/<mein_programm>

entfernt werden.

<mein_programm> muss durch den namen des Stop-/Start-Skriptes ersetzt werden.





Für ihre Anmerkungen und Anregungen danke ich Markus Rosellen und Murat Sariyar.

Fragen, Probleme, Anmerkungen?

marc.nause@audioattack.de