Product SiteDocumentation Site

Kapitel 9. Unix-Dienste

9.1. Systemstart
9.1.1. Das systemd Initialisierungssystem
9.1.2. Das System V Initialisierungssystem
9.2. Remoteanmeldung
9.2.1. Sicheres Remoteanmelden: SSH
9.2.2. Entfernte grafische Arbeitsflächen benutzen
9.3. Berechtigungen verwalten
9.4. Administrations-Schnittstellen
9.4.1. Über eine Webschnittstelle administrieren: webmin
9.4.2. Pakete konfigurieren: debconf
9.5. syslog Systemereignisse
9.5.1. Prinzip und Mechanismus
9.5.2. Die Konfigurationsdatei
9.6. Der Superserver inetd
9.7. Aufgaben mit cron und atd zeitlich festlegen
9.7.1. Aufbau der Datei crontab
9.7.2. Verwendung des Befehls at
9.8. Asynchrone Aufgaben planen: anacron
9.9. Quotas
9.10. Datensicherung
9.10.1. Datensicherung mit rsync
9.10.2. Rechner ohne Sicherheitskopien wiederherstellen
9.11. Wechsel im laufenden Betrieb: hotplug
9.11.1. Einführung
9.11.2. Das Namensproblem
9.11.3. Wie udev funktioniert
9.11.4. Ein konkretes Beispiel
9.12. Modernes Energiemanagement: Advanced Configuration and Power Interface (ACPI)
Dieses Kapitel behandelt eine Reihe grundlegender Dienste, die vielen Unix-Systemen gemein sind. Alle Administratoren sollten mit ihnen vertraut sein.

9.1. Systemstart

Beim Hochfahren des Rechners zeigen die zahlreichen Meldungen, die auf der Konsole vorüberrollen, viele selbsttätig ausgeführte Initialisierungen und Konfigurationen an. Manchmal möchten Sie vielleicht den Ablauf dieser Phase etwas verändern, weshalb Sie sie gut verstehen müssen. Das ist der Zweck dieses Abschnitts.
Zunächst übernimmt das BIOS die Kontrolle über den Rechner, erkennt die Festplatten, lädt den Master Boot Record und führt den Boot-Loader aus. Der Boot-Loader übernimmt, ermittelt den Kernel auf der Festplatte, lädt ihn und führt ihn aus. Der Kernel wird dann initialisiert und beginnt damit, nach der Partition, die das Wurzel-Dateisystem enthält, zu suchen und sie einzuhängen, und führt schließlich das erste Programm aus – init. In vielen Fällen befinden sich diese „Wurzel-Partition“ und der init-Befehl jedoch in einem virtuellen Dateisystem, das nur im Arbeitsspeicher existiert (daher sein Name „initramfs“, früher „initrd“ genannt für „initialization RAM disk“). Dieses Dateisystem wird vom Boot-Loader in den Speicher geladen, häufig aus einer Datei auf einer Festplatte oder aus dem Netzwerk. Es enthält das absolute Minimum dessen, was vom Kernel benötigt wird, um das „wirkliche“ Wurzel-Dateisystem zu laden: dies können Treiber-Module für die Festplatte oder andere Geräte sein, ohne die das System nicht hochfahren kann, oder häufiger Initialisierungsskripten und -module zum Aufbau von RAID-Arrays, zum Öffnen verschlüsselter Partitionen, zur Aktivierung von LVM-Volumes usw. Sobald die Wurzel-Partition eingehängt ist, übergibt initramfs die Kontrolle an das wirkliche init, und der Rechner kehrt zum Standard-Startprozess zurück.
Boot-Sequenz eines Rechners, auf dem Linux mit systemd läuft

Abbildung 9.1. Boot-Sequenz eines Rechners, auf dem Linux mit systemd läuft

9.1.1. Das systemd Initialisierungssystem

Das "tatsächliche init" wird zur Zeit von systemd bereitgestellt und dieser Abschnitt beschreibt das Init-System.
Systemd führt mehrere Prozesse aus, die für die Einrichtung des Systems verantwortlich sind: Tastatur, Treiber, Dateisysteme, Netzwerk, Dienste. Dabei behält er den Überblick über das Gesamtsystem und die Anforderungen der Komponenten. Jede Komponente wird durch eine "Unit-Datei" (manchmal auch mehrere) beschrieben; die allgemeine Syntax ergibt sich aus der weit verbreiteten "*.ini Dateien" Syntax, mit key = value Paare gruppiert zwischen [section] headers. Unit-Dateien werden unter /lib/system/system/ und /etc/systemd/system/ gespeichert; es gibt sie in verschiedenen Varianten, aber wir werden uns hier auf "services" und "targets" konzentrieren.
Eine systemd "Servicedatei" beschreibt einen von systemd verwalteten Prozess. Es enthält ungefähr die gleichen Informationen wie die alten Initskripte, jedoch in einer deklaratorischen (und viel prägnanteren) Form. Systemd übernimmt den Großteil der sich wiederholenden Aufgaben (Starten und Stoppen des Prozesses, Prüfen seines Status, Protokollieren, Löschen von Berechtigungen, usw.) und die Servicedatei muss nur die Besonderheiten des Prozesses ausfüllen. Hier ist zum Beispiel die Servicedatei für SSH:
[Unit]
Description=OpenBSD Secure Shell server
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target
Alias=sshd.service
Wie Sie sehen können, gibt es dort sehr wenig Code, nur Deklarationen. Systemd kümmert sich um die Anzeige von Fortschrittsberichten, verfolgt die Prozesse und startet sie bei Bedarf sogar neu.
Eine systemd "Target-Datei" beschreibt einen Zustand des Systems, in dem ein Satz von Diensten als funktionsfähig bekannt ist. Es kann als Äquivalent zum alten Runlevel angesehen werden. Eines der Targets ist local-fs.target; wenn es erreicht ist, kann der Rest des Systems davon ausgehen, dass alle lokalen Dateisysteme eingebunden und zugänglich sind. Andere Targets sind network-online.target und sound.target. Die Abhängigkeiten eines Ziels können entweder innerhalb der Zieldatei (in der Zeile Requires=) oder über einen symbolischen Link auf eine Servicedatei im Verzeichnis /lib/systemd/system/Targetname.target.wants/ aufgelistet werden. Zum Beispiel enthält /etc/systemd/system/printer.target.wants/ einen Link zu /lib/systemd/system/cups.service; systemd wird daher sicherstellen, dass CUPS läuft, um printer.target zu erreichen.
Da Unit-Dateien, anders als als Skripte oder Programme, eher deklarativ sind, können sie nicht direkt ausgeführt werden und werden von systemd nur interpretiert. Mehrere Dienstprogramme erlauben es dem Administrator daher, mit systemd zu interagieren und den Zustand des Systems und jeder Komponente zu kontrollieren.
Das erste derartige Dienstprogramm ist systemctl. Wenn es ohne Argumente ausgeführt wird, listet es alle dem System bekannten Unit-Dateien (mit Ausnahme derjenigen, die deaktiviert wurden) sowie deren Status auf. systemctl status gibt einen besseren Überblick über die Dienste und die damit verbundenen Prozesse. Wenn der Name eines Dienstes angegeben wird (wie in systemctl status ntp.service), gibt er noch mehr Details zurück, sowie die letzten Log-Zeilen, die sich auf den Dienst beziehen (mehr dazu später).
Das Starten eines Dienstes von Hand ist einfach das Starten von systemctl start servicename.service. Wie man leicht erraten kann, wird der Dienst mit systemctl stop servicename.service beendet; andere Unterbefehle beinhalten reload und restart.
Um zu steuern, ob ein Dienst aktiv ist (d.h. ob er beim Booten automatisch gestartet wird), verwenden Sie systemctl enable servicename.service (oder disable). is-enabled ermöglicht die Überprüfung des Status des Dienstes.
Eine interessante Eigenschaft von systemd ist, dass es eine Protokollierungskomponente namens journald enthält. Es ist eine Ergänzung zu herkömmlichen Protokollierungssystemen wie syslogd, aber es fügt interessante Funktionen hinzu, wie eine formale Verbindung zwischen einem Dienst und den von ihm erzeugten Nachrichten und die Fähigkeit, Fehlermeldungen zu erfassen, die durch seine Initialisierungssequenz erzeugt werden. Die Meldungen können später mit Hilfe des Befehls journalctl angezeigt werden. Ohne Argumente spuckt es einfach alle Logmeldungen aus, die seit dem Systemstart aufgetreten sind; es wird selten so verwendet. Meistens wird es mit einer Service-Kennung verwendet:
# journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 10:08:49 CEST, end at Tue 2015-03-31 17:06:02 CEST. --
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Received SIGHUP; restarting.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:32 mirtuel sshd[1151]: Accepted password for roland from 192.168.1.129 port 53394 ssh2
Mar 31 10:09:32 mirtuel sshd[1151]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Ein weiterer nützlicher Kommandozeilenparameter ist -f, der journalctl anweist, neue Nachrichten so anzuzeigen, wie sie ausgegeben werden (ziemlich so wie tail -f file).
Wenn ein Dienst nicht wie erwartet funktioniert, ist der erste Schritt zur Lösung des Problems die Überprüfung, ob der Dienst tatsächlich läuft: systemctl status. Wenn dies nicht der Fall ist und die Meldungen des ersten Befehls nicht ausreichen, um das Problem zu diagnostizieren, überprüfen Sie die von journald über diesen Dienst gesammelten Protokolle. Angenommen, der SSH-Server funktioniert nicht:
# systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
   Active: failed (Result: start-limit) since Tue 2015-03-31 17:30:36 CEST; 1s ago
  Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
  Process: 1188 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=255)
 Main PID: 1188 (code=exited, status=255)

Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
# journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 17:29:27 CEST, end at Tue 2015-03-31 17:30:36 CEST. --
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Received SIGHUP; restarting.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:30:10 mirtuel sshd[1147]: Accepted password for roland from 192.168.1.129 port 38742 ssh2
Mar 31 17:30:10 mirtuel sshd[1147]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Mar 31 17:30:35 mirtuel sshd[1180]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1182]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1184]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1186]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1188]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
# vi /etc/ssh/sshd_config
# systemctl start ssh.service
# systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
   Active: active (running) since Tue 2015-03-31 17:31:09 CEST; 2s ago
  Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
 Main PID: 1222 (sshd)
   CGroup: /system.slice/ssh.service
           └─1222 /usr/sbin/sshd -D
# 
Nachdem wir den Status des Dienstes überprüft haben (failed), haben wir die Protokolle überprüft; sie zeigen einen Fehler in der Konfigurationsdatei an. Nachdem wir die Konfigurationsdatei bearbeitet und den Fehler behoben haben, starten wir den Dienst neu und überprüfen, ob er tatsächlich läuft.

9.1.2. Das System V Initialisierungssystem

Das System V init System (das wir init für Kürze nennen werden) führt mehrere Prozesse aus, indem es Anweisungen aus der Datei /etc/inittab befolgt. Das erste Programm, das ausgeführt wird (was dem Schritt sysinit entspricht), ist /etc/init.d/rcS, ein Skript, das alle Programme im Verzeichnis /etc/rcS.d/ ausführt.
Unter diesen befinden sich nacheinander Programme, die zuständig sind für:
  • das Konfigurieren der Konsolentastatur;
  • das Laden von Treibern: die meisten Kernelmodule werden beim Erkennen der Hardware vom Kernel selbst geladen; zusätzliche Treiber werden selbsttätig geladen, wenn die entsprechenden Module in der Datei /etc/modules aufgeführt sind;
  • die Integritätsprüfung von Dateisystemen;
  • das Einhängen lokaler Partitionen;
  • das Konfigurieren des Netzwerks;
  • das Einhängen von Netzwerkdateisystemen (NFS).
Nach dieser Phase übernimmt init und startet die im Standard-Runlevel (der normalerweise Runlevel 2 ist) aktivierten Programme. Es führt /etc/init.d/rc 2 aus, ein Skript, das alle Dienste startet, die in /etc/rc2.d/ aufgeführt sind und mit dem Buchstaben „S“ beginnen. Die anschließenden zweistelligen Zahlen wurden früher dazu benutzt, die Reihenfolge festzulegen, in der die Dienste gestartet werden mussten, aber heute verwendet das Standard-Bootsystem insserv, das ausgehend von den Abhängigkeiten der Skripten alles selbsttätig zeitlich festlegt. Jedes Boot-Skript legt die Bedingungen fest, die gelten müssen, damit ein Dienst gestartet oder beendet wird (ob er zum Beispiel vor oder nach einem anderen Dienst gestartet werden muss); init startet sie dann in der Reihenfolge, die diese Bedingungen erfüllt. Die feststehende Nummerierung der Skripten wird daher nicht mehr berücksichtigt (sie müssen trotzdem weiterhin einen Namen haben, der mit „S“ beginnt gefolgt von zwei Zahlen und dem Namen des Skripts, das für die Abhängigkeiten verwendet wird). Im Allgemeinen werden grundlegende Dienste (wie das Protokollieren mit rsyslog oder die Portzuweisung mit portmap) als erste gestartet, gefolgt von Standarddiensten und der grafischen Schnittstelle (gdm3).
Dieses Bootsystem auf der Grundlage von Abhängigkeiten ermöglicht es, die Neu-Nummerierung zu automatisieren, die recht mühsam wäre, wenn sie von Hand erledigt werden müsste, und es begrenzt das Risiko menschlichen Versagens, da die Festlegung der zeitlichen Abfolge in Übereinstimmung mit den angegebenen Parametern erfolgt. Ein weiterer Vorteil besteht darin, dass voneinander unabhängige Dienste zeitgleich gestartet werden können, was den Prozess des Hochfahrens beschleunigt.
init unterscheidet zwischen verschiedenen Runleveln, so dass es mit dem Befehl telinit neuer-level von einem zum anderen umschalten kann. init führt bei einem neuen Runlevel unmittelbar ein weiteres Mal /etc/init.d/rc aus. Dieses Skript startet dann die fehlenden Dienste und beendet die nicht mehr benötigten. Hierzu bezieht es sich auf den Inhalt der Datei /etc/rcX.d (wobei X den neuen Runlevel bezeichnet). Skripten, deren Namen mit „S“ beginnen (wie in „Start“), verweisen auf zu startende Dienste, solche mit „K“ (wie in „Kill“) auf zu beendende. Das Skript startet keine Dienste, die im vorherigen Runlevel bereits aktiv waren.
Standardmäßig verwendet System V init in Debian vier verschiedene Runlevel:
  • Level 0 wird nur vorübergehend beim Herunterfahren des Rechners benutzt. Daher enthält er nur zahlreiche „K“-Skripten.
  • Level 1, auch Single-User Modus genannt, entspricht dem System in rudimentärem Zustand. Er umfasst einzig grundlegende Dienste und ist hauptsächlich für die Systemwartung gedacht, bei dem Interaktionen mit normalen Benutzern nicht erwünscht sind.
  • Level 2 ist der Level für den Normalbetrieb, der Netzwerkdienste, eine grafische Schnittstelle, Benutzeranmeldungen usw. umfasst.
  • Level 6 gleicht Level 0, nur dass er während des Herunterfahrens vor einem Neustart verwendet wird.
Es gibt weitere Level, insbesondere 3 bis 5. Standardmäßig sind sie so konfiguriert, dass sie sich wie Level 2 verhalten. Jedoch kann der Administrator sie verändern (indem er in den entsprechenden Verzeichnissen unter /etc/rcX.d Skripten hinzufügt oder löscht), um sie so besonderen Bedürfnissen anzupassen.
Boot-Sequenz eines Rechners, auf dem Linux mit System V init läuft

Abbildung 9.2. Boot-Sequenz eines Rechners, auf dem Linux mit System V init läuft

Alle in den verschiedenen Verzeichnissen unter /etc/rcX.d enthaltenen Skripten sind in Wirklichkeit symbolische Verknüpfungen - bei der Paketinstallation durch das Programm update-rc.d erstellt, die auf die eigentlichen, im Verzeichnis /etc/init.d/ gespeicherten, Skripten verweisen. Der Administrator kann die in jedem Runlevel verfügbaren Dienste fein einstellen, indem er den Befehl update-rc.d mit angepassten Parametern erneut ausführt. Die Handbuchseite update-rc.d(1) erläutert die Syntax im Detail. Bitte beachten Sie, dass das Entfernen aller symbolischen Verknüpfungen (mit dem Parameter remove) kein gutes Verfahren zum Abschalten eines Dienstes ist. Stattdessen sollten Sie ihn einfach so konfigurieren, dass er in dem gewünschten Runlevel nicht startet (und dabei gleichzeitig die entsprechenden Aufrufe zu seinem Abschalten bewahren, für den Fall, dass er im vorhergehenden Runlevel läuft). Da update-rc.d eine etwas verschachtelte Schnittstelle hat, benutzen Sie vielleicht lieber rcconf (aus dem Paket rcconf), das eine benutzerfreundlichere Schnittstelle hat.
Schließlich startet init Steuerprogramme für mehrere virtuelle Konsolen (getty). Es zeigt eine Eingabeaufforderung an, an der es auf einen Benutzernamen wartet, und führt dann login benutzer aus, um eine Sitzung zu starten.