# 4. Server- und Dienstfehler systematisch analysieren



# 4.0 Server- und Dienstfehler systematisch analysieren

Server- und Dienstfehler liegen vor, wenn ein benötigter Dienst nicht startet, unerwartet beendet wird, nicht erreichbar ist oder zwar Verbindungen annimmt, aber fehlerhafte Ergebnisse liefert.

Dieses Kapitel behandelt die systematische Analyse von Diensten und Serveranwendungen unter Windows, Linux und macOS. Dazu gehören unter anderem Webserver, Datenbanken, Datei- und Druckdienste, Anwendungsserver sowie Hintergrunddienste.

> **Grundsatz:**  
> Ein erreichbarer Server ist nicht automatisch ein funktionierender Server. Netzwerkverbindung, Port, Dienstprozess und Anwendungsfunktion müssen getrennt geprüft werden.

---

**Ziele dieses Kapitels**

Nach Abschluss dieses Kapitels sollst du:

- den betroffenen Dienst eindeutig identifizieren können,
- zwischen Netzwerk-, Port-, Dienst- und Anwendungsfehlern unterscheiden können,
- Dienststatus und Startart überprüfen können,
- Prozesse, Abhängigkeiten und verwendete Ports ermitteln können,
- Protokolle verschiedener Betriebssysteme auswerten können,
- Konfigurationsfehler erkennen können,
- Berechtigungs-, Ressourcen- und Zertifikatsprobleme untersuchen können,
- Dienste kontrolliert testen und neu starten können,
- wiederkehrende Dienstabbrüche analysieren können,
- Diagnoseergebnisse nachvollziehbar dokumentieren können.

---

**Sicherheits- und Risikokennzeichnungen**

| Kennzeichnung | Bedeutung |
|---|---|
| `[RO]` | Rein lesender Befehl; verändert normalerweise nichts |
| `[TEST]` | Führt eine aktive Prüfung oder Verbindungsanfrage aus |
| `[PRIV]` | Erfordert möglicherweise Administrator- oder Rootrechte |
| `[FILE]` | Liest eine Datei oder schreibt eine Ausgabe in eine Datei |
| `[SENS]` | Ausgabe kann sensible Informationen enthalten |
| `[CHANGE]` | Verändert Einstellungen, Zustände oder Konfigurationen |
| `[DISRUPT]` | Kann einen Dienst oder laufenden Betrieb unterbrechen |

> Befehle mit `[CHANGE]` oder `[DISRUPT]` dürfen erst nach Prüfung der Auswirkungen und möglichst innerhalb eines abgestimmten Wartungsfensters ausgeführt werden.

---

<details>
<summary><strong>1. Diagnosemodell für Server- und Dienstfehler</strong></summary>

Ein Dienst wird schrittweise von außen nach innen geprüft:

| Ebene | Leitfrage | Typische Prüfung |
|---|---|---|
| 1. Benutzer | Was funktioniert aus Sicht des Benutzers nicht? | Fehlermeldung und Zeitpunkt aufnehmen |
| 2. Client | Ist nur ein Gerät oder Benutzer betroffen? | Vergleich mit anderem Client |
| 3. Namensauflösung | Wird der richtige Servername aufgelöst? | DNS-Abfrage durchführen |
| 4. Netzwerk | Ist der Server erreichbar? | Route und Erreichbarkeit prüfen |
| 5. Transport | Ist der benötigte TCP- oder UDP-Port erreichbar? | Porttest durchführen |
| 6. Betriebssystem | Läuft das Betriebssystem stabil? | Ressourcen und Ereignisse prüfen |
| 7. Dienst | Läuft der benötigte Dienst? | Dienststatus und Prozess prüfen |
| 8. Abhängigkeiten | Funktionieren abhängige Dienste und Systeme? | Datenbank, DNS, Speicher oder Authentifizierung prüfen |
| 9. Konfiguration | Ist der Dienst korrekt konfiguriert? | Konfigurationsdateien und Startparameter prüfen |
| 10. Anwendung | Liefert der Dienst fachlich korrekte Ergebnisse? | Anwendungsspezifischen Funktionstest durchführen |

**Wichtig:** `ping` prüft nicht, ob ein Anwendungsdienst funktioniert. Ein Server kann ICMP-Anfragen beantworten, obwohl beispielsweise der Web-, Datenbank- oder Dateidienst ausgefallen ist.

</details>

---

<details>
<summary><strong>2. Vier grundlegende Dienstzustände unterscheiden</strong></summary>

| Zustand | Beschreibung | Typische Ursache |
|---|---|---|
| Server nicht erreichbar | Bereits die Netzwerkverbindung scheitert | Routing, VLAN, Firewall, Stromversorgung oder Netzwerkkarte |
| Port nicht erreichbar | Server ist erreichbar, aber der Dienstport nicht | Dienst gestoppt, falscher Port oder Firewall |
| Port erreichbar, Anwendung fehlerhaft | Verbindung wird aufgebaut, die Anfrage schlägt jedoch fehl | Konfiguration, Berechtigung, Datenbank oder Anwendung |
| Dienst funktioniert teilweise | Nur bestimmte Benutzer oder Funktionen sind betroffen | Rechte, Mandant, Backend, Datenbestand oder Lastproblem |

Diese Zustände dürfen nicht miteinander verwechselt werden. Die Fehlersuche beginnt immer bei der niedrigsten noch nicht nachgewiesenen Funktionsebene.

</details>

---

<details>
<summary><strong>3. Schnellprüfung unter Windows, Linux und macOS</strong></summary>

Die folgenden Befehle liefern eine erste Übersicht. `<DIENST>` und `<PORT>` müssen durch die tatsächlichen Werte ersetzt werden.

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Rechnername | `[RO] hostname` | `[RO] hostnamectl` | `[RO] scutil --get ComputerName` |
| Systemlaufzeit | `[RO] (Get-CimInstance Win32_OperatingSystem).LastBootUpTime` | `[RO] uptime` | `[RO] uptime` |
| Dienststatus | `[RO] Get-Service -Name "<DIENST>"` | `[RO] systemctl status <DIENST> --no-pager` | `[RO] launchctl print system/<DIENST>` |
| Alle laufenden Dienste | `[RO] Get-Service \| Where-Object Status -eq "Running"` | `[RO] systemctl list-units --type=service --state=running` | `[RO] launchctl list` |
| Prozess suchen | `[RO] Get-Process -Name "<PROZESS>" -ErrorAction SilentlyContinue` | `[RO] pgrep -a <PROZESS>` | `[RO] pgrep -alf <PROZESS>` |
| TCP-Listener anzeigen | `[RO] Get-NetTCPConnection -State Listen` | `[RO][PRIV] sudo ss -lntp` | `[RO][PRIV] sudo lsof -nP -iTCP -sTCP:LISTEN` |
| Bestimmten Port prüfen | `[RO] Get-NetTCPConnection -LocalPort <PORT> -ErrorAction SilentlyContinue` | `[RO][PRIV] sudo ss -lntp "sport = :<PORT>"` | `[RO][PRIV] sudo lsof -nP -iTCP:<PORT> -sTCP:LISTEN` |
| Remote-TCP-Port testen | `[TEST] Test-NetConnection <SERVER> -Port <PORT>` | `[TEST] nc -vz <SERVER> <PORT>` | `[TEST] nc -vz <SERVER> <PORT>` |
| CPU und Arbeitsspeicher | `[RO] Get-Process \| Sort-Object CPU -Descending \| Select-Object -First 10` | `[RO] top` | `[RO] top -o cpu` |
| Freien Speicherplatz prüfen | `[RO] Get-Volume` | `[RO] df -hT` | `[RO] df -h` |

> `launchctl print system/<DIENST>` benötigt das Dienstlabel und nicht zwingend den sichtbaren Namen einer Anwendung. Benutzerbezogene LaunchAgents befinden sich außerdem nicht in der Systemdomäne.

</details>

---

<details>
<summary><strong>4. Reihenfolge der praktischen Fehlersuche</strong></summary>

1. Störung und betroffene Funktion genau beschreiben.
2. Zeitpunkt und Dauer der Störung erfassen.
3. Prüfen, welche Benutzer, Clients und Standorte betroffen sind.
4. Letzte Änderungen und bekannte Wartungsarbeiten ermitteln.
5. Servername und Zielsystem eindeutig bestimmen.
6. DNS-Auflösung und Netzwerkpfad überprüfen.
7. Erreichbarkeit des benötigten Ports testen.
8. Dienststatus, Prozess und Startart kontrollieren.
9. Kontrollieren, auf welcher Adresse und welchem Port der Dienst lauscht.
10. Abhängige Dienste und externe Systeme überprüfen.
11. System- und Anwendungsprotokolle für den Störungszeitraum auswerten.
12. CPU, Arbeitsspeicher, Datenträger und offene Dateien prüfen.
13. Konfiguration, Berechtigungen und Zertifikate kontrollieren.
14. Einen gezielten Funktionstest durchführen.
15. Erst danach eine geeignete Maßnahme planen.
16. Nach der Maßnahme Funktion und Nebenwirkungen überprüfen.
17. Ursache, Maßnahme und Ergebnis dokumentieren.

</details>

---

<details>
<summary><strong>5. Kapitelübersicht</strong></summary>

| Seite | Thema | Inhalt |
|---|---|---|
| **4.0** | Server- und Dienstfehler systematisch analysieren | Kapitelübersicht und Diagnosemodell |
| **4.1** | Störung und betroffenen Dienst eingrenzen | Benutzer, Clients, Standorte und Zeiträume |
| **4.2** | Dienststatus und Startart prüfen | Windows-Dienste, systemd und launchd |
| **4.3** | Prozesse und Prozesszustände analysieren | PID, Elternprozess, Laufzeit und Ressourcen |
| **4.4** | Listener, Ports und Bindungsadressen prüfen | TCP, UDP, IPv4, IPv6 und Loopback |
| **4.5** | Dienstabhängigkeiten untersuchen | Abhängige Dienste, Backends und Startreihenfolge |
| **4.6** | System- und Dienstprotokolle auswerten | Ereignisanzeige, Journal und Unified Logging |
| **4.7** | Dienststartfehler analysieren | Exitcodes, Zeitüberschreitungen und Abstürze |
| **4.8** | Konfigurationsfehler untersuchen | Syntax, Pfade, Parameter und Umgebungsvariablen |
| **4.9** | Benutzer-, Dienstkonto- und Berechtigungsfehler | Konten, Dateirechte und Zugriffstoken |
| **4.10** | Ressourcenengpässe erkennen | CPU, RAM, Datenträger und Dateideskriptoren |
| **4.11** | Speicherplatz- und Dateisystemfehler | Volumes, Inodes, Quotas und schreibgeschützte Dateisysteme |
| **4.12** | Zertifikats- und TLS-Probleme | Gültigkeit, Vertrauenskette, Name und Protokoll |
| **4.13** | Webserver und HTTP-Dienste analysieren | HTTP-Statuscodes, Header, Logs und virtuelle Hosts |
| **4.14** | Datenbankverbindungen analysieren | Port, Anmeldung, Berechtigungen und Verbindungspools |
| **4.15** | Datei- und Freigabedienste analysieren | SMB, NFS, Berechtigungen und Sperren |
| **4.16** | Druckdienste und Warteschlangen analysieren | Spooler, Druckaufträge, Treiber und Erreichbarkeit |
| **4.17** | Wiederkehrende Dienstabbrüche untersuchen | Crash-Loops, Neustartregeln und Ursachenanalyse |
| **4.18** | Dienste kontrolliert neu starten | Risikoanalyse, Abhängigkeiten und Funktionstest |
| **4.19** | Befehlsübersicht – Server- und Dienstdiagnose | Vergleichstabelle für Windows, Linux und macOS |

</details>

---

<details>
<summary><strong>6. Entscheidungsweg bei einem nicht erreichbaren Dienst</strong></summary>

| Prüfschritt | Ergebnis | Nächste Aktion |
|---|---|---|
| Wird der richtige Servername verwendet? | Nein | Zielsystem und Dokumentation korrigieren |
| Wird der Name korrekt aufgelöst? | Nein | DNS-Konfiguration untersuchen |
| Ist der Server über das Netzwerk erreichbar? | Nein | Netzwerkpfad, VLAN, Routing und Firewall prüfen |
| Ist der benötigte Port erreichbar? | Nein | Listener, Dienststatus und Paketfilter prüfen |
| Läuft der Dienstprozess? | Nein | Startfehler und Protokolle untersuchen |
| Lauscht der Prozess auf dem erwarteten Port? | Nein | Bindungsadresse und Konfiguration prüfen |
| Antwortet das Anwendungsprotokoll? | Nein | Dienstprotokoll, TLS und Abhängigkeiten prüfen |
| Funktioniert die Anmeldung? | Nein | Konto, Kennwort, Berechtigungen und Identitätsdienst prüfen |
| Funktioniert die gewünschte Aktion? | Nein | Anwendung, Backend und Datenbestand untersuchen |
| Funktioniert alles wieder? | Ja | Ursache und Lösung dokumentieren |

</details>

---

<details>
<summary><strong>7. Wichtige Informationen vor einem Dienstneustart</strong></summary>

Vor einem Neustart müssen mindestens folgende Fragen beantwortet werden:

- Welche Benutzer und Anwendungen verwenden den Dienst?
- Gibt es laufende Transaktionen oder Dateioperationen?
- Hängen weitere Dienste von diesem Dienst ab?
- Wird der Dienst automatisch wieder gestartet?
- Existiert ein Cluster, Loadbalancer oder Failover-System?
- Gehen durch den Neustart Diagnoseinformationen verloren?
- Wurden die relevanten Protokolle bereits gesichert?
- Ist der Neustart betrieblich freigegeben?
- Wie wird die Funktion anschließend getestet?
- Gibt es eine Rückfallmöglichkeit?

> Ein Neustart kann die Verfügbarkeit kurzfristig wiederherstellen, beseitigt aber nicht automatisch die eigentliche Fehlerursache. Vorher sollten Zustand, Zeitstempel, Fehlermeldungen und relevante Protokolle erfasst werden.

</details>

---

<details>
<summary><strong>8. Mindestdokumentation eines Dienstfehlers</strong></summary>

| Information | Beispiel |
|---|---|
| Betroffener Dienst | Intranet-Webanwendung |
| Server | `srv-web01.example.local` |
| Betriebssystem | Windows Server beziehungsweise Linux-Distribution und Version |
| Beginn der Störung | Datum und genaue Uhrzeit mit Zeitzone |
| Betroffene Benutzer | Alle Benutzer am Standort Berlin |
| Fehlerbild | HTTP-Verbindung wird aufgebaut, Antwortcode 503 |
| Dienststatus | Dienst läuft beziehungsweise ist beendet |
| Prozess | Prozessname und PID |
| Port und Bindungsadresse | TCP 443 auf einer bestimmten IP-Adresse |
| Relevante Protokollmeldung | Ereignis-ID, Exitcode oder Fehlermeldung |
| Letzte Änderung | Aktualisierung oder Konfigurationsänderung |
| Durchgeführte Prüfungen | DNS-, Port-, Dienst- und Funktionstest |
| Maßnahme | Konfiguration korrigiert und Dienst kontrolliert neu gestartet |
| Funktionstest | Anmeldung und Beispielabfrage erfolgreich |
| Ursache | Technische Grundursache |
| Vorbeugung | Monitoring, Dokumentation oder Konfigurationsprüfung |

</details>

---

**Merksatz**

> **Erreichbarkeit beweist nur den Netzwerkweg. Ein offener Port beweist nur einen Listener. Erst ein erfolgreicher Anwendungstest beweist die Funktion des Dienstes.**

---

**Weiterführende Quellen**

- [Microsoft Learn – sc.exe query](https://learn.microsoft.com/de-de/windows-server/administration/windows-commands/sc-query)
- [Microsoft Learn – Get-Service](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-service)
- [systemd – systemctl](https://www.freedesktop.org/software/systemd/man/latest/systemctl.html)
- [systemd – journalctl](https://www.freedesktop.org/software/systemd/man/latest/journalctl.html)
- [Apple – Einführung in die App „Konsole“](https://support.apple.com/de-de/guide/console/welcome/mac)
- [Apple – Handbuchseite zu launchctl](https://keith.github.io/xcode-man-pages/launchctl.1.html)

# 4.1 Störung und betroffenen Dienst eingrenzen

Bevor Prozesse, Ports oder Protokolldateien untersucht werden, muss eindeutig feststehen, **welche Funktion tatsächlich gestört ist**. Eine Meldung wie „Der Server funktioniert nicht“ reicht für eine gezielte Fehleranalyse nicht aus.

> **Grundsatz:**  
> Zuerst das Fehlerbild und den Störungsumfang bestimmen. Erst danach mit technischen Prüfungen beginnen.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- eine ungenaue Störungsmeldung in ein überprüfbares Fehlerbild überführen können,
- den betroffenen Server und Dienst identifizieren können,
- den Störungsumfang systematisch eingrenzen können,
- zwischen Client-, Benutzer-, Netzwerk-, Dienst- und Anwendungsfehlern unterscheiden können,
- relevante Zeitangaben und Änderungen erfassen können,
- einen geeigneten Vergleichstest auswählen können,
- den Ausgangszustand vor Änderungen dokumentieren können.

---

<details>
<summary><strong>1. Ruhig und hypothesenoffen beginnen</strong></summary>

Bei einer Störung entsteht schnell der Wunsch, sofort einen Dienst neu zu starten oder eine bekannte Lösung auszuprobieren. Dadurch können jedoch wichtige Diagnoseinformationen verloren gehen.

Eine sinnvolle Haltung lautet:

1. Störungsmeldung nicht ungeprüft als Ursache übernehmen.
2. Beobachtungen von Vermutungen trennen.
3. Noch keine technische Ursache festlegen.
4. Zuerst den Umfang der Störung bestimmen.
5. Mit einfachen und möglichst lesenden Prüfungen beginnen.
6. Pro Arbeitsschritt nur eine wesentliche Veränderung durchführen.
7. Vor und nach jeder Maßnahme vergleichen.
8. Ergebnisse und Zeitpunkte dokumentieren.

| Aussage | Einordnung |
|---|---|
| „Das Intranet ist nicht erreichbar.“ | Beobachtung beziehungsweise Fehlerbild |
| „Der Webserver ist abgestürzt.“ | Noch unbestätigte Hypothese |
| „TCP-Port 443 antwortet nicht.“ | Technisches Prüfergebnis |
| „Der Webdienst befindet sich im Zustand `Stopped`.“ | Technisches Prüfergebnis |
| „Der Dienst wurde durch fehlenden Speicher beendet.“ | Mögliche Ursache, die durch Protokolle belegt werden muss |

> **Wichtig:** Eine Fehlermeldung beschreibt häufig nur die Stelle, an der ein Fehler sichtbar wird – nicht die eigentliche Ursache.

</details>

---

<details>
<summary><strong>2. Aus einer Störungsmeldung ein konkretes Fehlerbild erstellen</strong></summary>

Eine gute Fehlerbeschreibung beantwortet mindestens folgende Fragen:

| Frage | Beispiel |
|---|---|
| Was funktioniert nicht? | Anmeldung an der internen Webanwendung |
| Welche konkrete Aktion schlägt fehl? | Absenden des Anmeldeformulars |
| Welche Fehlermeldung erscheint? | HTTP-Statuscode 503 |
| Seit wann besteht das Problem? | Seit 31.07.2026 um 09:15 Uhr |
| Tritt der Fehler dauerhaft oder zeitweise auf? | Bei jedem Anmeldeversuch |
| Wer ist betroffen? | Alle Benutzer am Standort Berlin |
| Welche Clients sind betroffen? | Windows-, Linux- und macOS-Clients |
| Welche Funktion arbeitet weiterhin? | Startseite der Anwendung ist erreichbar |
| Wurde eine alternative Verbindung getestet? | Zugriff über einen zweiten Client ebenfalls fehlerhaft |
| Was wurde zuletzt verändert? | Aktualisierung der Anwendung am Vorabend |

**Unzureichende Beschreibung:**

> „Der Server geht nicht.“

**Verwertbare Beschreibung:**

> „Seit 09:15 Uhr erhalten alle geprüften Benutzer beim Anmelden an `https://intranet.example.local` den HTTP-Statuscode 503. Die Namensauflösung funktioniert und die Startseite ist erreichbar. Der Fehler tritt von mehreren Clients und Benutzerkonten aus auf.“

</details>

---

<details>
<summary><strong>3. Störungsumfang mit einer Eingrenzungsmatrix bestimmen</strong></summary>

| Prüfdimension | Mögliche Eingrenzung |
|---|---|
| Benutzer | Ein Benutzer, Benutzergruppe oder alle Benutzer |
| Endgerät | Ein Client, Gerätetyp oder alle Clients |
| Betriebssystem | Nur Windows, Linux, macOS oder alle Systeme |
| Standort | Ein Raum, Gebäude, Standort oder alle Standorte |
| Netzwerk | LAN, WLAN, VPN, Gastnetz oder alle Zugangswege |
| Anwendung | Eine Funktion, ein Modul oder vollständige Anwendung |
| Dienst | Ein Dienst, mehrere Dienste oder gesamter Server |
| Zeitpunkt | Dauerhaft, sporadisch, zu bestimmten Uhrzeiten |
| Daten | Einzelne Datei, Datensatz, Freigabe oder alle Daten |
| Berechtigung | Einzelnes Konto, Rolle, Gruppe oder alle Konten |
| Protokoll | HTTP, HTTPS, SMB, SSH, RDP oder Datenbankverbindung |
| Backend | Datenbank, Verzeichnisdienst, Speicher oder externe API |

**Beispiele für Schlussfolgerungen:**

| Beobachtung | Wahrscheinlicher Untersuchungsbereich |
|---|---|
| Nur ein Benutzer ist betroffen | Konto, Profil, Berechtigung oder benutzerspezifische Daten |
| Nur ein Client ist betroffen | Clientkonfiguration, Cache, Zertifikat oder lokale Firewall |
| Alle Benutzer eines Standortes sind betroffen | Standortnetz, WAN, DNS, Routing oder Firewall |
| Alle Benutzer sind betroffen | Zentraler Dienst, Server, Backend oder globale Änderung |
| Nur ein Anwendungsmodul ist betroffen | Modulkonfiguration, Backend oder Berechtigung |
| Zugriff per IP-Adresse funktioniert, per Name nicht | DNS oder Namenskonfiguration |
| TCP-Port ist offen, Anwendung antwortet fehlerhaft | Anwendung, Backend, TLS oder Berechtigung |
| Fehler tritt nur unter hoher Last auf | Ressourcen, Grenzwerte, Verbindungspool oder Zeitüberschreitung |

Diese Zuordnungen sind **Arbeitshypothesen** und noch kein endgültiger Ursachenbeweis.

</details>

---

<details>
<summary><strong>4. Betroffenen Server und Dienst eindeutig identifizieren</strong></summary>

Vor der technischen Prüfung müssen folgende Angaben geklärt werden:

| Information | Beispiel |
|---|---|
| Angezeigter Dienstname | Interne Webanwendung |
| Technischer Dienstname | `intranet-api` |
| Prozessname | `intranet-api.exe` beziehungsweise `intranet-api` |
| Servername | `srv-app01.example.local` |
| IP-Adresse | `192.0.2.20` |
| Protokoll | HTTPS |
| Zielport | TCP 443 |
| Pfad oder URL | `https://intranet.example.local/login` |
| Backend | `srv-db01.example.local` |
| Verantwortliches System | Webserver, Anwendungsdienst oder Datenbank |
| Produktivstatus | Produktiv-, Test- oder Entwicklungssystem |

> Der sichtbare Name einer Anwendung, der Betriebssystem-Dienstname und der Prozessname können unterschiedlich sein.

**Beispiel einer Dienstkette:**

```text
Client
  → DNS
  → Firewall oder Loadbalancer
  → Webserver
  → Anwendungsdienst
  → Datenbank
  → Verzeichnisdienst oder externe API
```

Die Störung kann an jeder Übergabestelle dieser Kette entstehen.

</details>

---

<details>
<summary><strong>5. Basisinformationen des untersuchten Servers erfassen</strong></summary>

Die folgenden Befehle verändern den Systemzustand normalerweise nicht.

| Aufgabe | Windows PowerShell | Linux | macOS |
|---|---|---|---|
| Rechnername | `[RO] hostname` | `[RO] hostname` | `[RO] hostname` |
| Vollständiger DNS-Name | `[RO] [System.Net.Dns]::GetHostEntry($env:COMPUTERNAME).HostName` | `[RO] hostname --fqdn` | `[RO] hostname -f` |
| Betriebssysteminformationen | `[RO] Get-ComputerInfo \| Select-Object WindowsProductName,WindowsVersion,OsBuildNumber` | `[RO][FILE] cat /etc/os-release` | `[RO] sw_vers` |
| Systemarchitektur | `[RO] $env:PROCESSOR_ARCHITECTURE` | `[RO] uname -m` | `[RO] uname -m` |
| Kernel beziehungsweise Systemversion | `[RO] systeminfo` | `[RO] uname -a` | `[RO] uname -a` |
| Letzter Systemstart | `[RO] (Get-CimInstance Win32_OperatingSystem).LastBootUpTime` | `[RO] uptime -s` | `[RO] sysctl -n kern.boottime` |
| Aktuelle Laufzeit | `[RO] (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime` | `[RO] uptime` | `[RO] uptime` |
| Aktuelle Uhrzeit | `[RO] Get-Date -Format o` | `[RO] date --iso-8601=seconds` | `[RO] date "+%Y-%m-%dT%H:%M:%S%z"` |
| Zeitzone | `[RO] Get-TimeZone` | `[RO] timedatectl status` | `[RO][PRIV] sudo systemsetup -gettimezone` |
| Angemeldete Benutzer | `[RO] quser` | `[RO] who` | `[RO] who` |

**Hinweise:**

- `hostname --fqdn` liefert nur dann ein sinnvolles Ergebnis, wenn Hostname und Namensauflösung korrekt konfiguriert sind.
- `hostname -f` kann unter macOS abhängig von der lokalen Namenskonfiguration fehlschlagen oder einen unerwarteten Namen liefern.
- `systeminfo` erzeugt eine umfangreiche Ausgabe. Für eine Dokumentation können relevante Zeilen gezielt ausgewählt werden.
- Zeitstempel müssen zusammen mit der Zeitzone dokumentiert werden, damit Client-, Server- und Netzwerkprotokolle richtig verglichen werden können.

</details>

---

<details>
<summary><strong>6. Dienstnamen und Prozesse zunächst nur lesend suchen</strong></summary>

Die Platzhalter `<SUCHBEGRIFF>`, `<DIENST>` und `<PROZESS>` müssen ersetzt werden.

| Aufgabe | Windows PowerShell | Linux | macOS |
|---|---|---|---|
| Dienst nach Namen suchen | `[RO] Get-Service -Name "*<SUCHBEGRIFF>*" -ErrorAction SilentlyContinue` | `[RO] systemctl list-unit-files --type=service \| grep -i -- "<SUCHBEGRIFF>"` | `[RO] launchctl list \| grep -i -- "<SUCHBEGRIFF>"` |
| Dienst nach Anzeigenamen suchen | `[RO] Get-Service -DisplayName "*<SUCHBEGRIFF>*" -ErrorAction SilentlyContinue` | Nicht getrennt vorhanden | Nicht getrennt vorhanden |
| Status eines Dienstes | `[RO] Get-Service -Name "<DIENST>"` | `[RO] systemctl status "<DIENST>" --no-pager` | `[RO] launchctl print "system/<DIENST>"` |
| Prozess nach Namen suchen | `[RO] Get-Process -Name "<PROZESS>" -ErrorAction SilentlyContinue` | `[RO] pgrep -a "<PROZESS>"` | `[RO] pgrep -alf "<PROZESS>"` |
| Prozesse ausführlich anzeigen | `[RO] Get-CimInstance Win32_Process \| Select-Object ProcessId,ParentProcessId,Name,CommandLine` | `[RO] ps -eo user,pid,ppid,lstart,stat,cmd` | `[RO] ps -axo user,pid,ppid,lstart,state,command` |

**Besonderheiten:**

- Windows unterscheidet zwischen internem Dienstnamen und sichtbarem Anzeigenamen.
- Bei systemd gehört die Endung `.service` zum vollständigen Unit-Namen, kann bei eindeutigen Namen aber häufig weggelassen werden.
- `launchctl list` zeigt nicht automatisch alle Konfigurationsdetails eines Dienstes.
- `launchctl print system/<DIENST>` erwartet das tatsächliche launchd-Label.
- Ein laufender Prozess beweist noch nicht, dass der Dienst auf dem erwarteten Port lauscht oder fachlich korrekt arbeitet.

> Auf dieser frühen Diagnosestufe sollte ein Dienst noch nicht neu gestartet werden. Zuerst müssen Status, Prozess, Port und relevante Protokolle erfasst werden.

</details>

---

<details>
<summary><strong>7. Geeignete Vergleichstests durchführen</strong></summary>

Ein Vergleichstest verändert jeweils nur **eine Prüfdimension**. Dadurch lässt sich erkennen, welche Eigenschaft mit dem Fehler zusammenhängt.

| Ausgangssituation | Sinnvoller Vergleich |
|---|---|
| Ein Benutzer meldet einen Fehler | Anderes Benutzerkonto am gleichen Client |
| Ein Client ist betroffen | Gleicher Benutzer an einem anderen Client |
| WLAN-Zugriff scheitert | Gleicher Client über LAN oder VPN |
| Zugriff per Servername scheitert | DNS-Ergebnis prüfen und mit dokumentierter Zieladresse vergleichen |
| Eine URL funktioniert nicht | Andere Funktion desselben Dienstes testen |
| Ein Standort ist betroffen | Zugriff von einem anderen Standort testen |
| Zugriff über Loadbalancer scheitert | Backend nur über den vorgesehenen administrativen Testweg prüfen |
| Anwendung meldet einen Fehler | Porttest und protokollspezifischen Funktionstest getrennt durchführen |
| Produktivsystem ist betroffen | Verhalten im freigegebenen Testsystem vergleichen |
| Fehler tritt zeitabhängig auf | Ergebnisse mit Last, Sicherung oder geplanten Aufgaben vergleichen |

**Regel für einen aussagekräftigen Vergleich:**

```text
Gleicher Benutzer + anderer Client
oder
anderer Benutzer + gleicher Client
oder
gleicher Client + anderer Netzwerkweg
```

Werden mehrere Eigenschaften gleichzeitig verändert, ist das Ergebnis häufig nicht eindeutig.

> Der direkte Zugriff auf ein Backend kann Sicherheitsregeln, Authentifizierung, TLS-Prüfungen oder den Loadbalancer umgehen. Er darf nur über einen freigegebenen administrativen Testweg erfolgen.

</details>

---

<details>
<summary><strong>8. Ersten Client-zu-Dienst-Test dokumentieren</strong></summary>

Bevor auf dem Server weitergesucht wird, sollte der Fehler möglichst reproduziert und genau protokolliert werden.

| Prüfpunkte | Zu dokumentierende Information |
|---|---|
| Ausgangsgerät | Hostname, Betriebssystem und Netzwerkverbindung |
| Benutzerkontext | Betroffenes Konto oder Rolle, ohne Kennwort |
| Ziel | Servername, URL, Freigabe oder Anwendung |
| Zeitpunkt | Datum, Uhrzeit und Zeitzone |
| Aktion | Exakter Arbeitsschritt, der den Fehler auslöst |
| Ergebnis | Vollständige Fehlermeldung oder Statuscode |
| Dauer | Sofortiger Fehler oder Zeitüberschreitung |
| Wiederholbarkeit | Immer, sporadisch oder nur einmal |
| Vergleichstest | Zweiter Client, Benutzer oder Netzwerkweg |
| Beweismittel | Screenshot, Ereignis-ID, Logauszug oder Befehlsausgabe |

**Beispiel:**

```text
Zeitpunkt:       2026-07-31T09:15:42+02:00
Client:          client-017
Betriebssystem:  Windows 11
Benutzerrolle:   Standardbenutzer
Ziel:            https://intranet.example.local/login
Aktion:          Anmeldeformular abgesendet
Ergebnis:        HTTP 503
Dauer:           Antwort nach ungefähr 2 Sekunden
Wiederholbar:    Ja
Vergleich:       Gleicher Fehler auf einem zweiten Client
```

Sensible Inhalte wie Kennwörter, Sitzungscookies, Zugriffstoken, private Schlüssel oder vollständige personenbezogene Daten dürfen nicht in die Dokumentation übernommen werden.

</details>

---

<details>
<summary><strong>9. Letzte Änderungen und zeitliche Zusammenhänge erfassen</strong></summary>

Viele Dienstfehler entstehen nach einer technischen oder organisatorischen Änderung. Ein zeitlicher Zusammenhang ist jedoch noch kein Beweis für die Ursache.

Zu prüfen sind insbesondere:

- Betriebssystem- und Anwendungsupdates,
- Änderungen an Konfigurationsdateien,
- Zertifikatswechsel,
- Kennwortänderungen von Dienstkonten,
- Änderungen an Gruppen oder Berechtigungen,
- Firewall- und Proxyänderungen,
- DNS- oder Loadbalanceränderungen,
- Datenbankmigrationen,
- Speicher- und Volumeänderungen,
- Container- oder Image-Updates,
- Neustarts und Stromausfälle,
- Sicherungs- und Wartungsaufgaben,
- Änderungen an externen APIs,
- abgelaufene Lizenzen oder Zertifikate,
- neu eingerichtete Überwachungs- oder Sicherheitssoftware.

| Frage | Zweck |
|---|---|
| Was wurde geändert? | Technische Änderung bestimmen |
| Wann wurde es geändert? | Zeitliche Übereinstimmung prüfen |
| Auf welchem System? | Betroffene Komponente bestimmen |
| Wer oder welcher Prozess führte die Änderung aus? | Rückfragen und Audit ermöglichen |
| Wurde die Änderung getestet? | Fehlende Prüfungen erkennen |
| Gibt es einen Rückfallplan? | Wiederherstellung bewerten |
| Besteht der Fehler auch ohne diese Änderung? | Kausalität weiter untersuchen |

> Die Aussage „Seit dem Update besteht der Fehler“ ist eine wichtige Spur. Erst ein reproduzierbarer Zusammenhang oder ein passender Protokolleintrag macht daraus einen belastbaren Ursachenhinweis.

</details>

---

<details>
<summary><strong>10. Wann die Eingrenzung abgeschlossen ist</strong></summary>

Die erste Eingrenzung ist ausreichend, wenn folgende Punkte beantwortet sind:

- Welche konkrete Funktion ist gestört?
- Welcher Server oder Dienst stellt diese Funktion bereit?
- Welche Benutzer, Geräte und Standorte sind betroffen?
- Welche Bereiche sind ausdrücklich nicht betroffen?
- Seit wann besteht die Störung?
- Ist der Fehler reproduzierbar?
- Welche Fehlermeldung oder welcher Statuscode erscheint?
- Welche Vergleichstests wurden durchgeführt?
- Welche Änderungen gingen der Störung voraus?
- Welche technische Ebene wird als Nächstes geprüft?
- Wurde der Ausgangszustand dokumentiert?

**Beispiel einer abgeschlossenen Eingrenzung:**

> Alle geprüften Benutzer können die Startseite des Intranets über HTTPS aufrufen. Beim Absenden des Anmeldeformulars antwortet die Anwendung jedoch mit HTTP 503. Der Fehler tritt von Windows-, Linux- und macOS-Clients sowie an zwei Standorten auf. DNS-Auflösung und Netzwerkzugriff funktionieren. Als Nächstes werden deshalb Dienststatus, Prozess und Backend-Abhängigkeiten auf dem Anwendungsserver geprüft.

</details>

---

<details>
<summary><strong>11. Typische Fehler bei der ersten Eingrenzung</strong></summary>

| Fehler | Folge | Bessere Vorgehensweise |
|---|---|---|
| Sofortiger Neustart | Flüchtige Diagnoseinformationen gehen verloren | Zustand und Protokolle zuerst sichern |
| Fehlermeldung als Ursache behandeln | Untersuchung beginnt an der falschen Stelle | Beobachtung und Ursache trennen |
| Nur einen Benutzer befragen | Störungsumfang bleibt unbekannt | Vergleich mit weiteren Benutzern durchführen |
| Nur `ping` verwenden | Dienstfunktion bleibt ungeprüft | Port- und Anwendungstest ergänzen |
| Mehrere Änderungen gleichzeitig | Wirkung einzelner Maßnahmen bleibt unklar | Änderungen einzeln durchführen |
| Servername nicht verifizieren | Falsches System wird untersucht | Ziel, IP-Adresse und Umgebung abgleichen |
| Test- und Produktivsystem verwechseln | Falsche Ergebnisse oder Betriebsrisiko | Umgebung eindeutig dokumentieren |
| Keine Zeitstempel erfassen | Protokolle lassen sich schlecht zuordnen | Datum, Uhrzeit und Zeitzone notieren |
| Nur Erfolg oder Fehler notieren | Diagnose ist nicht nachvollziehbar | Befehl, Ausgabe und Kontext dokumentieren |
| Geheimnisse in Tickets kopieren | Sicherheitsrisiko | Kennwörter, Token und Cookies entfernen |

</details>

---

<details>
<summary><strong>12. Kompakte Checkliste für den Einsatz</strong></summary>

```text
[ ] Konkrete gestörte Funktion erfasst
[ ] Vollständige Fehlermeldung erfasst
[ ] Datum, Uhrzeit und Zeitzone notiert
[ ] Betroffene Benutzer bestimmt
[ ] Betroffene Clients und Betriebssysteme bestimmt
[ ] Betroffene Standorte und Netzwerkwege bestimmt
[ ] Funktionierende Bereiche dokumentiert
[ ] Fehler reproduziert
[ ] Vergleichstest durchgeführt
[ ] Servername und Umgebung verifiziert
[ ] Dienstname, Prozess, Protokoll und Port zugeordnet
[ ] Abhängige Systeme aufgenommen
[ ] Letzte Änderungen erfragt
[ ] Ausgangszustand vor Änderungen dokumentiert
[ ] Keine Kennwörter, Token oder vertraulichen Daten gespeichert
[ ] Nächster technischer Prüfschritt festgelegt
```

</details>

---

**Ergebnis dieser Diagnosestufe**

Am Ende dieser Seite steht noch nicht zwingend die Ursache fest. Es muss jedoch klar sein:

```text
Was ist gestört?
Wer oder was ist betroffen?
Seit wann besteht die Störung?
Welcher Dienst stellt die Funktion bereit?
Auf welchem System läuft er?
Wie lässt sich der Fehler reproduzieren?
Welche technische Ebene wird als Nächstes geprüft?
```

Die nächste Diagnosestufe ist die Überprüfung von **Dienststatus und Startart**.

---

**Weiterführende Quellen**

- [Microsoft Learn – Get-Service](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-service)
- [Microsoft Learn – Get-CimInstance](https://learn.microsoft.com/powershell/module/cimcmdlets/get-ciminstance)
- [Microsoft Learn – Windows-Dienstprogramme und Befehle](https://learn.microsoft.com/windows-server/administration/windows-commands/windows-commands)
- [systemd – systemctl](https://www.freedesktop.org/software/systemd/man/latest/systemctl.html)
- [systemd – systemd.unit](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html)
- [Apple – launchctl-Handbuchseite](https://keith.github.io/xcode-man-pages/launchctl.1.html)
- [Apple – Aktivitätsanzeige – Benutzerhandbuch](https://support.apple.com/de-de/guide/activity-monitor/welcome/mac)

# 4.2 Dienststatus und Startart prüfen

Nachdem der betroffene Dienst eindeutig bestimmt wurde, wird geprüft, ob er:

- im Betriebssystem registriert beziehungsweise geladen ist,
- aktuell ausgeführt wird,
- beendet oder fehlgeschlagen ist,
- beim Systemstart oder bei Bedarf gestartet werden soll,
- deaktiviert wurde,
- unter dem vorgesehenen Benutzerkonto läuft,
- nach einem Fehler automatisch neu gestartet wird.

> **Grundsatz:**  
> Zuerst den vorhandenen Zustand vollständig erfassen. Einen Dienst erst danach und nur bei betrieblicher Freigabe starten, stoppen oder neu starten.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- Dienstname und Anzeigename unterscheiden können,
- den aktuellen Dienststatus ermitteln können,
- die konfigurierte Startart überprüfen können,
- Startart und aktuellen Laufzustand getrennt bewerten können,
- Dienstkonto, Prozess-ID und Exitcode ermitteln können,
- Windows-Dienste, systemd-Units und launchd-Jobs unterscheiden können,
- deaktivierte oder maskierte Dienste erkennen können,
- einen wiederholt abstürzenden Dienst identifizieren können,
- Statusinformationen vor einer Änderung dokumentieren können.

---

**Sicherheitskennzeichnungen**

| Kennzeichnung | Bedeutung |
|---|---|
| `[RO]` | Rein lesende Abfrage |
| `[TEST]` | Aktiver Test ohne beabsichtigte dauerhafte Konfigurationsänderung |
| `[PRIV]` | Erfordert möglicherweise erhöhte Rechte |
| `[FILE]` | Greift lesend oder schreibend auf eine Datei zu |
| `[SENS]` | Ausgabe kann sensible Informationen enthalten |
| `[CHANGE]` | Verändert den Dienstzustand oder die Konfiguration |
| `[DISRUPT]` | Kann laufende Verbindungen oder Arbeitsvorgänge unterbrechen |

---

<details>
<summary><strong>1. Startart und Dienststatus nicht verwechseln</strong></summary>

Die **Startart** beschreibt, wann beziehungsweise wodurch ein Dienst gestartet werden soll. Der **Dienststatus** beschreibt seinen aktuellen Zustand.

| Startart beziehungsweise Aktivierung | Aktueller Zustand | Mögliche Bewertung |
|---|---|---|
| Automatisch aktiviert | Läuft | Normaler Zustand |
| Automatisch aktiviert | Beendet | Startfehler, Absturz oder bewusster Stopp möglich |
| Manuell beziehungsweise bedarfsgesteuert | Beendet | Kann ein normaler Zustand sein |
| Manuell beziehungsweise bedarfsgesteuert | Läuft | Dienst wurde angefordert oder manuell gestartet |
| Deaktiviert | Beendet | Erwarteter Zustand |
| Deaktiviert | Läuft | Zustandsänderung möglicherweise noch nicht wirksam oder Sonderfall |
| Aktiviert | Wiederholt startend und stoppend | Absturzschleife oder fehlerhafte Startbedingung möglich |

> Ein beendeter Dienst ist nicht automatisch fehlerhaft. Bedarfsgesteuerte Dienste laufen häufig nur, wenn sie tatsächlich benötigt werden.

</details>

---

<details>
<summary><strong>2. Dienstverwaltung der Betriebssysteme vergleichen</strong></summary>

| Betriebssystem | Dienstverwaltung | Konfigurationseinheit | Typische Statusabfrage |
|---|---|---|---|
| Windows | Service Control Manager | Windows-Dienst | `Get-Service` oder `sc.exe query` |
| Linux mit systemd | systemd | Unit, meistens `.service` | `systemctl status` |
| macOS | launchd | Daemon, Agent oder XPC-Service | `launchctl print` |

**Wichtige Unterschiede:**

- Windows verwendet unter anderem die Startarten automatisch, manuell und deaktiviert.
- systemd unterscheidet den aktuellen Laufzustand von der Aktivierung für den Systemstart.
- Eine systemd-Unit kann zusätzlich `masked` sein. Dann kann sie nicht normal gestartet werden.
- macOS verwendet häufig bedarfsgesteuerte Dienste.
- Ein launchd-Job muss deshalb nicht dauerhaft als Prozess laufen.
- launchd unterscheidet verschiedene Ausführungsbereiche, sogenannte Domains.
- Ein fehlender Prozess bedeutet bei einem bedarfsgesteuerten launchd-Dienst nicht automatisch einen Fehler.

</details>

---

<details>
<summary><strong>3. Dienststatus unter Windows prüfen</strong></summary>

`<DIENSTNAME>` muss durch den internen Dienstnamen ersetzt werden.

**Status eines bestimmten Dienstes:**

```powershell
[RO] Get-Service -Name "<DIENSTNAME>"
```

**Ausgewählte Statusinformationen anzeigen:**

```powershell
[RO] Get-Service -Name "<DIENSTNAME>" |
    Select-Object Name, DisplayName, Status, ServiceType
```

**Mit einem Teil des Dienstnamens suchen:**

```powershell
[RO] Get-Service -Name "*<SUCHBEGRIFF>*" -ErrorAction SilentlyContinue
```

**Mit einem Teil des Anzeigenamens suchen:**

```powershell
[RO] Get-Service -DisplayName "*<SUCHBEGRIFF>*" -ErrorAction SilentlyContinue
```

**Alle beendeten Dienste anzeigen:**

```powershell
[RO] Get-Service |
    Where-Object Status -eq "Stopped" |
    Sort-Object DisplayName
```

**Alle laufenden Dienste anzeigen:**

```powershell
[RO] Get-Service |
    Where-Object Status -eq "Running" |
    Sort-Object DisplayName
```

**Dienststatus mit `sc.exe` abfragen:**

```powershell
[RO] sc.exe query "<DIENSTNAME>"
```

**Erweiterte Statusabfrage einschließlich Prozess-ID:**

```powershell
[RO] sc.exe queryex "<DIENSTNAME>"
```

Typische Zustände sind:

| Zustand | Bedeutung |
|---|---|
| `Running` beziehungsweise `RUNNING` | Dienst wird ausgeführt |
| `Stopped` beziehungsweise `STOPPED` | Dienst wird nicht ausgeführt |
| `StartPending` beziehungsweise `START_PENDING` | Startvorgang läuft |
| `StopPending` beziehungsweise `STOP_PENDING` | Beendigung läuft |
| `PausePending` | Pausierung wird vorbereitet |
| `Paused` | Dienst ist pausiert |
| `ContinuePending` | Fortsetzung wird vorbereitet |

> Bleibt ein Dienst ungewöhnlich lange in `StartPending` oder `StopPending`, müssen Prozess, Abhängigkeiten und Ereignisprotokolle untersucht werden. Ein erzwungener Abbruch ist nicht der erste Diagnoseschritt.

</details>

---

<details>
<summary><strong>4. Startart und Dienstkonto unter Windows prüfen</strong></summary>

`Get-Service` zeigt den Laufzustand, aber nicht alle Konfigurationsinformationen. Dafür kann die CIM-Klasse `Win32_Service` verwendet werden.

**Vollständige Basiskonfiguration eines Dienstes:**

```powershell
[RO][SENS] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name,
                  DisplayName,
                  State,
                  Status,
                  StartMode,
                  StartName,
                  ProcessId,
                  ExitCode,
                  ServiceSpecificExitCode,
                  PathName
```

**Nur Startart und Dienstkonto anzeigen:**

```powershell
[RO] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name, State, StartMode, StartName
```

**Konfiguration mit `sc.exe` prüfen:**

```powershell
[RO][SENS] sc.exe qc "<DIENSTNAME>"
```

Typische Werte für `StartMode`:

| Wert | Bedeutung |
|---|---|
| `Auto` | Automatischer Start |
| `Manual` | Manueller beziehungsweise bedarfsgesteuerter Start |
| `Disabled` | Dienst ist deaktiviert |
| `Boot` | Start durch den Systemlader, normalerweise bei Treibern |
| `System` | Start während der Kernelinitialisierung, normalerweise bei Treibern |

**Typische Angaben von `sc.exe qc`:**

| Angabe | Bedeutung |
|---|---|
| `SERVICE_NAME` | Interner Dienstname |
| `TYPE` | Art des Dienstes oder Treibers |
| `START_TYPE` | Konfigurierte Startart |
| `ERROR_CONTROL` | Verhalten bei Startfehlern während des Systemstarts |
| `BINARY_PATH_NAME` | Programmdatei und Startparameter |
| `DEPENDENCIES` | Konfigurierte Abhängigkeiten |
| `SERVICE_START_NAME` | Verwendetes Dienstkonto |

> `[SENS]`: Programmpfade und Startparameter können interne Verzeichnisstrukturen, Servernamen oder andere schützenswerte Konfigurationsangaben enthalten.

</details>

---

<details>
<summary><strong>5. Verzögerten automatischen Start unter Windows prüfen</strong></summary>

Die Startart `Auto` allein zeigt nicht immer, ob der automatische Start verzögert erfolgt.

**Dienstkonfiguration über CIM prüfen:**

```powershell
[RO] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name, State, StartMode, DelayedAutoStart
```

Interpretation:

| `StartMode` | `DelayedAutoStart` | Bedeutung |
|---|---:|---|
| `Auto` | `False` | Normaler automatischer Start |
| `Auto` | `True` | Verzögerter automatischer Start |
| `Manual` | `False` | Manueller oder bedarfsgesteuerter Start |
| `Disabled` | `False` | Dienst ist deaktiviert |

Falls `DelayedAutoStart` auf dem untersuchten System nicht ausgegeben wird, kann der Wert gezielt in der Dienstkonfiguration der Registrierung geprüft werden:

```powershell
[RO] Get-ItemProperty `
    -Path "HKLM:\SYSTEM\CurrentControlSet\Services\<DIENSTNAME>" `
    -Name DelayedAutoStart `
    -ErrorAction SilentlyContinue
```

Dabei gilt üblicherweise:

| Wert | Bedeutung |
|---:|---|
| `1` | Verzögerter automatischer Start aktiviert |
| `0` oder nicht vorhanden | Kein verzögerter Start daraus ableitbar |

> Die Registrierung darf an dieser Stelle nur gelesen werden. Eine Änderung der Startart gehört in ein freigegebenes Änderungsverfahren.

</details>

---

<details>
<summary><strong>6. Dienststatus unter Linux mit systemd prüfen</strong></summary>

`<DIENST>` muss durch den tatsächlichen Unit-Namen ersetzt werden, beispielsweise `nginx.service`.

**Ausführlichen Status anzeigen:**

```bash
[RO] systemctl status "<DIENST>" --no-pager
```

**Aktuellen Laufzustand abfragen:**

```bash
[RO] systemctl is-active "<DIENST>"
```

**Prüfen, ob die Unit für einen automatischen Start aktiviert ist:**

```bash
[RO] systemctl is-enabled "<DIENST>"
```

**Prüfen, ob die Unit fehlgeschlagen ist:**

```bash
[RO] systemctl is-failed "<DIENST>"
```

**Wichtige Eigenschaften kompakt anzeigen:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=Id,Names,LoadState,ActiveState,SubState,UnitFileState,MainPID,ExecMainCode,ExecMainStatus,Result
```

**Alle fehlgeschlagenen Units anzeigen:**

```bash
[RO] systemctl --failed --no-pager
```

**Laufende Dienste anzeigen:**

```bash
[RO] systemctl list-units \
  --type=service \
  --state=running \
  --no-pager
```

**Installierte Service-Unit-Dateien und Aktivierungszustände anzeigen:**

```bash
[RO] systemctl list-unit-files --type=service --no-pager
```

> `systemctl status` zeigt zusätzlich einige aktuelle Protokollzeilen. Für eine vollständige Protokollanalyse wird später gezielt `journalctl` verwendet.

</details>

---

<details>
<summary><strong>7. systemd-Zustände richtig interpretieren</strong></summary>

systemd verwendet mehrere voneinander unabhängige Zustandsangaben.

**Ladezustand:**

| `LoadState` | Bedeutung |
|---|---|
| `loaded` | Unit-Datei wurde erfolgreich geladen |
| `not-found` | Keine passende Unit-Datei gefunden |
| `error` | Fehler beim Laden |
| `masked` | Unit wurde maskiert und kann nicht normal gestartet werden |

**Aktivzustand:**

| `ActiveState` | Bedeutung |
|---|---|
| `active` | Unit ist aktiv |
| `inactive` | Unit ist nicht aktiv |
| `activating` | Aktivierung läuft |
| `deactivating` | Deaktivierung läuft |
| `failed` | Aktivierung oder Ausführung ist fehlgeschlagen |
| `reloading` | Konfiguration wird neu geladen |

**Typische Aktivierungszustände:**

| `systemctl is-enabled` | Bedeutung |
|---|---|
| `enabled` | Für einen vorgesehenen automatischen Start aktiviert |
| `enabled-runtime` | Nur bis zum nächsten Neustart aktiviert |
| `disabled` | Nicht für automatischen Start aktiviert |
| `static` | Keine eigene Aktivierung über einen Installationsabschnitt; kann abhängig gestartet werden |
| `indirect` | Indirekte Aktivierung über eine andere Unit vorgesehen |
| `masked` | Start vollständig blockiert |
| `masked-runtime` | Bis zum nächsten Neustart maskiert |
| `generated` | Unit wurde dynamisch erzeugt |
| `transient` | Temporäre Unit |
| `not-found` | Unit wurde nicht gefunden |

**Wichtige Kombinationen:**

| Laufzustand | Aktivierungszustand | Bewertung |
|---|---|---|
| `active` | `enabled` | Läuft und ist dauerhaft aktiviert |
| `inactive` | `enabled` | Sollte möglicherweise laufen; Start- und Protokollprüfung erforderlich |
| `active` | `disabled` | Wurde manuell, abhängig oder auf anderem Weg gestartet |
| `inactive` | `static` | Kann bei bedarfsgesteuerten oder abhängigen Units normal sein |
| `failed` | beliebig | Fehlerursache und Protokolle untersuchen |
| `inactive` | `masked` | Start ist absichtlich blockiert |

> `disabled` bedeutet nicht automatisch „defekt“. Es bedeutet zunächst nur, dass die Unit nicht über ihre normalen Installationsverknüpfungen für den automatischen Start aktiviert ist.

</details>

---

<details>
<summary><strong>8. systemd-Unit-Datei und Startbefehl prüfen</strong></summary>

**Wirksame Unit-Datei einschließlich Ergänzungen anzeigen:**

```bash
[RO][FILE][SENS] systemctl cat "<DIENST>"
```

**Pfad der geladenen Unit-Datei anzeigen:**

```bash
[RO] systemctl show "<DIENST>" --property=FragmentPath
```

**Ergänzende Drop-in-Konfigurationen anzeigen:**

```bash
[RO] systemctl show "<DIENST>" --property=DropInPaths
```

**Startbefehl und Dienstkonto anzeigen:**

```bash
[RO][SENS] systemctl show "<DIENST>" \
  --property=User,Group,ExecStart,WorkingDirectory,EnvironmentFiles
```

**Abhängigkeiten anzeigen:**

```bash
[RO] systemctl list-dependencies "<DIENST>" --no-pager
```

**Prüfen, wodurch die Unit für den Systemstart eingebunden ist:**

```bash
[RO] systemctl is-enabled "<DIENST>"
```

Die Ausgabe von `systemctl cat` kann enthalten:

- ursprüngliche Unit-Datei,
- lokale Überschreibungen,
- Drop-in-Dateien,
- Start- und Stopbefehle,
- Dienstkonto,
- Neustartregeln,
- Abhängigkeiten,
- Umgebungsdateien.

> `[SENS]`: Unit-Dateien können interne Pfade, Serveradressen oder Umgebungsdateien referenzieren. Die Inhalte von geheimen Umgebungsdateien dürfen nicht ungeprüft in Tickets oder Dokumentationen kopiert werden.

</details>

---

<details>
<summary><strong>9. Dienststatus unter macOS mit launchd prüfen</strong></summary>

macOS unterscheidet unter anderem folgende Domains:

| Domain | Bedeutung | Beispiel |
|---|---|---|
| `system` | Systemweite Dienste | `system/com.example.service` |
| `user/<UID>` | Dienste eines Benutzerkontextes | `user/501/com.example.service` |
| `gui/<UID>` | Dienste einer grafischen Anmeldesitzung | `gui/501/com.example.agent` |

**Benutzer-ID des aktuell angemeldeten Terminalbenutzers anzeigen:**

```bash
[RO] id -u
```

**Systemweiten Dienst prüfen:**

```bash
[RO] launchctl print "system/<LABEL>"
```

**Dienst im GUI-Kontext des aktuellen Benutzers prüfen:**

```bash
[RO] launchctl print "gui/$(id -u)/<LABEL>"
```

**Gesamten Systembereich anzeigen:**

```bash
[RO] launchctl print system
```

**GUI-Bereich des aktuellen Benutzers anzeigen:**

```bash
[RO] launchctl print "gui/$(id -u)"
```

Die Detailausgabe eines Dienstes kann unter anderem enthalten:

- Dienstlabel,
- aktuellen Zustand,
- Programmpfad,
- Startargumente,
- Prozess-ID,
- letzten Exitstatus,
- Dienstursprung auf dem Datenträger,
- Ausführungskontext,
- Startbedingungen.

> Die Ausgabe von `launchctl print` ist für die manuelle Diagnose bestimmt. Apple garantiert ihr Format nicht als stabile Schnittstelle für Skripte.

</details>

---

<details>
<summary><strong>10. Deaktivierte launchd-Dienste unter macOS prüfen</strong></summary>

**Deaktivierungsüberschreibungen im Systembereich anzeigen:**

```bash
[RO] launchctl print-disabled system
```

**Deaktivierungsüberschreibungen im GUI-Bereich anzeigen:**

```bash
[RO] launchctl print-disabled "gui/$(id -u)"
```

Ein Eintrag mit `true` bedeutet, dass der Dienst in dieser Domain deaktiviert wurde. Ein Eintrag mit `false` bedeutet, dass eine Aktivierungsüberschreibung vorhanden sein kann.

**Wichtig:**

- Nicht jeder Dienst erscheint in `print-disabled`.
- Ein fehlender Eintrag bedeutet nicht automatisch, dass der Dienst aktiviert ist.
- Die effektive Startentscheidung kann zusätzlich von der plist-Konfiguration und Startbedingungen abhängen.
- Aktivierungsüberschreibungen werden außerhalb der eigentlichen plist-Datei verwaltet.
- Ein launchd-Job kann aktiviert, aber momentan ohne laufenden Prozess sein.
- Bedarfsgesteuerte Dienste werden möglicherweise erst beim Eintreten einer Startbedingung ausgeführt.

</details>

---

<details>
<summary><strong>11. launchd-Konfiguration unter macOS prüfen</strong></summary>

Typische Speicherorte sind:

| Pfad | Bedeutung |
|---|---|
| `/System/Library/LaunchDaemons` | Von macOS bereitgestellte systemweite Dienste |
| `/Library/LaunchDaemons` | Zusätzlich installierte systemweite Dienste |
| `/System/Library/LaunchAgents` | Von macOS bereitgestellte Benutzer-Agenten |
| `/Library/LaunchAgents` | Zusätzlich installierte Benutzer-Agenten |
| `~/Library/LaunchAgents` | Agenten des jeweiligen Benutzers |

> Dateien unter `/System/Library` gehören zum Betriebssystem und dürfen nicht manuell verändert werden.

**Konfigurationsdatei eines bekannten Drittanbieterdienstes lesbar anzeigen:**

```bash
[RO][FILE][SENS] plutil -p "/Library/LaunchDaemons/<LABEL>.plist"
```

**Konfigurationsdatei auf formale plist-Fehler prüfen:**

```bash
[RO][FILE] plutil -lint "/Library/LaunchDaemons/<LABEL>.plist"
```

**Benutzerbezogenen Agenten anzeigen:**

```bash
[RO][FILE][SENS] plutil -p "$HOME/Library/LaunchAgents/<LABEL>.plist"
```

Typische Schlüssel einer launchd-plist:

| Schlüssel | Bedeutung |
|---|---|
| `Label` | Eindeutige Dienstbezeichnung |
| `Program` | Auszuführendes Programm |
| `ProgramArguments` | Programm und Argumente |
| `RunAtLoad` | Start beim Laden der Jobdefinition |
| `KeepAlive` | Bedingungen für Ausführung beziehungsweise Neustart |
| `StartInterval` | Zeitgesteuerter Start in Sekundenabständen |
| `StartCalendarInterval` | Kalenderbasierter Start |
| `WatchPaths` | Start bei Änderungen überwachter Pfade |
| `QueueDirectories` | Start, wenn ein überwachtes Verzeichnis nicht leer ist |
| `UserName` | Benutzerkonto eines systemweiten Daemons |
| `GroupName` | Gruppenkonto eines systemweiten Daemons |
| `WorkingDirectory` | Arbeitsverzeichnis |
| `StandardOutPath` | Datei für Standardausgabe |
| `StandardErrorPath` | Datei für Fehlerausgabe |
| `Disabled` | Standardvorgabe zur Deaktivierung; kann überschrieben werden |

> `RunAtLoad`, `KeepAlive` und andere Startbedingungen sind nicht direkt mit den Windows-Startarten gleichzusetzen. launchd ist stark auf bedarfs- und ereignisgesteuertes Starten ausgelegt.

</details>

---

<details>
<summary><strong>12. Letzten Exitstatus und wiederholte Starts erkennen</strong></summary>

| Betriebssystem | Prüfung |
|---|---|
| Windows | Dienststatus, Prozess-ID, Exitcode und Ereignisprotokolle |
| Linux | `Result`, `ExecMainCode`, `ExecMainStatus`, Neustartzähler und Journal |
| macOS | `state`, `pid`, `last exit code` und Unified Logging |

**Windows:**

```powershell
[RO] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name, State, ProcessId, ExitCode, ServiceSpecificExitCode
```

**Linux:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=ActiveState,SubState,Result,MainPID,ExecMainCode,ExecMainStatus,NRestarts
```

**macOS:**

```bash
[RO] launchctl print "system/<LABEL>"
```

Bei macOS sind insbesondere folgende Angaben relevant:

```text
state
pid
last exit code
runs
reason
```

Die tatsächlich vorhandenen Felder können abhängig vom Dienst und von der macOS-Version abweichen.

**Verdächtige Anzeichen:**

- Prozess-ID wechselt in kurzen Abständen,
- Neustartzähler steigt,
- Dienststatus springt zwischen Start und Stopp,
- letzter Exitcode ist ungleich null,
- Dienst wird durch ein Signal beendet,
- Startgrenze oder Neustartbegrenzung wird erreicht,
- Dienst läuft nur wenige Sekunden,
- abhängiger Dienst ist nicht verfügbar.

> Ein Exitcode ist zunächst nur ein technischer Hinweis. Seine genaue Bedeutung muss anhand der Dienst-, Hersteller- oder Betriebssystemdokumentation bestimmt werden.

</details>

---

<details>
<summary><strong>13. Status vor einer Änderung dokumentieren</strong></summary>

Vor einem Start, Stopp oder Neustart sollten mindestens folgende Informationen gesichert werden:

| Information | Zweck |
|---|---|
| Datum, Uhrzeit und Zeitzone | Zuordnung zu Protokolleinträgen |
| Dienstname und Anzeigename | Eindeutige Identifikation |
| Aktueller Status | Ausgangszustand |
| Konfigurierte Startart | Sollverhalten |
| Prozess-ID | Zuordnung zum Prozess |
| Dienstkonto | Berechtigungsprüfung |
| Programmpfad und Argumente | Konfigurationsprüfung |
| Exitcode | Hinweis auf Beendigungsursache |
| Abhängigkeiten | Auswirkungsanalyse |
| Neustartregeln | Erkennung automatischer Wiederanläufe |
| Letzte Protokollmeldungen | Erhaltung flüchtiger Diagnoseinformationen |
| Aktive Verbindungen | Bewertung möglicher Unterbrechungen |

**Kompakte Dokumentationsvorlage:**

```text
Zeitpunkt:
Server:
Betriebssystem:
Dienstname:
Anzeigename beziehungsweise Label:
Dienststatus:
Startart beziehungsweise Aktivierung:
Prozess-ID:
Dienstkonto:
Programmpfad:
Letzter Exitcode:
Neustartzähler:
Abhängigkeiten:
Relevante Protokollmeldung:
Bewertung:
Nächster Prüfschritt:
```

</details>

---

<details>
<summary><strong>14. Dienstzustand verändern – nur nach Freigabe</strong></summary>

Die folgenden Befehle sind **keine reinen Diagnosebefehle**. Sie verändern den Zustand und können Benutzer, Verbindungen oder Datenverarbeitung beeinträchtigen.

| Aufgabe | Windows PowerShell | Linux mit systemd | macOS mit launchd |
|---|---|---|---|
| Dienst starten | `[CHANGE][PRIV] Start-Service -Name "<DIENSTNAME>"` | `[CHANGE][PRIV] sudo systemctl start "<DIENST>"` | `[CHANGE][PRIV] sudo launchctl kickstart "system/<LABEL>"` |
| Dienst stoppen | `[CHANGE][DISRUPT][PRIV] Stop-Service -Name "<DIENSTNAME>"` | `[CHANGE][DISRUPT][PRIV] sudo systemctl stop "<DIENST>"` | `[CHANGE][DISRUPT][PRIV] sudo launchctl kill SIGTERM "system/<LABEL>"` |
| Dienst neu starten | `[CHANGE][DISRUPT][PRIV] Restart-Service -Name "<DIENSTNAME>"` | `[CHANGE][DISRUPT][PRIV] sudo systemctl restart "<DIENST>"` | `[CHANGE][DISRUPT][PRIV] sudo launchctl kickstart -k "system/<LABEL>"` |
| Aktivieren | `[CHANGE][PRIV] Set-Service -Name "<DIENSTNAME>" -StartupType Automatic` | `[CHANGE][PRIV] sudo systemctl enable "<DIENST>"` | `[CHANGE][PRIV] sudo launchctl enable "system/<LABEL>"` |
| Deaktivieren | `[CHANGE][DISRUPT][PRIV] Set-Service -Name "<DIENSTNAME>" -StartupType Disabled` | `[CHANGE][PRIV] sudo systemctl disable "<DIENST>"` | `[CHANGE][PRIV] sudo launchctl disable "system/<LABEL>"` |

**Wichtige Unterschiede:**

- `systemctl enable` startet einen Dienst normalerweise nicht sofort.
- `systemctl start` aktiviert ihn nicht automatisch für spätere Systemstarts.
- `systemctl enable --now` würde beide Vorgänge kombinieren und ist deshalb eine weitergehende Änderung.
- `launchctl kickstart -k` beendet eine bereits laufende Instanz und startet sie neu.
- `launchctl disable` speichert eine Deaktivierungsüberschreibung, die Neustarts überdauern kann.
- Das Senden von `SIGTERM` beendet den aktuellen Prozess. launchd kann ihn abhängig von der Konfiguration erneut starten.
- Das Ändern der Startart beseitigt nicht die Ursache eines Startfehlers.

> Diese Befehle sollten erst nach Sicherung des Ausgangszustands, Prüfung der Auswirkungen und betrieblicher Freigabe eingesetzt werden.

</details>

---

<details>
<summary><strong>15. Typische Fehlinterpretationen</strong></summary>

| Fehlinterpretation | Tatsächliche Bedeutung |
|---|---|
| „Der Dienst ist beendet, also ist er defekt.“ | Ein manueller oder bedarfsgesteuerter Dienst kann regulär beendet sein |
| „Der Dienst ist aktiviert, also läuft er.“ | Aktivierung und aktueller Laufzustand sind getrennte Eigenschaften |
| „Der Prozess läuft, also funktioniert der Dienst.“ | Port, Protokoll und Anwendungsfunktion können trotzdem fehlerhaft sein |
| „systemd zeigt `static`, also ist die Unit deaktiviert.“ | Die Unit kann durch Abhängigkeiten oder andere Auslöser gestartet werden |
| „systemd zeigt `disabled`, also kann die Unit nicht gestartet werden.“ | Ein deaktivierter Dienst kann weiterhin manuell gestartet werden |
| „systemd zeigt `masked`, das ist dasselbe wie `disabled`.“ | Eine maskierte Unit ist zusätzlich gegen normalen Start blockiert |
| „launchd zeigt keine PID, also ist der Dienst defekt.“ | Ein bedarfsgesteuerter Job kann momentan ohne Prozess sein |
| „Exitcode 0 beweist vollständige Funktion.“ | Er zeigt nur eine erfolgreiche Beendigung nach Definition des Programms |
| „Ein Neustart hat das Problem gelöst.“ | Er kann nur das sichtbare Fehlerbild vorübergehend beseitigt haben |
| „Automatischer Neustart ist immer erwünscht.“ | Er kann Abstürze verdecken oder eine Neustartschleife erzeugen |

</details>

---

<details>
<summary><strong>16. Checkliste zur Status- und Startartprüfung</strong></summary>

```text
[ ] Internen Dienstnamen beziehungsweise launchd-Label ermittelt
[ ] Anzeigenamen und technischen Namen unterschieden
[ ] Richtigen Server und richtige Umgebung bestätigt
[ ] Aktuellen Dienststatus erfasst
[ ] Startart beziehungsweise Aktivierungszustand geprüft
[ ] Bedarfsgesteuerten Betrieb berücksichtigt
[ ] Deaktivierung oder Maskierung geprüft
[ ] Prozess-ID erfasst
[ ] Dienstkonto beziehungsweise Ausführungskontext geprüft
[ ] Programmpfad und Startargumente geprüft
[ ] Exitcode und dienstspezifischen Exitcode erfasst
[ ] Neustartzähler beziehungsweise wiederholte Starts geprüft
[ ] Abhängigkeiten aufgenommen
[ ] Ausgangszustand vor Änderungen dokumentiert
[ ] Noch keine ungeprüfte Zustandsänderung durchgeführt
[ ] Nächsten Diagnoseschritt festgelegt
```

</details>

---

**Bewertung des Ergebnisses**

| Ergebnis | Nächster Schritt |
|---|---|
| Dienst ist nicht registriert oder nicht auffindbar | Installation, Produktdokumentation und Zielsystem prüfen |
| Dienst ist deaktiviert oder maskiert | Grund der Deaktivierung und Änderungsverlauf klären |
| Dienst ist beendet, sollte aber laufen | Startfehler, Exitcode und Protokolle untersuchen |
| Dienst hängt im Übergangszustand | Prozess, Abhängigkeiten und Protokolle prüfen |
| Dienst startet und beendet sich wieder | Exitcode, Neustartregeln und Anwendungsprotokolle prüfen |
| Dienst läuft stabil | Prozess, Listener, Port und Anwendungsfunktion prüfen |
| Dienst läuft unter falschem Konto | Konfiguration und benötigte Berechtigungen untersuchen |
| Startart entspricht nicht dem Sollzustand | Sollkonfiguration und letzte Änderungen prüfen |
| Zustand ist unklar | Keine Änderung durchführen; weitere Beweise sammeln |

---

**Merksatz**

> **„Aktiviert“ beschreibt die Startkonfiguration. „Läuft“ beschreibt den aktuellen Zustand. „Funktioniert“ muss durch einen eigenen Anwendungstest bewiesen werden.**

---

**Weiterführende Quellen**

- [Microsoft Learn – Get-Service](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-service)
- [Microsoft Learn – Get-CimInstance](https://learn.microsoft.com/powershell/module/cimcmdlets/get-ciminstance)
- [Microsoft Learn – Win32_Service](https://learn.microsoft.com/windows/win32/cimwin32prov/win32-service)
- [Microsoft Learn – sc.exe query](https://learn.microsoft.com/de-de/windows-server/administration/windows-commands/sc-query)
- [Microsoft Learn – sc.exe qc](https://learn.microsoft.com/windows-server/administration/windows-commands/sc-qc)
- [systemd – systemctl](https://www.freedesktop.org/software/systemd/man/latest/systemctl.html)
- [systemd – systemd.service](https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html)
- [systemd – systemd.unit](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html)
- [Apple – launchctl-Handbuchseite](https://keith.github.io/xcode-man-pages/launchctl.1.html)
- [Apple – launchd.plist-Handbuchseite](https://keith.github.io/xcode-man-pages/launchd.plist.5.html)

# 4.3 Prozesse und Prozesszustände analysieren

Ein Betriebssystemdienst wird letztlich durch einen oder mehrere Prozesse ausgeführt. Auch wenn die Dienstverwaltung den Zustand „läuft“ meldet, kann der zugehörige Prozess blockiert sein, ungewöhnlich viele Ressourcen verbrauchen oder fortlaufend beendet und neu gestartet werden.

> **Grundsatz:**  
> Ein vorhandener Prozess beweist nur, dass eine Prozessinstanz existiert. Er beweist nicht, dass der Dienst Anfragen korrekt verarbeitet.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- einen Dienst seinem Prozess zuordnen können,
- PID und Elternprozess bestimmen können,
- Benutzerkonto, Startzeit und Befehlszeile prüfen können,
- CPU- und Speicherverbrauch richtig bewerten können,
- Prozesszustände unter Windows, Linux und macOS einordnen können,
- Zombies und blockierte Prozesse erkennen können,
- Prozessneustarts und wechselnde PIDs feststellen können,
- Threads, Handles und geöffnete Dateien prüfen können,
- Diagnoseinformationen vor einer Prozessbeendigung sichern können.

---

<details>
<summary><strong>1. Dienst, Prozess, Thread und PID unterscheiden</strong></summary>

| Begriff | Bedeutung |
|---|---|
| Dienst | Vom Betriebssystem verwaltete Hintergrundfunktion |
| Prozess | Laufende Instanz eines Programms |
| PID | Eindeutige Prozess-ID innerhalb des aktuell laufenden Systems |
| PPID | PID des Elternprozesses |
| Thread | Ausführungsstrang innerhalb eines Prozesses |
| Handle | Windows-Verweis auf eine verwendete Systemressource |
| Dateideskriptor | Unix-Verweis auf Datei, Socket, Pipe oder andere Ressource |
| Elternprozess | Prozess, der einen anderen Prozess erzeugt hat |
| Kindprozess | Von einem anderen Prozess erzeugter Prozess |
| Prozessbaum | Hierarchische Darstellung von Eltern- und Kindprozessen |

Ein Dienst kann:

- genau einen Prozess verwenden,
- mehrere Prozesse starten,
- Kindprozesse erzeugen,
- mehrere Dienste in einem gemeinsamen Prozess ausführen,
- bedarfsgesteuert ohne dauerhaften Prozess arbeiten,
- nach einem Absturz automatisch eine neue PID erhalten.

> Eine PID ist nicht dauerhaft. Nach dem Ende eines Prozesses kann dieselbe Nummer später einem anderen Prozess zugewiesen werden.

</details>

---

<details>
<summary><strong>2. Prozesse unter Windows suchen und anzeigen</strong></summary>

Die Platzhalter `<PROZESS>` und `<PID>` müssen ersetzt werden.

**Prozess nach Namen suchen:**

```powershell
[RO] Get-Process -Name "<PROZESS>" -ErrorAction SilentlyContinue
```

Die Dateiendung `.exe` wird bei `Get-Process -Name` normalerweise nicht angegeben.

**Prozess über die PID suchen:**

```powershell
[RO] Get-Process -Id <PID> -ErrorAction SilentlyContinue
```

**Ausgewählte Prozessinformationen anzeigen:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id,
                  ProcessName,
                  StartTime,
                  CPU,
                  WorkingSet64,
                  PrivateMemorySize64,
                  VirtualMemorySize64,
                  HandleCount,
                  Responding
```

**Alle Prozesse nach CPU-Zeit sortieren:**

```powershell
[RO] Get-Process |
    Sort-Object CPU -Descending |
    Select-Object -First 15 Id, ProcessName, CPU, WorkingSet64
```

**Alle Prozesse nach belegtem Arbeitsspeicher sortieren:**

```powershell
[RO] Get-Process |
    Sort-Object WorkingSet64 -Descending |
    Select-Object -First 15 Id, ProcessName, WorkingSet64, CPU
```

**Klassische Prozessübersicht:**

```powershell
[RO] tasklist
```

**Bestimmten Prozess mit `tasklist` suchen:**

```powershell
[RO] tasklist /FI "PID eq <PID>"
```

> Eigenschaften wie `StartTime` oder `Path` können bei geschützten Prozessen oder ohne ausreichende Rechte einen Zugriffsfehler verursachen.

</details>

---

<details>
<summary><strong>3. Dienst einem Windows-Prozess zuordnen</strong></summary>

**Dienstname, Status und PID ermitteln:**

```powershell
[RO] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name, DisplayName, State, StartName, ProcessId
```

**Alle laufenden Dienste mit ihrer PID anzeigen:**

```powershell
[RO] Get-CimInstance Win32_Service |
    Where-Object State -eq "Running" |
    Select-Object Name, DisplayName, ProcessId, StartName |
    Sort-Object ProcessId
```

**Alle Dienste innerhalb einer bestimmten PID suchen:**

```powershell
[RO] Get-CimInstance Win32_Service -Filter "ProcessId=<PID>" |
    Select-Object Name, DisplayName, State, StartName
```

**Erweiterte Dienstabfrage mit `sc.exe`:**

```powershell
[RO] sc.exe queryex "<DIENSTNAME>"
```

**Dienstinformationen mit Prozessinformationen verbinden:**

```powershell
[RO][SENS] $service = Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'"
Get-CimInstance Win32_Process -Filter "ProcessId=$($service.ProcessId)" |
    Select-Object ProcessId,
                  ParentProcessId,
                  Name,
                  ExecutablePath,
                  CommandLine
```

> Mehrere Windows-Dienste können sich einen gemeinsamen Hostprozess teilen. Das ist beispielsweise bei bestimmten `svchost.exe`-Instanzen üblich. Deshalb darf nicht allein anhand des Prozessnamens entschieden werden, welcher Dienst betroffen ist.

</details>

---

<details>
<summary><strong>4. Windows-Prozessdetails mit CIM prüfen</strong></summary>

**Prozessname, Elternprozess, Pfad und Befehlszeile anzeigen:**

```powershell
[RO][SENS] Get-CimInstance Win32_Process -Filter "ProcessId=<PID>" |
    Select-Object ProcessId,
                  ParentProcessId,
                  Name,
                  ExecutablePath,
                  CommandLine,
                  CreationDate
```

**Elternprozess ermitteln:**

```powershell
[RO] $process = Get-CimInstance Win32_Process -Filter "ProcessId=<PID>"
Get-CimInstance Win32_Process -Filter "ProcessId=$($process.ParentProcessId)" |
    Select-Object ProcessId, ParentProcessId, Name, CreationDate
```

**Direkte Kindprozesse anzeigen:**

```powershell
[RO][SENS] Get-CimInstance Win32_Process -Filter "ParentProcessId=<PID>" |
    Select-Object ProcessId, ParentProcessId, Name, CommandLine
```

**Anzahl der Threads und Handles prüfen:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id,
                  ProcessName,
                  HandleCount,
                  @{Name="ThreadCount";Expression={$_.Threads.Count}}
```

**Ausführungskonto des Prozesses abfragen:**

```powershell
[RO][PRIV] Invoke-CimMethod `
    -InputObject (Get-CimInstance Win32_Process -Filter "ProcessId=<PID>") `
    -MethodName GetOwner
```

> `[SENS]`: Befehlszeilen können interne Pfade, Benutzernamen, Serveradressen oder unsicher übergebene Zugangsdaten enthalten. Die Ausgabe darf nicht ungeprüft weitergegeben werden.

</details>

---

<details>
<summary><strong>5. Prozesse unter Linux suchen und anzeigen</strong></summary>

**Prozess nach Namen suchen:**

```bash
[RO] pgrep -a "<PROZESS>"
```

**Exakte Übereinstimmung des Prozessnamens verwenden:**

```bash
[RO] pgrep -x -a "<PROZESS>"
```

**Vollständige Befehlszeile durchsuchen:**

```bash
[RO][SENS] pgrep -f -a "<SUCHMUSTER>"
```

**Bestimmte PID untersuchen:**

```bash
[RO][SENS] ps -p <PID> \
  -o user,pid,ppid,lstart,etime,stat,%cpu,%mem,rss,vsz,cmd
```

**Alle Prozesse ausführlich anzeigen:**

```bash
[RO][SENS] ps -eo user,pid,ppid,lstart,etime,stat,%cpu,%mem,rss,vsz,cmd
```

**Nach CPU-Auslastung sortieren:**

```bash
[RO] ps -eo pid,ppid,user,stat,%cpu,%mem,etime,comm \
  --sort=-%cpu |
  head -n 16
```

**Nach residentem Speicher sortieren:**

```bash
[RO] ps -eo pid,ppid,user,stat,%cpu,%mem,rss,etime,comm \
  --sort=-rss |
  head -n 16
```

**Interaktive Prozessübersicht:**

```bash
[RO] top
```

Falls installiert:

```bash
[RO] htop
```

> `htop` gehört nicht auf jeder Linux-Distribution zur Standardinstallation.

</details>

---

<details>
<summary><strong>6. Linux-Prozessdetails über das proc-Dateisystem prüfen</strong></summary>

Linux stellt Prozessinformationen normalerweise unter `/proc/<PID>` bereit.

**Ausführbare Datei bestimmen:**

```bash
[RO][PRIV] sudo readlink -f "/proc/<PID>/exe"
```

**Arbeitsverzeichnis anzeigen:**

```bash
[RO][PRIV] sudo readlink -f "/proc/<PID>/cwd"
```

**Prozessstatus anzeigen:**

```bash
[RO][FILE][SENS] cat "/proc/<PID>/status"
```

**Befehlszeile lesbar darstellen:**

```bash
[RO][FILE][SENS] tr '\0' ' ' < "/proc/<PID>/cmdline"
```

**Umgebungsvariablen anzeigen:**

```bash
[RO][FILE][SENS][PRIV] sudo tr '\0' '\n' < "/proc/<PID>/environ"
```

**Grenzwerte des Prozesses anzeigen:**

```bash
[RO][FILE] cat "/proc/<PID>/limits"
```

**Eingehängte Ressourcen des Prozesses anzeigen:**

```bash
[RO][FILE][SENS] cat "/proc/<PID>/mountinfo"
```

**Anzahl geöffneter Dateideskriptoren ermitteln:**

```bash
[RO][PRIV] sudo find "/proc/<PID>/fd" -mindepth 1 -maxdepth 1 -printf '.' |
    wc -c
```

> `/proc/<PID>/environ` kann Kennwörter, Token oder andere geheime Werte enthalten. Diese Abfrage darf nur bei berechtigtem Diagnosebedarf erfolgen. Die Ausgabe gehört nicht ungefiltert in ein Ticket.

</details>

---

<details>
<summary><strong>7. systemd-Dienst einem Linux-Prozess zuordnen</strong></summary>

**Hauptprozess eines Dienstes anzeigen:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=MainPID,ControlPID,ExecMainPID,ExecMainStartTimestamp
```

**Prozessbaum der Unit im Status anzeigen:**

```bash
[RO] systemctl status "<DIENST>" --no-pager
```

**Prozesse innerhalb der Unit beziehungsweise Control Group anzeigen:**

```bash
[RO] systemd-cgls --unit "<DIENST>"
```

**Ressourcennutzung von Control Groups beobachten:**

```bash
[RO] systemd-cgtop
```

**Hauptprozess anschließend mit `ps` untersuchen:**

```bash
[RO][SENS] ps -p <PID> \
  -o user,pid,ppid,lstart,etime,stat,%cpu,%mem,rss,vsz,cmd
```

**Wichtig:**

- `MainPID=0` kann bedeuten, dass aktuell kein Hauptprozess vorhanden ist.
- Eine Unit kann mehrere Prozesse enthalten.
- Ein Kindprozess kann weiterlaufen, obwohl der ursprüngliche Startprozess bereits beendet wurde.
- Bei `Type=oneshot` kann eine erfolgreiche Unit aktiv sein, obwohl kein dauerhafter Prozess läuft.
- Der systemd-Status der gesamten Unit ist aussagekräftiger als die isolierte Betrachtung nur einer PID.

</details>

---

<details>
<summary><strong>8. Prozesse unter macOS suchen und anzeigen</strong></summary>

**Prozess nach Namen oder Befehlszeile suchen:**

```bash
[RO][SENS] pgrep -alf "<SUCHMUSTER>"
```

**Exakten Prozessnamen suchen:**

```bash
[RO] pgrep -x "<PROZESS>"
```

**Bestimmte PID ausführlich anzeigen:**

```bash
[RO][SENS] ps -p <PID> \
  -o user,pid,ppid,lstart,etime,state,%cpu,%mem,rss,vsz,command
```

**Alle Prozesse ausführlich anzeigen:**

```bash
[RO][SENS] ps -axo user,pid,ppid,lstart,etime,state,%cpu,%mem,rss,vsz,command
```

**Prozesse nach aktueller CPU-Nutzung sortiert anzeigen:**

```bash
[RO] ps -Arcwwxo pid,ppid,user,state,%cpu,%mem,rss,etime,command
```

**Prozesse nach Speicherverbrauch sortiert anzeigen:**

```bash
[RO] ps -Amcwwxo pid,ppid,user,state,%cpu,%mem,rss,etime,command
```

**Interaktive Prozessübersicht nach CPU-Nutzung:**

```bash
[RO] top -o cpu
```

**Drei Messungen für eine bestimmte PID ausgeben:**

```bash
[RO] top -l 3 -pid <PID> \
  -stats pid,command,cpu,mem,threads,state,time
```

> Bei `top -l` ist die erste CPU-Messung möglicherweise noch nicht aussagekräftig, weil für eine belastbare Prozentberechnung ein zeitlicher Vergleich benötigt wird.

</details>

---

<details>
<summary><strong>9. launchd-Dienst einem macOS-Prozess zuordnen</strong></summary>

**Systemweiten launchd-Dienst prüfen:**

```bash
[RO] launchctl print "system/<LABEL>"
```

**Benutzerbezogenen Dienst prüfen:**

```bash
[RO] launchctl print "gui/$(id -u)/<LABEL>"
```

In der Ausgabe sind insbesondere folgende Angaben relevant:

```text
state
pid
runs
last exit code
program
arguments
```

**Gefundene PID anschließend untersuchen:**

```bash
[RO][SENS] ps -p <PID> \
  -o user,pid,ppid,lstart,etime,state,%cpu,%mem,rss,vsz,command
```

**Direkte Kindprozesse einer PID anzeigen:**

```bash
[RO][SENS] pgrep -P <PID> -a
```

**Geöffnete Dateien und Netzwerkressourcen des Prozesses anzeigen:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -p <PID>
```

> Ein launchd-Job kann geladen und funktionsfähig sein, obwohl momentan keine PID angezeigt wird. Das ist bei bedarfsgesteuerten Diensten möglich.

</details>

---

<details>
<summary><strong>10. Wichtige Prozessfelder verstehen</strong></summary>

| Feld | Bedeutung | Diagnosewert |
|---|---|---|
| `PID` | Prozess-ID | Identifiziert die aktuelle Instanz |
| `PPID` | Elternprozess-ID | Zeigt den erzeugenden Prozess |
| `USER` | Ausführungskonto | Wichtig für Berechtigungen |
| `START` beziehungsweise `LSTART` | Startzeit | Hilft beim Erkennen von Neustarts |
| `ETIME` | Vergangene Zeit seit Prozessstart | Zeigt kurze oder lange Laufzeit |
| `STAT` beziehungsweise `STATE` | Prozesszustand | Erkennt Schlafen, Warten, Stopp oder Zombie |
| `%CPU` | CPU-Nutzung | Hinweis auf Last oder Endlosschleife |
| `%MEM` | Anteil am physischen Speicher | Grober Speichervergleich |
| `RSS` | Aktuell residenter physischer Speicher | Praktischer Speicherindikator |
| `VSZ` | Virtueller Adressraum | Nicht mit tatsächlich belegtem RAM gleichsetzen |
| `TIME` | Verbrauchte CPU-Zeit | Kumulierte Prozessorzeit |
| `CMD` beziehungsweise `COMMAND` | Programm und Argumente | Identifikation und Konfigurationsprüfung |
| `THREADS` | Anzahl der Threads | Hinweis auf Threadwachstum |
| `HandleCount` | Offene Windows-Handles | Hinweis auf Ressourcenleck |
| `FD` | Dateideskriptor | Geöffnete Ressource unter Unix-Systemen |

> Hoher virtueller Speicher bedeutet nicht automatisch, dass entsprechend viel physischer Arbeitsspeicher belegt ist.

</details>

---

<details>
<summary><strong>11. Linux-Prozesszustände interpretieren</strong></summary>

Der erste Buchstabe in der Spalte `STAT` beschreibt den grundlegenden Zustand.

| Zustand | Bedeutung | Bewertung |
|---|---|---|
| `R` | Laufend oder ausführungsbereit | Bei dauerhafter hoher CPU-Nutzung untersuchen |
| `S` | Unterbrechbarer Schlafzustand | Häufig normal; Prozess wartet auf ein Ereignis |
| `D` | Nicht unterbrechbarer Wartezustand | Häufig Warten auf Ein-/Ausgabe; dauerhaft auffällig |
| `T` | Gestoppt oder durch Debugger angehalten | Ursache des Stopps prüfen |
| `t` | Während Ablaufverfolgung gestoppt | Debugger oder Tracing prüfen |
| `Z` | Zombie | Prozess ist beendet, Elternprozess hat Status noch nicht abgeholt |
| `I` | Leerlaufender Kernel-Thread | Normaler Kernelzustand |
| `X` | Beendeter Prozess | Normalerweise nur sehr kurz sichtbar |

Weitere Zeichen können zusätzliche Eigenschaften angeben:

| Zeichen | Bedeutung |
|---|---|
| `<` | Höhere Priorität |
| `N` | Niedrigere Priorität |
| `L` | Speicherseiten sind gesperrt |
| `s` | Prozess ist Sitzungsleiter |
| `l` | Mehrere Threads |
| `+` | Vordergrund-Prozessgruppe |

**Wichtige Bewertung:**

- `S` ist bei Serverdiensten sehr häufig und normalerweise unauffällig.
- `R` ist nur zusammen mit Messdauer und CPU-Verbrauch zu bewerten.
- Ein kurzzeitiger `D`-Zustand kann normal sein.
- Ein dauerhaft im Zustand `D` verbleibender Prozess kann auf Datenträger-, Netzwerkdateisystem- oder Kernelprobleme hinweisen.
- Ein `Z`-Prozess verbraucht kaum Arbeitsspeicher, belegt aber weiterhin einen Eintrag in der Prozesstabelle.
- Ein Zombie wird durch den fehlerhaften oder nicht reagierenden Elternprozess bereinigt, nicht durch das Beenden des bereits beendeten Kindprozesses.

</details>

---

<details>
<summary><strong>12. macOS-Prozesszustände interpretieren</strong></summary>

macOS verwendet ebenfalls Zustandszeichen, deren genaue Kombination mehrere Eigenschaften enthalten kann.

| Zustand | Grundbedeutung |
|---|---|
| `R` | Laufend oder ausführungsbereit |
| `S` | Schlafend für weniger als ungefähr 20 Sekunden |
| `I` | Länger inaktiv beziehungsweise schlafend |
| `D` | Warten auf Datenträger- oder andere nicht unterbrechbare Ein-/Ausgabe |
| `T` | Angehalten |
| `Z` | Zombie |
| `U` | Nicht unterbrechbarer Wartezustand |
| `H` | Angehaltene Ausführung |
| `L` | Prozess besitzt gesperrte Speicherseiten |

Abhängig von der Ausgabe können zusätzliche Zeichen erscheinen. Deshalb sollte bei Unklarheiten die lokale Handbuchseite herangezogen werden:

```bash
[RO] man ps
```

> Prozesszustände dürfen nicht isoliert bewertet werden. Entscheidend ist, ob ein Zustand über einen längeren Messzeitraum bestehen bleibt und gleichzeitig eine Funktionsstörung vorliegt.

</details>

---

<details>
<summary><strong>13. CPU-Verbrauch richtig untersuchen</strong></summary>

Eine einzelne Momentaufnahme reicht häufig nicht aus. CPU-Nutzung sollte über mehrere Messpunkte beobachtet werden.

| Beobachtung | Mögliche Erklärung |
|---|---|
| Kurzer CPU-Ausschlag | Reguläre Verarbeitung einer Anfrage |
| Dauerhaft hohe CPU-Nutzung | Hohe Last, Schleife, Kompression, Verschlüsselung oder fehlerhafte Verarbeitung |
| Niedrige CPU-Nutzung trotz Störung | Warten auf Netzwerk, Datenträger, Sperre oder Backend |
| Hohe gesamte CPU-Last, Dienst selbst unauffällig | Konkurrenz durch andere Prozesse |
| Ein Prozess über 100 Prozent unter Unix | Nutzung mehrerer CPU-Kerne möglich |
| Steigende kumulierte CPU-Zeit | Prozess verbraucht weiterhin Prozessorzeit |

**Windows – zwei Messpunkte vergleichen:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id, ProcessName, CPU, StartTime
```

Die Eigenschaft `CPU` enthält die bisher vom Prozess verbrauchte Prozessorzeit in Sekunden und nicht die momentane prozentuale Auslastung.

**Linux – Prozess beobachten:**

```bash
[RO] top -p <PID>
```

**macOS – mehrere Messpunkte erfassen:**

```bash
[RO] top -l 5 -s 2 -pid <PID> \
  -stats pid,command,cpu,mem,threads,state,time
```

> Ein Prozess mit niedriger CPU-Nutzung kann trotzdem blockiert sein. Warten auf Ein-/Ausgabe benötigt häufig kaum Prozessorzeit.

</details>

---

<details>
<summary><strong>14. Speicherverbrauch richtig untersuchen</strong></summary>

| Messwert | Bedeutung |
|---|---|
| Working Set | Derzeit im physischen Speicher befindliche Speicherseiten unter Windows |
| Private Memory | Speicher, der dem Prozess privat zugeordnet ist |
| RSS | Residenter physischer Speicher unter Unix-Systemen |
| VSZ | Gesamter virtueller Adressraum |
| Swap | Auf Auslagerungsspeicher verschobene Daten |
| Page Fault | Zugriff auf eine nicht aktuell im Working Set befindliche Speicherseite |

**Windows:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id,
                  ProcessName,
                  WorkingSet64,
                  PrivateMemorySize64,
                  VirtualMemorySize64,
                  PagedMemorySize64
```

**Linux:**

```bash
[RO] ps -p <PID> -o pid,etime,%mem,rss,vsz,stat,comm
```

**macOS:**

```bash
[RO] ps -p <PID> -o pid,etime,%mem,rss,vsz,state,command
```

**Hinweise auf ein mögliches Speicherleck:**

- Speicherverbrauch steigt über längere Zeit kontinuierlich,
- der Verbrauch sinkt nach abgeschlossenen Aufgaben nicht wieder,
- Auslagerungsaktivität nimmt zu,
- der Prozess wird wegen Speichermangels beendet,
- die Dienstfunktion wird mit zunehmender Laufzeit langsamer,
- ein Neustart reduziert den Speicherverbrauch nur vorübergehend.

> Ein Speicherleck lässt sich nicht durch einen einzelnen hohen Messwert beweisen. Dafür ist eine Zeitreihe unter vergleichbarer Last erforderlich.

</details>

---

<details>
<summary><strong>15. Threads, Handles und Dateideskriptoren prüfen</strong></summary>

Ein Prozess kann funktionsunfähig werden, obwohl er weiterhin läuft. Ursachen können erschöpfte Handles, Dateideskriptoren oder ungewöhnlich viele Threads sein.

| Ressource | Windows | Linux | macOS |
|---|---|---|---|
| Threads | `Get-Process` | `ps -L` | `ps -M` |
| Handles | `HandleCount` | Nicht gleichbedeutend | Nicht gleichbedeutend |
| Dateideskriptoren | Über spezialisierte Werkzeuge | `/proc/<PID>/fd` oder `lsof` | `lsof` |
| Geöffnete Dateien | Sysinternals-Werkzeuge oder Prozesswerkzeuge | `lsof -p` | `lsof -p` |

**Windows – Thread- und Handleanzahl:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id,
                  ProcessName,
                  HandleCount,
                  @{Name="ThreadCount";Expression={$_.Threads.Count}}
```

**Linux – Threads anzeigen:**

```bash
[RO] ps -L -p <PID> -o pid,tid,psr,stat,%cpu,comm
```

**Linux – geöffnete Ressourcen anzeigen:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -p <PID>
```

**macOS – Threads anzeigen:**

```bash
[RO] ps -M -p <PID>
```

**macOS – geöffnete Ressourcen anzeigen:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -p <PID>
```

Verdächtig ist nicht allein eine hohe Anzahl, sondern insbesondere:

- kontinuierliches Wachstum,
- Erreichen eines konfigurierten Grenzwertes,
- Meldungen wie „too many open files“,
- fehlgeschlagene neue Verbindungen,
- steigende Threadzahl ohne entsprechende Last,
- Handles oder Dateien werden nach Aufgaben nicht freigegeben.

</details>

---

<details>
<summary><strong>16. Wechselnde PIDs und Neustartschleifen erkennen</strong></summary>

Eine neue PID kann bedeuten, dass ein Prozess neu gestartet wurde.

**Windows – wiederholte Dienstabfrage:**

```powershell
[RO] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name, State, ProcessId, ExitCode
```

**Linux – Neustartzähler und Hauptprozess:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=MainPID,NRestarts,ActiveEnterTimestamp,ExecMainStartTimestamp,Result
```

**macOS – Anzahl der Starts und aktuelle PID:**

```bash
[RO] launchctl print "system/<LABEL>"
```

**Anzeichen einer Neustartschleife:**

- PID wechselt innerhalb kurzer Zeit,
- Prozesslaufzeit bleibt sehr kurz,
- systemd-Eigenschaft `NRestarts` steigt,
- launchd-Ausgabe zeigt eine steigende Anzahl unter `runs`,
- Windows-Ereignisprotokoll enthält wiederholte Start- und Stoppmeldungen,
- Anwendung protokolliert wiederholt denselben Startfehler,
- Dienststatus wechselt zwischen `Starting`, `Running` und `Stopped`,
- ein Überwachungswerkzeug startet den Prozess fortlaufend neu.

> Ein automatisch neu gestarteter Dienst kann nach außen zeitweise erreichbar wirken. Die wechselnden PIDs und kurzen Unterbrechungen sind dann wichtige Diagnosehinweise.

</details>

---

<details>
<summary><strong>17. Nicht reagierenden Prozess richtig bewerten</strong></summary>

Ein Prozess kann:

- CPU-intensiv arbeiten,
- auf Datenträgerzugriff warten,
- auf eine Netzwerkantwort warten,
- auf eine Datenbanksperre warten,
- auf einen anderen Thread warten,
- durch einen Deadlock blockiert sein,
- auf Benutzereingabe warten,
- zwar reagieren, aber extrem langsam sein.

**Windows-Eigenschaft `Responding`:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id, ProcessName, Responding
```

Diese Eigenschaft ist hauptsächlich bei Prozessen mit grafischer Benutzeroberfläche hilfreich. Sie ist kein zuverlässiger allgemeiner Funktionstest für Serverdienste.

**Bessere Bewertung eines Serverprozesses:**

1. Bleibt die PID stabil?
2. Verändert sich die CPU-Zeit?
3. Lauscht der Prozess auf dem erwarteten Port?
4. Nimmt er neue Verbindungen an?
5. Reagiert das Anwendungsprotokoll?
6. Gibt es blockierte Ein-/Ausgabe?
7. Steigt die Anzahl offener Verbindungen oder Dateien?
8. Zeigen Protokolle Zeitüberschreitungen oder Sperren?
9. Funktionieren abhängige Systeme?
10. Reagiert der Prozess auf einen kontrollierten Diagnosetest?

> „Läuft“ und „reagiert“ sind unterschiedliche Zustände.

</details>

---

<details>
<summary><strong>18. Prozess beenden – nur als kontrollierte Maßnahme</strong></summary>

Die folgenden Befehle verändern den Systemzustand und können Datenverlust oder Dienstunterbrechungen verursachen.

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Reguläre Beendigung anfordern | `[CHANGE][DISRUPT] Stop-Process -Id <PID>` | `[CHANGE][DISRUPT] kill -TERM <PID>` | `[CHANGE][DISRUPT] kill -TERM <PID>` |
| Beendigung erzwingen | `[CHANGE][DISRUPT][PRIV] Stop-Process -Id <PID> -Force` | `[CHANGE][DISRUPT][PRIV] sudo kill -KILL <PID>` | `[CHANGE][DISRUPT][PRIV] sudo kill -KILL <PID>` |

Vorher prüfen:

```text
[ ] PID unmittelbar vor der Maßnahme erneut verifiziert
[ ] Prozessname und Dienstzuordnung bestätigt
[ ] Aktive Benutzer und Verbindungen geprüft
[ ] Laufende Schreibvorgänge und Transaktionen berücksichtigt
[ ] Prozess- und Dienstprotokolle gesichert
[ ] Abhängige Dienste geprüft
[ ] Cluster- oder Failover-Verhalten berücksichtigt
[ ] Automatische Neustartregel geprüft
[ ] Betriebliche Freigabe vorhanden
[ ] Funktionstest nach der Maßnahme vorbereitet
```

**Wichtige Unterschiede:**

- `SIGTERM` gibt einem Unix-Prozess die Möglichkeit, kontrolliert zu beenden.
- `SIGKILL` kann nicht vom Prozess behandelt oder abgefangen werden.
- `Stop-Process -Force` erzwingt die Beendigung unter Windows.
- Wird nur der Prozess beendet, kann die Dienstverwaltung ihn automatisch erneut starten.
- Bei verwalteten Diensten sollte grundsätzlich die jeweilige Dienstverwaltung verwendet werden.
- Eine erzwungene Beendigung ist kein Ersatz für eine Ursachenanalyse.

> Niemals eine alte, zuvor notierte PID ungeprüft verwenden. Die PID könnte inzwischen einem anderen Prozess gehören.

</details>

---

<details>
<summary><strong>19. Typische Fehlinterpretationen</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „Die PID existiert, also funktioniert der Dienst.“ | Nur die Prozessinstanz wurde nachgewiesen |
| „Der Prozess verwendet wenig CPU, also ist er gesund.“ | Er kann auf Ein-/Ausgabe oder eine Sperre warten |
| „Hohe CPU-Nutzung ist immer ein Fehler.“ | Sie kann durch reguläre Last entstehen |
| „Hoher virtueller Speicher ist vollständig belegter RAM.“ | Virtueller Adressraum und residenter Speicher unterscheiden sich |
| „Ein Zombie verbraucht sehr viel Arbeitsspeicher.“ | Er belegt hauptsächlich einen Prozesslisteneintrag |
| „Der Zombie muss mit `kill` beendet werden.“ | Der Prozess ist bereits beendet; der Elternprozess muss seinen Status abholen |
| „Eine neue PID ist unproblematisch.“ | Sie kann einen Absturz und automatischen Neustart anzeigen |
| „Der Prozessname identifiziert den Dienst eindeutig.“ | Mehrere Dienste können denselben Prozessnamen verwenden |
| „`Responding=True` beweist die Serverfunktion.“ | Es ist kein vollständiger Anwendungstest |
| „SIGKILL ist schneller und deshalb besser.“ | Es verhindert eine kontrollierte Bereinigung und erhöht das Risiko |

</details>

---

<details>
<summary><strong>20. Checkliste zur Prozessanalyse</strong></summary>

```text
[ ] Dienst dem richtigen Prozess zugeordnet
[ ] PID unmittelbar aktuell ermittelt
[ ] Prozessname geprüft
[ ] Elternprozess und Kindprozesse geprüft
[ ] Ausführungskonto geprüft
[ ] Programmpfad und Befehlszeile geprüft
[ ] Startzeit und bisherige Laufzeit geprüft
[ ] Prozesszustand geprüft
[ ] CPU über mehrere Messpunkte beobachtet
[ ] Speicherverbrauch über einen Zeitraum bewertet
[ ] Threadanzahl geprüft
[ ] Handles beziehungsweise Dateideskriptoren geprüft
[ ] Geöffnete Dateien und Sockets bei Bedarf geprüft
[ ] Wechselnde PID ausgeschlossen oder dokumentiert
[ ] Automatische Neustarts geprüft
[ ] Exitcode und Protokolle gesichert
[ ] Noch keine ungeprüfte Prozessbeendigung durchgeführt
[ ] Nächsten Diagnoseschritt festgelegt
```

</details>

---

**Bewertung des Ergebnisses**

| Ergebnis | Nächster Schritt |
|---|---|
| Kein Prozess vorhanden, Dienst sollte laufen | Dienststartfehler und Protokolle prüfen |
| Prozess wird fortlaufend neu gestartet | Exitcode, Neustartregel und Startprotokoll untersuchen |
| Prozess läuft stabil | Listener, Ports und Anwendungsfunktion prüfen |
| Prozess verwendet dauerhaft viel CPU | Threads, Anfragen, Schleifen und Last untersuchen |
| Speicherverbrauch steigt kontinuierlich | Zeitreihe, Grenzwerte und mögliche Speicherlecks untersuchen |
| Prozess verbleibt in einem Wartezustand | Datenträger, Netzwerk, Sperren und Backends prüfen |
| Zombieprozesse sammeln sich | Elternprozess und dessen Fehlerbehandlung untersuchen |
| Handle- oder Dateideskriptoranzahl steigt | Ressourcenleck und Grenzwerte untersuchen |
| Falsches Ausführungskonto | Dienstkonfiguration und Berechtigungen prüfen |
| Unerwarteter Elternprozess | Startweg, Überwachung, Wrapper oder Sicherheitsvorfall untersuchen |

---

**Merksatz**

> **Der Dienststatus zeigt die Sicht der Dienstverwaltung. Die Prozessanalyse zeigt, was die ausführende Instanz tatsächlich tut – oder worauf sie wartet.**

---

**Weiterführende Quellen**

- [Microsoft Learn – Get-Process](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-process)
- [Microsoft Learn – Win32_Process](https://learn.microsoft.com/windows/win32/cimwin32prov/win32-process)
- [Microsoft Learn – Win32_Service](https://learn.microsoft.com/windows/win32/cimwin32prov/win32-service)
- [Microsoft Learn – tasklist](https://learn.microsoft.com/windows-server/administration/windows-commands/tasklist)
- [Linux-Handbuch – ps](https://man7.org/linux/man-pages/man1/ps.1.html)
- [Linux-Handbuch – proc](https://man7.org/linux/man-pages/man5/proc.5.html)
- [Linux-Handbuch – pgrep](https://man7.org/linux/man-pages/man1/pgrep.1.html)
- [systemd – systemctl](https://www.freedesktop.org/software/systemd/man/latest/systemctl.html)
- [systemd – systemd-cgls](https://www.freedesktop.org/software/systemd/man/latest/systemd-cgls.html)
- [Apple – ps-Handbuchseite](https://keith.github.io/xcode-man-pages/ps.1.html)
- [Apple – pgrep-Handbuchseite](https://keith.github.io/xcode-man-pages/pkill.1.html)
- [Apple – top-Handbuchseite](https://keith.github.io/xcode-man-pages/top.1.html)
- [Apple – Aktivitätsanzeige – Benutzerhandbuch](https://support.apple.com/de-de/guide/activity-monitor/welcome/mac)

# 4.4 Listener, Ports und Bindungsadressen prüfen

**4.4 Listener, Ports und Bindungsadressen prüfen**

Ein laufender Dienstprozess ist nur dann über das Netzwerk erreichbar, wenn er einen passenden Socket geöffnet und an die erwartete lokale Adresse sowie den vorgesehenen Port gebunden hat.

> **Grundsatz:**  
> Dienststatus, Prozess, Listener und erfolgreiche Anwendungsantwort sind vier getrennte Nachweise.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- TCP-Listener und UDP-Endpunkte anzeigen können,
- einen Port dem verantwortlichen Prozess zuordnen können,
- Bindungsadressen richtig interpretieren können,
- zwischen Loopback-, Einzeladress- und Wildcard-Bindung unterscheiden können,
- IPv4- und IPv6-Listener getrennt prüfen können,
- lokale und entfernte Porttests durchführen können,
- Portkonflikte erkennen können,
- TCP-Verbindungszustände einordnen können,
- zwischen „Port geschlossen“, „gefiltert“ und „Anwendung fehlerhaft“ unterscheiden können,
- Listener prüfen, ohne unnötig die Dienstkonfiguration zu verändern.

---

<details>
<summary><strong>1. Socket, Listener, Port und Verbindung unterscheiden</strong></summary>

| Begriff | Bedeutung |
|---|---|
| Socket | Betriebssystemobjekt für eine Kommunikationsverbindung oder einen Endpunkt |
| Lokale Adresse | IP-Adresse der lokalen Netzwerkschnittstelle |
| Lokaler Port | Portnummer auf dem untersuchten System |
| Remoteadresse | IP-Adresse der Gegenstelle |
| Remoteport | Portnummer der Gegenstelle |
| TCP-Listener | Passiver TCP-Socket, der neue Verbindungen annehmen kann |
| UDP-Endpunkt | Gebundener UDP-Socket; UDP besitzt keinen TCP-ähnlichen `LISTEN`-Zustand |
| Bindung | Zuordnung eines Sockets zu lokaler Adresse und Port |
| Wildcard-Bindung | Bindung an alle passenden lokalen Adressen |
| Loopback-Bindung | Zugriff nur über die lokale Loopback-Schnittstelle |
| Established | Vollständig aufgebaute TCP-Verbindung |

**Beispiel einer TCP-Verbindung:**

```text
Client:  192.0.2.50:53124
Server:  192.0.2.20:443
```

Dabei ist `53124` normalerweise ein temporärer Clientport und `443` der bekannte Serverport.

</details>

---

<details>
<summary><strong>2. Erwarteten Netzwerkendpunkt vor der Prüfung festlegen</strong></summary>

Vor der Listenerprüfung müssen folgende Sollwerte bekannt sein:

| Eigenschaft | Beispiel |
|---|---|
| Protokoll | TCP |
| Port | 443 |
| IP-Version | IPv4 und IPv6 |
| Erwartete Bindungsadresse | `192.0.2.20` |
| Erwarteter Prozess | Webserverprozess |
| Erwarteter Dienst | Interner Webdienst |
| Erlaubte Quellnetze | Unternehmens-LAN und VPN |
| Verschlüsselung | TLS |
| Anwendungsprotokoll | HTTPS |
| Zugriffspfad | Direkt, über Proxy oder Loadbalancer |

**Unzureichende Prüffrage:**

> „Ist Port 443 offen?“

**Bessere Prüffragen:**

- Lauscht der erwartete Prozess auf TCP-Port 443?
- Lauscht er auf der richtigen IPv4- oder IPv6-Adresse?
- Ist der Port lokal erreichbar?
- Ist er von einem vorgesehenen Clientnetz erreichbar?
- Antwortet dort tatsächlich das erwartete Anwendungsprotokoll?
- Wird der Zugriff durch einen Proxy oder Loadbalancer vermittelt?

</details>

---

<details>
<summary><strong>3. Bindungsadressen richtig interpretieren</strong></summary>

| Bindungsadresse | Typische Bedeutung |
|---|---|
| `127.0.0.1` | Nur lokale IPv4-Verbindungen |
| `::1` | Nur lokale IPv6-Verbindungen |
| `0.0.0.0` | Alle lokalen IPv4-Adressen |
| `::` beziehungsweise `[::]` | IPv6-Wildcard; mögliche IPv4-Mitbenutzung ist system- und socketabhängig |
| Bestimmte IPv4-Adresse | Nur diese lokale IPv4-Adresse |
| Bestimmte IPv6-Adresse | Nur diese lokale IPv6-Adresse |

**Beispiel:**

Ein Server besitzt folgende Adressen:

```text
127.0.0.1
192.0.2.20
198.51.100.20
```

Der Dienst bindet sich an:

```text
127.0.0.1:8080
```

Dann ist der Dienst normalerweise nicht direkt über `192.0.2.20:8080` oder `198.51.100.20:8080` erreichbar.

Bindet er sich an:

```text
0.0.0.0:8080
```

nimmt er grundsätzlich auf allen lokalen IPv4-Adressen Verbindungen an. Firewall- und Routingregeln gelten zusätzlich.

> Eine Wildcard-Bindung bedeutet nicht, dass der Port aus jedem Netzwerk erreichbar ist. Paketfilter, Routing, NAT, Sicherheitsgruppen und vorgeschaltete Systeme können den Zugriff weiterhin verhindern.

</details>

---

<details>
<summary><strong>4. TCP-Listener unter Windows anzeigen</strong></summary>

**Alle TCP-Listener anzeigen:**

```powershell
[RO] Get-NetTCPConnection -State Listen |
    Sort-Object LocalPort, LocalAddress
```

**Wichtige Felder auswählen:**

```powershell
[RO] Get-NetTCPConnection -State Listen |
    Select-Object LocalAddress, LocalPort, State, OwningProcess |
    Sort-Object LocalPort, LocalAddress
```

**Bestimmten TCP-Port prüfen:**

```powershell
[RO] Get-NetTCPConnection `
    -State Listen `
    -LocalPort <PORT> `
    -ErrorAction SilentlyContinue
```

**Bestimmte lokale Adresse und Port prüfen:**

```powershell
[RO] Get-NetTCPConnection `
    -State Listen `
    -LocalAddress "<IP-ADRESSE>" `
    -LocalPort <PORT> `
    -ErrorAction SilentlyContinue
```

**Klassische Alternative:**

```powershell
[RO] netstat -ano -p tcp
```

**Nur TCP-Listener mit `netstat`:**

```powershell
[RO] netstat -ano -p tcp |
    Select-String "LISTENING"
```

> `Get-NetTCPConnection` liefert strukturierte PowerShell-Objekte und ist deshalb für gezielte Filterungen besser geeignet als das Verarbeiten formatierter `netstat`-Ausgaben.

</details>

---

<details>
<summary><strong>5. UDP-Endpunkte unter Windows anzeigen</strong></summary>

UDP besitzt keinen Verbindungszustand `Listen`. Stattdessen werden gebundene UDP-Endpunkte angezeigt.

**Alle UDP-Endpunkte anzeigen:**

```powershell
[RO] Get-NetUDPEndpoint |
    Select-Object LocalAddress, LocalPort, OwningProcess |
    Sort-Object LocalPort, LocalAddress
```

**Bestimmten UDP-Port prüfen:**

```powershell
[RO] Get-NetUDPEndpoint `
    -LocalPort <PORT> `
    -ErrorAction SilentlyContinue
```

**Klassische Alternative:**

```powershell
[RO] netstat -ano -p udp
```

**Wichtig:**

- Das Vorhandensein eines UDP-Endpunkts zeigt nur eine lokale Bindung.
- UDP verwendet keinen TCP-Handshake.
- Ein UDP-Porttest kann deshalb nicht so eindeutig wie ein TCP-Verbindungstest bewertet werden.
- Eine fehlende UDP-Antwort kann normal sein, wenn die Testanfrage nicht dem erwarteten Anwendungsprotokoll entspricht.

</details>

---

<details>
<summary><strong>6. Windows-Port dem verantwortlichen Prozess zuordnen</strong></summary>

**TCP-Port und Prozess-ID ermitteln:**

```powershell
[RO] Get-NetTCPConnection `
    -State Listen `
    -LocalPort <PORT> `
    -ErrorAction SilentlyContinue |
    Select-Object LocalAddress, LocalPort, OwningProcess
```

**Zugehörigen Prozess anzeigen:**

```powershell
[RO] $connection = Get-NetTCPConnection `
    -State Listen `
    -LocalPort <PORT> `
    -ErrorAction SilentlyContinue

$connection |
    ForEach-Object {
        Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
    } |
    Select-Object Id, ProcessName, StartTime
```

**Prozess und Dienst über eine gefundene PID zuordnen:**

```powershell
[RO] Get-CimInstance Win32_Service -Filter "ProcessId=<PID>" |
    Select-Object Name, DisplayName, State, StartName
```

**Alle TCP-Listener zusammen mit Prozessnamen anzeigen:**

```powershell
[RO] Get-NetTCPConnection -State Listen |
    ForEach-Object {
        $process = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue

        [PSCustomObject]@{
            LocalAddress = $_.LocalAddress
            LocalPort    = $_.LocalPort
            PID          = $_.OwningProcess
            ProcessName  = $process.ProcessName
        }
    } |
    Sort-Object LocalPort, LocalAddress
```

> Mehrere Listener können dieselbe PID verwenden. Ebenso kann ein Prozess auf mehreren Adressen und Ports lauschen.

</details>

---

<details>
<summary><strong>7. Listener unter Linux mit ss anzeigen</strong></summary>

`ss` ist auf modernen Linux-Systemen das bevorzugte Werkzeug für Socketinformationen.

**Alle lauschenden TCP-Sockets numerisch anzeigen:**

```bash
[RO] ss -lnt
```

**TCP-Listener einschließlich Prozessinformationen anzeigen:**

```bash
[RO][PRIV] sudo ss -lntp
```

**Gebundene UDP-Sockets anzeigen:**

```bash
[RO] ss -lnu
```

**UDP-Sockets einschließlich Prozessinformationen anzeigen:**

```bash
[RO][PRIV] sudo ss -lnup
```

**TCP- und UDP-Sockets gemeinsam anzeigen:**

```bash
[RO][PRIV] sudo ss -lntup
```

Bedeutung wichtiger Optionen:

| Option | Bedeutung |
|---|---|
| `-l` | Nur lauschende beziehungsweise unverbundene Server-Sockets |
| `-n` | Adressen und Ports numerisch ausgeben |
| `-t` | TCP-Sockets |
| `-u` | UDP-Sockets |
| `-p` | Zugehörige Prozesse anzeigen |
| `-4` | Nur IPv4 |
| `-6` | Nur IPv6 |

**Nur IPv4-TCP-Listener:**

```bash
[RO] ss -4 -lnt
```

**Nur IPv6-TCP-Listener:**

```bash
[RO] ss -6 -lnt
```

> Ohne ausreichende Berechtigungen können Prozessname und PID in der Ausgabe fehlen.

</details>

---

<details>
<summary><strong>8. Bestimmten Port oder Prozess unter Linux prüfen</strong></summary>

**Bestimmten TCP-Listener prüfen:**

```bash
[RO][PRIV] sudo ss -lntp "sport = :<PORT>"
```

**Bestimmten UDP-Port prüfen:**

```bash
[RO][PRIV] sudo ss -lnup "sport = :<PORT>"
```

**Offene Netzwerkressourcen einer PID anzeigen:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -a -p <PID> -i
```

**TCP-Listener einer PID anzeigen:**

```bash
[RO][SENS][PRIV] sudo lsof \
    -nP \
    -a \
    -p <PID> \
    -iTCP \
    -sTCP:LISTEN
```

**Bestimmten TCP-Port mit `lsof` prüfen:**

```bash
[RO][PRIV] sudo lsof -nP -iTCP:<PORT> -sTCP:LISTEN
```

**Bestimmten UDP-Port mit `lsof` prüfen:**

```bash
[RO][PRIV] sudo lsof -nP -iUDP:<PORT>
```

> `lsof` ist nicht auf jeder minimalen Linux-Installation vorhanden. In diesem Fall kann zunächst `ss` verwendet werden.

</details>

---

<details>
<summary><strong>9. Listener unter macOS anzeigen</strong></summary>

**Alle TCP-Listener anzeigen:**

```bash
[RO][PRIV] sudo lsof -nP -iTCP -sTCP:LISTEN
```

**Bestimmten TCP-Port prüfen:**

```bash
[RO][PRIV] sudo lsof -nP -iTCP:<PORT> -sTCP:LISTEN
```

**Gebundene UDP-Sockets anzeigen:**

```bash
[RO][PRIV] sudo lsof -nP -iUDP
```

**Bestimmten UDP-Port prüfen:**

```bash
[RO][PRIV] sudo lsof -nP -iUDP:<PORT>
```

**Netzwerksockets einer bestimmten PID anzeigen:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -a -p <PID> -i
```

**TCP-Verbindungen und Listener mit `netstat` anzeigen:**

```bash
[RO] netstat -anv -p tcp
```

**UDP-Sockets mit `netstat` anzeigen:**

```bash
[RO] netstat -anv -p udp
```

> Unter macOS ist `lsof` für die Zuordnung von Netzwerkendpunkten zu Prozessen meist übersichtlicher als `netstat`.

</details>

---

<details>
<summary><strong>10. Ausgabe von ss, lsof und netstat lesen</strong></summary>

Beispiel eines TCP-Listeners:

```text
LISTEN  0  128  0.0.0.0:443  0.0.0.0:*
```

Interpretation:

| Feld | Bedeutung |
|---|---|
| `LISTEN` | Socket nimmt neue TCP-Verbindungen an |
| `0.0.0.0:443` | Bindung an TCP-Port 443 auf allen lokalen IPv4-Adressen |
| `0.0.0.0:*` | Noch keine bestimmte entfernte Gegenstelle |
| `0` | Je nach Werkzeug aktueller Warteschlangenwert |
| `128` | Je nach Werkzeug Warteschlangen- oder Grenzwert |

Beispiel einer aufgebauten Verbindung:

```text
192.0.2.20:443  192.0.2.50:53124  ESTABLISHED
```

Interpretation:

```text
Lokaler Serverendpunkt:  192.0.2.20:443
Entfernter Client:       192.0.2.50:53124
Zustand:                 Verbindung aufgebaut
```

> Bei der Auswertung muss zuerst bestimmt werden, welches System Client und welches System Server ist. Ein hoher temporärer Port gehört häufig zum Client.

</details>

---

<details>
<summary><strong>11. IPv4 und IPv6 getrennt prüfen</strong></summary>

Ein Dienst kann:

- nur auf IPv4 lauschen,
- nur auf IPv6 lauschen,
- getrennte IPv4- und IPv6-Sockets verwenden,
- einen IPv6-Wildcard-Socket verwenden,
- abhängig vom Betriebssystem IPv4-Verbindungen über einen IPv6-Socket annehmen.

**Windows – IPv4-Listener eines Ports:**

```powershell
[RO] Get-NetTCPConnection -State Listen -LocalPort <PORT> |
    Where-Object LocalAddress -NotLike "*:*"
```

**Windows – IPv6-Listener eines Ports:**

```powershell
[RO] Get-NetTCPConnection -State Listen -LocalPort <PORT> |
    Where-Object LocalAddress -Like "*:*"
```

**Linux – IPv4 prüfen:**

```bash
[RO][PRIV] sudo ss -4 -lntp "sport = :<PORT>"
```

**Linux – IPv6 prüfen:**

```bash
[RO][PRIV] sudo ss -6 -lntp "sport = :<PORT>"
```

**macOS – IPv4 prüfen:**

```bash
[RO][PRIV] sudo lsof -nP -i4TCP:<PORT> -sTCP:LISTEN
```

**macOS – IPv6 prüfen:**

```bash
[RO][PRIV] sudo lsof -nP -i6TCP:<PORT> -sTCP:LISTEN
```

> Aus einer Bindung an `[::]:<PORT>` darf nicht ungeprüft geschlossen werden, dass IPv4 ebenfalls funktioniert. IPv4 und IPv6 müssen praktisch getrennt getestet werden.

</details>

---

<details>
<summary><strong>12. Lokalen TCP-Porttest durchführen</strong></summary>

Ein lokaler Test hilft zu unterscheiden, ob der Dienst grundsätzlich Verbindungen annimmt oder ob nur der externe Zugriff fehlschlägt.

**Windows – IPv4-Loopback testen:**

```powershell
[TEST] Test-NetConnection 127.0.0.1 -Port <PORT>
```

**Windows – konkrete Serveradresse testen:**

```powershell
[TEST] Test-NetConnection <SERVER-IP> -Port <PORT>
```

**Linux – IPv4-Loopback testen:**

```bash
[TEST] nc -vz -w 3 127.0.0.1 <PORT>
```

**Linux – konkrete Serveradresse testen:**

```bash
[TEST] nc -vz -w 3 <SERVER-IP> <PORT>
```

**macOS – IPv4-Loopback testen:**

```bash
[TEST] nc -vz -w 3 127.0.0.1 <PORT>
```

**macOS – konkrete Serveradresse testen:**

```bash
[TEST] nc -vz -w 3 <SERVER-IP> <PORT>
```

**IPv6-Loopback unter Linux oder macOS testen:**

```bash
[TEST] nc -6 -vz -w 3 ::1 <PORT>
```

**Interpretation:**

| Loopback | Server-IP | Mögliche Bewertung |
|---|---|---|
| Erfolgreich | Erfolgreich | Lokaler Listener grundsätzlich erreichbar |
| Erfolgreich | Fehlgeschlagen | Falsche Bindung oder lokaler Paketfilter möglich |
| Fehlgeschlagen | Erfolgreich | Dienst lauscht möglicherweise nur auf einer konkreten Adresse |
| Fehlgeschlagen | Fehlgeschlagen | Kein Listener, falscher Port oder Paketfilter |
| Erfolgreich | Extern fehlgeschlagen | Externe Firewall, Routing oder Netzpfad untersuchen |

> Ein erfolgreicher TCP-Porttest beweist nur, dass ein TCP-Verbindungsaufbau möglich war. Er beweist nicht, dass die Anwendung fachlich korrekt antwortet.

</details>

---

<details>
<summary><strong>13. TCP-Port von einem entfernten Client testen</strong></summary>

Der Test sollte aus dem tatsächlich betroffenen Netzwerk oder von einem vergleichbaren Client erfolgen.

| Betriebssystem | Befehl |
|---|---|
| Windows | `[TEST] Test-NetConnection <SERVER> -Port <PORT>` |
| Linux | `[TEST] nc -vz -w 3 <SERVER> <PORT>` |
| macOS | `[TEST] nc -vz -w 3 <SERVER> <PORT>` |

**Windows mit ausführlicher Ausgabe:**

```powershell
[TEST] Test-NetConnection <SERVER> -Port <PORT> -InformationLevel Detailed
```

Wichtige Ausgabe:

```text
ComputerName
RemoteAddress
RemotePort
InterfaceAlias
SourceAddress
TcpTestSucceeded
```

**Prüffragen:**

- Wurde der erwartete Servername verwendet?
- Wurde der Name zur erwarteten IP-Adresse aufgelöst?
- Verwendet der Test die erwartete Quelladresse?
- Erfolgt der Test über das vorgesehene Netzwerkinterface?
- Ist der Port nur aus bestimmten Netzen erreichbar?
- Wird IPv4 oder IPv6 verwendet?
- Besteht zwischen Client und Server ein Proxy, VPN oder Loadbalancer?

</details>

---

<details>
<summary><strong>14. UDP-Porttests vorsichtig bewerten</strong></summary>

**Linux oder macOS:**

```bash
[TEST] nc -vzu -w 3 <SERVER> <PORT>
```

Ein solcher Test kann jedoch häufig nicht zuverlässig bestätigen, dass:

- ein UDP-Dienst tatsächlich antwortet,
- die Anwendung die Testdaten verstanden hat,
- eine Firewall die Pakete verworfen hat,
- die Rückantwort den Client erreicht,
- der Dienst fachlich funktioniert.

**Bessere UDP-Prüfung:**

| Dienst | Geeigneter protokollspezifischer Test |
|---|---|
| DNS | `dig` oder `nslookup` |
| NTP | `ntpq`, `chronyc` oder geeigneter NTP-Client |
| DHCP | Kontrollierter DHCP-Test im vorgesehenen Netz |
| SNMP | `snmpget` mit autorisierten Zugangsdaten |
| TFTP | Kontrollierter TFTP-Clienttest |
| Syslog | Testnachricht und serverseitige Protokollkontrolle |

> Bei UDP ist ein protokollspezifischer Funktionstest wesentlich aussagekräftiger als ein allgemeiner Portscan.

</details>

---

<details>
<summary><strong>15. Lokal erreichbar, von außen nicht erreichbar</strong></summary>

Wenn ein lokaler Porttest erfolgreich ist, ein entfernter Test aber fehlschlägt, kommen unter anderem folgende Ursachen infrage:

- Dienst bindet nur an Loopback,
- Dienst bindet an die falsche Netzwerkschnittstelle,
- lokale Hostfirewall blockiert externe Quellen,
- Netzwerkfirewall blockiert den Zielport,
- Routing zum Server oder zurück zum Client fehlt,
- falsches VLAN wird verwendet,
- Zugriff erfolgt über falsche IP-Adresse,
- IPv4 und IPv6 werden verwechselt,
- NAT- oder Portweiterleitung ist fehlerhaft,
- Sicherheitsgruppe oder Cloud-Firewall blockiert,
- Reverse Proxy oder Loadbalancer leitet nicht weiter,
- VPN-Richtlinie erlaubt das Zielnetz nicht,
- Dienst akzeptiert nur bestimmte Quelladressen.

**Diagnosereihenfolge:**

```text
1. Listener und Bindungsadresse prüfen
2. Lokalen Test über Loopback durchführen
3. Lokalen Test über die Server-IP durchführen
4. Test aus demselben Subnetz durchführen
5. Test aus dem betroffenen Clientnetz durchführen
6. Hostfirewall prüfen
7. Netzwerkpfad und Zwischenfirewalls prüfen
8. Paketmitschnitt auf Client und Server erwägen
```

</details>

---

<details>
<summary><strong>16. Portkonflikte erkennen</strong></summary>

Ein Portkonflikt entsteht, wenn ein Prozess eine Adresse-Port-Kombination verwenden möchte, die bereits unvereinbar belegt ist.

Typische Fehlermeldungen:

```text
Address already in use
Only one usage of each socket address is normally permitted
Failed to bind
Bind failed
EADDRINUSE
Port is already allocated
```

**Windows:**

```powershell
[RO] Get-NetTCPConnection -State Listen -LocalPort <PORT> |
    Select-Object LocalAddress, LocalPort, OwningProcess
```

```powershell
[RO] Get-NetUDPEndpoint -LocalPort <PORT> |
    Select-Object LocalAddress, LocalPort, OwningProcess
```

**Linux:**

```bash
[RO][PRIV] sudo ss -lntup "sport = :<PORT>"
```

**macOS – TCP:**

```bash
[RO][PRIV] sudo lsof -nP -iTCP:<PORT> -sTCP:LISTEN
```

**macOS – UDP:**

```bash
[RO][PRIV] sudo lsof -nP -iUDP:<PORT>
```

**Prüffragen bei einem Konflikt:**

- Welcher Prozess besitzt den Port?
- Gehört der Prozess zum erwarteten Dienst?
- Verwendet er eine Wildcard- oder Einzeladressbindung?
- Wurde eine zweite Dienstinstanz gestartet?
- Wurde der Port nach einer Aktualisierung verändert?
- Läuft ein alter Prozess weiter?
- Wird der Port durch einen Container oder Proxy veröffentlicht?
- Unterstützt die Anwendung mehrere Prozesse mit gemeinsamem Listener?
- Ist die Mehrfachbindung durch Socketoptionen ausdrücklich vorgesehen?

> Einen unbekannten Prozess nicht allein deshalb beenden, weil er den gewünschten Port verwendet. Zuerst müssen Prozess, Dienst und betriebliche Funktion eindeutig zugeordnet werden.

</details>

---

<details>
<summary><strong>17. Wichtige TCP-Zustände einordnen</strong></summary>

| Zustand | Bedeutung | Mögliche Diagnose |
|---|---|---|
| `LISTEN` | Server wartet auf neue Verbindungen | Listener vorhanden |
| `SYN_SENT` | Lokales System versucht eine Verbindung aufzubauen | Rückantwort fehlt oder Ziel nicht erreichbar |
| `SYN_RECEIVED` | Verbindungsanfrage empfangen, Handshake noch nicht abgeschlossen | Clientantwort fehlt oder Warteschlange belastet |
| `ESTABLISHED` | TCP-Verbindung vollständig aufgebaut | Transportverbindung vorhanden |
| `FIN_WAIT_1` | Lokales System hat Beendigung eingeleitet | Normal während Verbindungsabbau |
| `FIN_WAIT_2` | Bestätigung erhalten, Abschluss der Gegenseite fehlt | Bei großer dauerhafter Anzahl untersuchen |
| `CLOSE_WAIT` | Gegenseite hat beendet, lokale Anwendung noch nicht | Große dauerhafte Anzahl kann auf Anwendungsfehler hinweisen |
| `LAST_ACK` | Lokale Anwendung beendet, letzte Bestätigung steht aus | Normal kurzzeitig |
| `TIME_WAIT` | Verbindung wird nach Beendigung vorübergehend vorgehalten | Häufig normal |
| `CLOSED` | Socket ist nicht aktiv | Keine Verbindung |
| `CLOSING` | Beide Seiten beenden nahezu gleichzeitig | Normal kurzzeitig |

> Einzelne Verbindungen in `TIME_WAIT` oder `CLOSE_WAIT` sind noch kein Fehler. Auffällig sind große oder kontinuierlich wachsende Bestände über einen längeren Zeitraum.

</details>

---

<details>
<summary><strong>18. Aufgebaute Verbindungen eines Dienstes prüfen</strong></summary>

**Windows – Verbindungen einer PID:**

```powershell
[RO] Get-NetTCPConnection -OwningProcess <PID> |
    Select-Object LocalAddress,
                  LocalPort,
                  RemoteAddress,
                  RemotePort,
                  State
```

**Linux – alle TCP-Verbindungen einer PID über lsof:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -a -p <PID> -iTCP
```

**macOS – alle TCP-Verbindungen einer PID:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -a -p <PID> -iTCP
```

Damit können unter anderem folgende Fragen beantwortet werden:

- Nimmt der Dienst Clientverbindungen an?
- Baut der Dienst Verbindungen zu einer Datenbank auf?
- Verbindet er sich mit einem Verzeichnisdienst?
- Greift er auf einen Proxy oder eine externe API zu?
- Bleiben ungewöhnlich viele Verbindungen in `CLOSE_WAIT`?
- Verwendet der Prozess den erwarteten Zielport?
- Baut er Verbindungen zu einer unerwarteten Adresse auf?

> Remoteadressen, interne Servernamen und Verbindungsziele können sensible Infrastrukturinformationen darstellen.

</details>

---

<details>
<summary><strong>19. Container und vorgeschaltete Dienste berücksichtigen</strong></summary>

Bei containerisierten oder weitergeleiteten Anwendungen können mehrere Portebenen vorhanden sein.

```text
Client
  → Hostadresse: veröffentlichter Port
  → Firewall oder Proxy
  → Containeradresse: interner Port
  → Anwendungsprozess
```

**Beispiel:**

```text
Host:       192.0.2.20:8443
Container:  172.18.0.5:443
Anwendung:  0.0.0.0:443 im Container
```

Prüfungen müssen deshalb unterscheiden zwischen:

- Listener auf dem Host,
- veröffentlichtem Containerport,
- internem Containerport,
- Listener innerhalb des Containers,
- Reverse-Proxy-Listener,
- Backend-Verbindung des Proxys,
- Host- und Containerfirewall,
- Container-Netzwerk und DNS.

**Typische Fehler:**

- Port wurde nicht veröffentlicht,
- Hostport und Containerport wurden vertauscht,
- Anwendung lauscht im Container nur auf `127.0.0.1`,
- Reverse Proxy verwendet falschen Backendport,
- zwei Container beanspruchen denselben Hostport,
- Container wurde neu erstellt und erhielt eine andere interne Adresse,
- Anwendung startet später als der vorgeschaltete Proxy,
- Dienst lauscht nur auf IPv6 oder nur auf IPv4.

> Die allgemeine Socketprüfung bleibt gleich, muss aber in jedem relevanten Netzwerk-Namespace beziehungsweise auf jeder Weiterleitungsstufe wiederholt werden.

</details>

---

<details>
<summary><strong>20. Typische Fehlerbilder systematisch bewerten</strong></summary>

| Beobachtung | Mögliche Ursache | Nächster Schritt |
|---|---|---|
| Dienst läuft, aber kein Listener vorhanden | Start unvollständig, falsche Konfiguration oder interner Fehler | Dienstprotokoll und Startparameter prüfen |
| Falscher Prozess besitzt den Port | Portkonflikt oder falsche Dienstinstanz | Prozess und Änderungshistorie untersuchen |
| Listener nur auf `127.0.0.1` | Dienst nur für lokale Nutzung konfiguriert | Sollkonfiguration und Proxy-Aufbau prüfen |
| Listener nur auf einer Server-IP | Bindung an falsche oder alte Adresse | Netzwerkkonfiguration und Dienstkonfiguration prüfen |
| Listener nur auf IPv4 | IPv6-Clients erreichen den Dienst nicht | Sollzustand und IPv6-Konfiguration prüfen |
| Listener nur auf IPv6 | IPv4-Zugriff möglicherweise nicht verfügbar | IPv4 getrennt testen |
| Lokaler Test erfolgreich, entfernter Test fehlerhaft | Firewall, Routing oder falsche Bindung | Netzwerkpfad schrittweise prüfen |
| TCP-Verbindung erfolgreich, Anwendung fehlerhaft | Protokoll-, TLS-, Backend- oder Berechtigungsproblem | Anwendungsspezifischen Test durchführen |
| Viele `CLOSE_WAIT`-Verbindungen | Anwendung schließt Sockets möglicherweise nicht | Prozess- und Anwendungscode beziehungsweise Herstellerhinweise prüfen |
| Viele `SYN_RECEIVED`-Verbindungen | Handshakes bleiben unvollständig | Last, Netzwerk, Filter und mögliche Angriffe prüfen |
| UDP-Endpunkt vorhanden, Test ohne Antwort | Test möglicherweise nicht protokollgerecht | Protokollspezifischen Test verwenden |
| Port wechselt nach jedem Start | Dynamische Portkonfiguration oder fehlerhafte Vorgabe | Effektive Konfiguration prüfen |

</details>

---

<details>
<summary><strong>21. Typische Fehlinterpretationen</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „Der Dienst läuft, also ist der Port offen.“ | Der Prozess muss tatsächlich einen Socket gebunden haben |
| „Port offen bedeutet Anwendung funktioniert.“ | Nur der Transportverbindungsaufbau wurde bestätigt |
| „`0.0.0.0` bedeutet Zugriff aus dem gesamten Internet.“ | Es bedeutet alle lokalen IPv4-Adressen; Netzwerkfilter gelten weiterhin |
| „`127.0.0.1` ist die Server-IP für Clients.“ | Loopback ist nur auf dem jeweiligen System erreichbar |
| „UDP hat ebenfalls einen `LISTEN`-Zustand.“ | UDP verwendet keinen TCP-ähnlichen Listenerzustand |
| „Ein fehlgeschlagener UDP-Test beweist einen geschlossenen Port.“ | Ohne Protokollantwort ist das Ergebnis oft nicht eindeutig |
| „`[::]` beweist gleichzeitig IPv4-Erreichbarkeit.“ | IPv4 muss separat getestet werden |
| „Jeder hohe Clientport ist ein unbekannter Serverdienst.“ | Temporäre Clientports sind normal |
| „Viele `TIME_WAIT`-Einträge bedeuten automatisch einen Fehler.“ | Der Zustand ist Bestandteil des normalen TCP-Abbaus |
| „Ein Portkonflikt darf durch sofortiges Beenden gelöst werden.“ | Der besitzende Prozess muss zuerst eindeutig identifiziert werden |

</details>

---

<details>
<summary><strong>22. Checkliste zur Listener- und Portprüfung</strong></summary>

```text
[ ] Erwartetes Protokoll bestimmt
[ ] Erwarteten Port bestimmt
[ ] Erwartete Bindungsadresse bestimmt
[ ] IPv4 und IPv6 berücksichtigt
[ ] Dienststatus geprüft
[ ] Prozess und aktuelle PID geprüft
[ ] TCP-Listener beziehungsweise UDP-Endpunkt gesucht
[ ] Port dem richtigen Prozess zugeordnet
[ ] Loopback-Bindung ausgeschlossen oder als vorgesehen bestätigt
[ ] Wildcard- oder Einzeladressbindung bewertet
[ ] Lokalen Test über Loopback durchgeführt
[ ] Lokalen Test über die Serveradresse durchgeführt
[ ] Test aus dem betroffenen Clientnetz durchgeführt
[ ] Aufgelöste Zieladresse kontrolliert
[ ] TCP-Verbindungszustände geprüft
[ ] Portkonflikt ausgeschlossen
[ ] Proxy-, Loadbalancer- oder Containerstufe berücksichtigt
[ ] UDP nur mit geeignetem Protokolltest bewertet
[ ] Noch keine ungeprüfte Prozessbeendigung durchgeführt
[ ] Nächsten Diagnoseschritt dokumentiert
```

</details>

---

**Bewertung des Ergebnisses**

| Ergebnis | Nächster Schritt |
|---|---|
| Kein Listener vorhanden | Dienststart, Konfiguration und Protokolle untersuchen |
| Falscher Prozess besitzt den Port | Portkonflikt und Prozessursprung untersuchen |
| Listener verwendet falschen Port | Effektive Dienstkonfiguration prüfen |
| Listener bindet an falsche Adresse | Netzwerkschnittstellen und Bindungskonfiguration prüfen |
| Nur Loopback ist gebunden | Vorgesehenen Proxy oder externe Bindung prüfen |
| Lokaler Test funktioniert | Externen Netzwerkpfad prüfen |
| Entfernter TCP-Test scheitert | Firewall, Routing, NAT und Zwischenkomponenten prüfen |
| TCP-Test funktioniert | TLS und Anwendungsprotokoll prüfen |
| Viele problematische TCP-Zustände | Anwendung, Last und Gegenstellen untersuchen |
| UDP-Ergebnis ist unklar | Protokollspezifischen Funktionstest durchführen |

---

**Merksatz**

> **Ein laufender Prozess ohne Listener ist nicht erreichbar. Ein Listener ohne erfolgreichen Porttest ist nicht nachgewiesen erreichbar. Ein erfolgreicher Porttest ohne Anwendungstest beweist noch keine funktionierende Anwendung.**

---

**Weiterführende Quellen**

- [Microsoft Learn – Get-NetTCPConnection](https://learn.microsoft.com/powershell/module/nettcpip/get-nettcpconnection)
- [Microsoft Learn – Get-NetUDPEndpoint](https://learn.microsoft.com/powershell/module/nettcpip/get-netudpendpoint)
- [Microsoft Learn – Test-NetConnection](https://learn.microsoft.com/powershell/module/nettcpip/test-netconnection)
- [Microsoft Learn – netstat](https://learn.microsoft.com/windows-server/administration/windows-commands/netstat)
- [Linux-Handbuch – ss](https://man7.org/linux/man-pages/man8/ss.8.html)
- [Linux-Handbuch – socket](https://man7.org/linux/man-pages/man7/socket.7.html)
- [Linux-Handbuch – tcp](https://man7.org/linux/man-pages/man7/tcp.7.html)
- [Linux-Handbuch – udp](https://man7.org/linux/man-pages/man7/udp.7.html)
- [Apple – lsof-Handbuchseite](https://keith.github.io/xcode-man-pages/lsof.8.html)
- [Apple – netstat-Handbuchseite](https://keith.github.io/xcode-man-pages/netstat.1.html)
- [Apple – TCP-Handbuchseite](https://keith.github.io/xcode-man-pages/tcp.4.html)
- [Apple – listen-Handbuchseite](https://keith.github.io/xcode-man-pages/listen.2.html)

# 4.5 Dienstabhängigkeiten untersuchen*

Ein Dienst kann korrekt gestartet sein und trotzdem nicht funktionieren, wenn eine benötigte Abhängigkeit fehlt oder fehlerhaft arbeitet. Solche Abhängigkeiten können vom Betriebssystem ausdrücklich konfiguriert oder nur innerhalb der Anwendung hinterlegt sein.

> **Grundsatz:**  
> Ein abhängiger Dienst kann nur so zuverlässig funktionieren wie die gesamte Kette seiner benötigten Komponenten.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- formale und versteckte Dienstabhängigkeiten unterscheiden können,
- erforderliche und optionale Abhängigkeiten erkennen können,
- Startreihenfolge und echte Abhängigkeit auseinanderhalten können,
- vorwärts und rückwärts gerichtete Abhängigkeiten ermitteln können,
- DNS-, Netzwerk-, Speicher-, Datenbank- und Authentifizierungsabhängigkeiten prüfen können,
- Fehler entlang einer Dienstkette eingrenzen können,
- gemeinsame Abhängigkeiten bei mehreren gestörten Diensten erkennen können,
- Auswirkungen eines Dienstneustarts auf abhängige Systeme bewerten können.

---

<details>
<summary><strong>1. Formale und funktionale Abhängigkeiten unterscheiden</strong></summary>

| Art | Beschreibung | Beispiel |
|---|---|---|
| Formale Dienstabhängigkeit | In der Betriebssystem-Dienstverwaltung eingetragen | Webdienst benötigt einen lokalen Datenbankdienst |
| Startreihenfolge | Legt fest, was vorher oder nachher gestartet wird | Anwendung startet nach dem Netzwerkziel |
| Netzwerkabhängigkeit | Externes System muss über das Netzwerk erreichbar sein | Anwendung verbindet sich mit Datenbankserver |
| Namensauflösung | Dienst benötigt funktionierendes DNS | Backend wird über Hostnamen angesprochen |
| Speicherabhängigkeit | Lokales oder entferntes Dateisystem muss verfügbar sein | Anwendung benötigt SMB- oder NFS-Freigabe |
| Authentifizierungsabhängigkeit | Identitätsdienst wird benötigt | Anmeldung über Active Directory oder LDAP |
| Zertifikatsabhängigkeit | Vertrauenskette und Gültigkeit müssen stimmen | TLS-Verbindung zu einer API |
| Zeitabhängigkeit | Systemuhren müssen ausreichend synchron sein | Kerberos oder Zertifikatsprüfung |
| Ressourcenabhängigkeit | CPU, RAM, Speicherplatz oder Dateideskriptoren werden benötigt | Datenbank kann keine Dateien mehr schreiben |
| Anwendungsabhängigkeit | Andere Anwendung oder API muss funktionieren | Warenwirtschaft greift auf Zahlungsdienst zu |
| Konfigurationsabhängigkeit | Datei, Variable oder Secret muss vorhanden sein | Datenbank-URL aus Umgebungsvariable |
| Infrastrukturabhängigkeit | Plattformkomponente stellt Laufzeit bereit | Container-Runtime, Hypervisor oder Cluster |

> Betriebssystemwerkzeuge zeigen normalerweise nur die formal registrierten Abhängigkeiten. Externe Datenbanken, DNS-Server, APIs oder Netzwerkspeicher erscheinen dort häufig nicht.

</details>

---

<details>
<summary><strong>2. Eine Dienstkette darstellen</strong></summary>

Eine Anwendung kann beispielsweise folgende Kette besitzen:

```text
Benutzer
  → Client
  → DNS
  → Netzwerk und Firewall
  → Loadbalancer
  → Reverse Proxy
  → Webserver
  → Anwendungsdienst
  → Datenbank
  → Verzeichnisdienst
  → Netzwerkspeicher
  → externe API
```

Für jede Verbindung sollten folgende Informationen erfasst werden:

| Eigenschaft | Beispiel |
|---|---|
| Quellsystem | Anwendungsserver |
| Zielsystem | Datenbankserver |
| Zielname | `srv-db01.example.local` |
| Zielport | TCP 5432 |
| Protokoll | PostgreSQL |
| Authentifizierung | Dienstkonto |
| Verschlüsselung | TLS |
| Zeitüberschreitung | 10 Sekunden |
| Kritikalität | Erforderlich |
| Verhalten bei Ausfall | Anmeldung nicht möglich |
| Überwachung | TCP- und Datenbankabfrage |
| Verantwortlichkeit | Datenbankbetrieb |

**Praktische Dokumentationsform:**

| Quelle | Abhängigkeit | Ziel | Port/Protokoll | Kritisch | Nachweis |
|---|---|---|---|---:|---|
| Webserver | Namensauflösung | DNS-Server | UDP/TCP 53 | Ja | DNS-Abfrage |
| Webserver | Anwendung | App-Server | TCP 8443 | Ja | HTTPS-Test |
| App-Server | Datenbank | DB-Server | TCP 5432 | Ja | Datenbankabfrage |
| App-Server | Anmeldung | LDAP-Server | TCP 636 | Ja | LDAPS-Test |
| App-Server | Dateispeicher | Fileserver | SMB 445 | Nein | Freigabetest |

</details>

---

<details>
<summary><strong>3. Erforderliche und optionale Abhängigkeiten unterscheiden</strong></summary>

| Abhängigkeitstyp | Verhalten bei Ausfall |
|---|---|
| Zwingend erforderlich | Dienst kann nicht starten oder Hauptfunktion fällt aus |
| Optional | Nur Zusatzfunktion fällt aus |
| Bedingt erforderlich | Nur bestimmte Benutzer oder Vorgänge sind betroffen |
| Redundant | Andere Instanz kann übernehmen |
| Zwischengespeichert | Funktioniert vorübergehend mit vorhandenen Cache-Daten |
| Asynchron | Anfragen werden zunächst in eine Warteschlange geschrieben |
| Startabhängig | Nur während des Starts erforderlich |
| Laufzeitabhängig | Während des gesamten Betriebs erforderlich |
| Verwaltungsabhängig | Nur für Administration oder Monitoring erforderlich |

**Beispiele:**

- Eine Webanwendung kann ihre Startseite ohne Datenbank ausliefern, aber keine Benutzer anmelden.
- Ein Maildienst kann Nachrichten zwischenspeichern, obwohl das Zielsystem vorübergehend nicht erreichbar ist.
- Ein Cluster kann beim Ausfall einer Instanz weiterarbeiten.
- Ein Dienst kann starten, obwohl ein optionales Monitoring-Backend fehlt.
- Eine Anwendung kann nach dem Start weiterarbeiten, obwohl der Konfigurationsdienst später ausfällt.

> Der Ausfall einer Abhängigkeit führt nicht immer zum vollständigen Dienststillstand. Teilfunktionen und verzögerte Fehler müssen deshalb ausdrücklich geprüft werden.

</details>

---

<details>
<summary><strong>4. Windows-Dienstabhängigkeiten mit PowerShell prüfen</strong></summary>

`<DIENSTNAME>` muss durch den internen Dienstnamen ersetzt werden.

**Dienst und erforderliche Systemdienste anzeigen:**

```powershell
[RO] Get-Service -Name "<DIENSTNAME>" -RequiredServices
```

**Nur die erforderlichen Dienste übersichtlich anzeigen:**

```powershell
[RO] (Get-Service -Name "<DIENSTNAME>").ServicesDependedOn |
    Select-Object Name, DisplayName, Status
```

**Dienste anzeigen, die vom untersuchten Dienst abhängen:**

```powershell
[RO] Get-Service -Name "<DIENSTNAME>" -DependentServices
```

**Abhängige Dienste übersichtlich anzeigen:**

```powershell
[RO] (Get-Service -Name "<DIENSTNAME>").DependentServices |
    Select-Object Name, DisplayName, Status
```

**Dienst und beide Abhängigkeitsrichtungen erfassen:**

```powershell
[RO] $service = Get-Service -Name "<DIENSTNAME>"

$service | Select-Object Name, DisplayName, Status

"Benötigte Dienste:"
$service.ServicesDependedOn |
    Select-Object Name, DisplayName, Status

"Abhängige Dienste:"
$service.DependentServices |
    Select-Object Name, DisplayName, Status
```

**Wichtig:**

- `ServicesDependedOn` zeigt Dienste, die der untersuchte Dienst benötigt.
- `DependentServices` zeigt Dienste, die den untersuchten Dienst benötigen.
- Beide Richtungen sind vor einem Stopp oder Neustart relevant.
- Nicht jede funktionale Anwendungsabhängigkeit ist beim Service Control Manager registriert.

</details>

---

<details>
<summary><strong>5. Windows-Dienstabhängigkeiten mit sc.exe prüfen</strong></summary>

**Konfiguration einschließlich eingetragener Abhängigkeiten anzeigen:**

```powershell
[RO][SENS] sc.exe qc "<DIENSTNAME>"
```

Relevant ist insbesondere der Abschnitt:

```text
DEPENDENCIES
```

**Direkt abhängige Dienste anzeigen:**

```powershell
[RO] sc.exe enumdepend "<DIENSTNAME>"
```

**Erweiterte Dienstinformationen anzeigen:**

```powershell
[RO] sc.exe queryex "<DIENSTNAME>"
```

**Interpretation:**

| Abfrage | Richtung |
|---|---|
| `sc.exe qc` → `DEPENDENCIES` | Welche Dienste benötigt der untersuchte Dienst? |
| `sc.exe enumdepend` | Welche Dienste hängen vom untersuchten Dienst ab? |

> `sc.exe qc` kann Programmpfade, Dienstkonten und interne Konfigurationsinformationen anzeigen. Die Ausgabe sollte deshalb als potenziell sensibel behandelt werden.

</details>

---

<details>
<summary><strong>6. Zustand aller formalen Windows-Abhängigkeiten prüfen</strong></summary>

**Benötigte Dienste samt Startart und Konto untersuchen:**

```powershell
[RO] $requiredServices = (Get-Service -Name "<DIENSTNAME>").ServicesDependedOn

foreach ($requiredService in $requiredServices) {
    Get-CimInstance Win32_Service `
        -Filter "Name='$($requiredService.Name)'" |
        Select-Object Name,
                      DisplayName,
                      State,
                      StartMode,
                      StartName,
                      ProcessId,
                      ExitCode
}
```

**Mögliche Auffälligkeiten:**

- erforderlicher Dienst ist beendet,
- erforderlicher Dienst ist deaktiviert,
- Dienst hängt in `StartPending`,
- Dienst läuft unter einem falschen Konto,
- Dienstprozess besitzt keine PID,
- Exitcode ist ungleich null,
- benötigter Dienst wird wiederholt neu gestartet,
- Abhängigkeitsdefinition enthält einen nicht mehr vorhandenen Dienst.

> Ein laufender erforderlicher Dienst kann trotzdem funktional gestört sein. Nach dem Status müssen Listener, Protokoll und tatsächliche Funktion geprüft werden.

</details>

---

<details>
<summary><strong>7. Abhängigkeiten unter Linux mit systemd anzeigen</strong></summary>

**Direkte und indirekte Abhängigkeiten anzeigen:**

```bash
[RO] systemctl list-dependencies "<DIENST>" --no-pager
```

**Nur unmittelbare Abhängigkeiten anzeigen:**

```bash
[RO] systemctl list-dependencies \
  --plain \
  --no-pager \
  "<DIENST>"
```

**Rückwärts gerichtete Abhängigkeiten anzeigen:**

```bash
[RO] systemctl list-dependencies \
  --reverse \
  --no-pager \
  "<DIENST>"
```

**Abhängigkeiten und Reihenfolgenbeziehungen strukturiert anzeigen:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=Requires,Wants,Requisite,BindsTo,PartOf,After,Before,Conflicts
```

**Wirksame Unit-Konfiguration anzeigen:**

```bash
[RO][FILE][SENS] systemctl cat "<DIENST>"
```

**Status abhängiger Units prüfen:**

```bash
[RO] systemctl --failed --no-pager
```

> `systemctl list-dependencies` zeigt systemd-Units. Eine in der Anwendung konfigurierte Datenbank oder API wird nur dann sichtbar, wenn dafür ausdrücklich eine systemd-Beziehung definiert wurde.

</details>

---

<details>
<summary><strong>8. systemd-Beziehungen richtig interpretieren</strong></summary>

| Direktive | Grundbedeutung |
|---|---|
| `Requires=` | Starke Anforderungsbeziehung zu einer anderen Unit |
| `Wants=` | Schwächere Anforderungsbeziehung |
| `Requisite=` | Andere Unit muss bereits aktiv sein; sie wird dadurch nicht automatisch gestartet |
| `BindsTo=` | Engere Bindung an den Aktivzustand einer anderen Unit |
| `PartOf=` | Bestimmte Stop- und Neustartaktionen werden weitergegeben |
| `After=` | Diese Unit wird nach der genannten Unit gestartet |
| `Before=` | Diese Unit wird vor der genannten Unit gestartet |
| `Conflicts=` | Units sollen nicht gleichzeitig aktiv sein |
| `OnFailure=` | Andere Unit wird bei einem Fehlschlag aktiviert |

**Besonders wichtig:**

```text
Requires=  ist nicht dasselbe wie After=
Wants=     ist nicht dasselbe wie After=
After=     legt Reihenfolge fest, aber keine zwingende Anforderung
Before=    legt Reihenfolge fest, aber keine zwingende Anforderung
```

**Beispiel:**

```ini
[Unit]
Requires=postgresql.service
After=network-online.target postgresql.service
```

Mögliche Interpretation:

- Der Dienst besitzt eine starke Anforderung an `postgresql.service`.
- Er soll nach `postgresql.service` gestartet werden.
- Er soll außerdem nach `network-online.target` gestartet werden.
- Das Erreichen von `network-online.target` beweist nicht, dass eine bestimmte entfernte Datenbank tatsächlich erreichbar ist.

> Für eine zuverlässige Bewertung müssen Anforderungs- und Reihenfolgedirektiven gemeinsam betrachtet werden.

</details>

---

<details>
<summary><strong>9. Abhängigkeitsbaum unter systemd in beide Richtungen lesen</strong></summary>

**Vorwärts gerichtete Frage:**

> Was benötigt dieser Dienst?

```bash
[RO] systemctl list-dependencies "<DIENST>" --no-pager
```

**Rückwärts gerichtete Frage:**

> Welche Units benötigen diesen Dienst?

```bash
[RO] systemctl list-dependencies \
  --reverse \
  --no-pager \
  "<DIENST>"
```

**Nur Abhängigkeiten vor einem Neustart prüfen:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=RequiredBy,WantedBy,ConsistsOf,PartOf
```

**Bewertung vor einer Maßnahme:**

| Feststellung | Bedeutung |
|---|---|
| Viele rückwärtige Abhängigkeiten | Neustart kann mehrere Dienste beeinflussen |
| `PartOf=` vorhanden | Neustart- oder Stoppaktionen können gekoppelt sein |
| `BindsTo=` vorhanden | Ausfall kann abhängige Unit ebenfalls deaktivieren |
| Gemeinsame Datenbankabhängigkeit | Datenbankfehler kann mehrere Anwendungen betreffen |
| Gemeinsames Netzwerkmount | Speicherfehler kann mehrere Dienste blockieren |
| Gemeinsames Target | Nicht jede aufgeführte Unit ist zwingend funktional abhängig |

</details>

---

<details>
<summary><strong>10. Abhängigkeiten unter macOS mit launchd untersuchen</strong></summary>

launchd besitzt laut Apple kein allgemeines ausdrückliches Abhängigkeitsmodell wie systemd. Dienstinteraktionen sollen möglichst über bedarfsgesteuerte IPC-Mechanismen gelöst werden.

Deshalb müssen mehrere Informationsquellen kombiniert werden.

**Systemweiten Dienst anzeigen:**

```bash
[RO] launchctl print "system/<LABEL>"
```

**Benutzerbezogenen Dienst anzeigen:**

```bash
[RO] launchctl print "gui/$(id -u)/<LABEL>"
```

**Konfigurationsdatei eines bekannten Drittanbieterdienstes anzeigen:**

```bash
[RO][FILE][SENS] plutil -p "/Library/LaunchDaemons/<LABEL>.plist"
```

**Benutzerbezogenen LaunchAgent anzeigen:**

```bash
[RO][FILE][SENS] plutil -p "$HOME/Library/LaunchAgents/<LABEL>.plist"
```

In der plist können unter anderem folgende Auslöser relevant sein:

| Schlüssel | Bedeutung |
|---|---|
| `MachServices` | Vom Job bereitgestellte Mach-Dienste |
| `Sockets` | Von launchd verwaltete Sockets |
| `KeepAlive` | Bedingungen für fortlaufende oder erneute Ausführung |
| `PathState` | Startbedingung anhand vorhandener Pfade |
| `OtherJobEnabled` | Bedingung anhand des Aktivierungszustands anderer Jobs |
| `WatchPaths` | Start bei Änderung beobachteter Pfade |
| `QueueDirectories` | Start bei nicht leerem Verzeichnis |
| `NetworkState` | Historische grobe Netzwerkbedingung; nicht als Erreichbarkeitsnachweis verwenden |
| `StartOnMount` | Start beim Einhängen eines Dateisystems |

> Der Schlüssel `OtherJobEnabled` bildet keine harte, zuverlässige Dienstabhängigkeit wie ein allgemeines Abhängigkeitsmodell. Apple beschreibt solche Bedingungen als Hinweise und empfiehlt bedarfsgesteuerte IPC-Mechanismen.

</details>

---

<details>
<summary><strong>11. Versteckte Anwendungsabhängigkeiten finden</strong></summary>

Funktionale Abhängigkeiten können an folgenden Stellen dokumentiert oder konfiguriert sein:

- Herstellerdokumentation,
- Architekturdiagramm,
- Betriebshandbuch,
- Konfigurationsdatei,
- Umgebungsvariable,
- Dienststartparameter,
- Containerdefinition,
- Reverse-Proxy-Konfiguration,
- DNS-Eintrag,
- Zertifikatskonfiguration,
- Mount-Konfiguration,
- Secret- oder Credential-Verwaltung,
- Anwendungsprotokoll,
- Überwachungssystem,
- Quellcode oder Deploymentbeschreibung.

**Typische Konfigurationsbegriffe:**

```text
host
hostname
server
endpoint
url
uri
database
db_host
connection_string
ldap
smtp
proxy
upstream
backend
api
mount
share
certificate
key
timeout
retry
```

> Konfigurationsdateien und Umgebungsvariablen können Geheimnisse enthalten. Nicht wahllos nach Inhalten suchen oder vollständige Dateien in Tickets kopieren.

</details>

---

<details>
<summary><strong>12. Aktive Netzwerkabhängigkeiten eines Prozesses erkennen</strong></summary>

Bereits aufgebaute Verbindungen können Hinweise auf verwendete Backends liefern.

**Windows:**

```powershell
[RO][SENS] Get-NetTCPConnection -OwningProcess <PID> |
    Select-Object LocalAddress,
                  LocalPort,
                  RemoteAddress,
                  RemotePort,
                  State
```

**Linux:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -a -p <PID> -i
```

**macOS:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -a -p <PID> -i
```

**Damit können Hinweise gefunden werden auf:**

- Datenbankserver,
- Authentifizierungsserver,
- SMTP-Server,
- Proxys,
- externe APIs,
- Clusterknoten,
- Objekt- oder Netzwerkspeicher,
- Monitoring- und Protokollserver.

**Einschränkungen:**

- Nur aktuell geöffnete Verbindungen sind sichtbar.
- Kurzlebige Verbindungen können zwischen zwei Abfragen fehlen.
- Ein Ziel kann über einen Proxy vermittelt werden.
- IP-Adressen allein beweisen nicht die fachliche Funktion des Zielsystems.
- UDP-Kommunikation ist schwieriger zu bewerten.
- Eine aktuell fehlende Verbindung kann bei Leerlauf normal sein.

</details>

---

<details>
<summary><strong>13. DNS-Abhängigkeit prüfen</strong></summary>

Wenn ein Dienst ein Backend über einen Namen anspricht, muss genau dieser Name aus dem Kontext des Dienstservers geprüft werden.

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| A- und AAAA-Auflösung | `[TEST] Resolve-DnsName "<BACKEND>"` | `[TEST] getent ahosts "<BACKEND>"` | `[TEST] dscacheutil -q host -a name "<BACKEND>"` |
| DNS gezielt abfragen | `[TEST] Resolve-DnsName "<BACKEND>" -Server <DNS-IP>` | `[TEST] dig @<DNS-IP> "<BACKEND>" A` | `[TEST] dig @<DNS-IP> "<BACKEND>" A` |
| IPv6-Adresse abfragen | `[TEST] Resolve-DnsName "<BACKEND>" -Type AAAA` | `[TEST] dig "<BACKEND>" AAAA` | `[TEST] dig "<BACKEND>" AAAA` |

**Zu prüfen:**

- Wird der richtige Name verwendet?
- Wird die erwartete IP-Adresse geliefert?
- Existieren unerwartete alte Adressen?
- Gibt es unterschiedliche Ergebnisse auf Client und Server?
- Wird ein Suchsuffix benötigt?
- Verwendet die Anwendung einen vollständig qualifizierten Namen?
- Bevorzugt die Anwendung IPv6?
- Ist der DNS-Server aus dem Dienstkontext erreichbar?
- Wurde ein DNS-Eintrag kürzlich geändert?

> Eine erfolgreiche DNS-Abfrage beweist nur die Namensauflösung. Der zurückgegebene Zielserver muss anschließend über das erforderliche Protokoll geprüft werden.

</details>

---

<details>
<summary><strong>14. TCP-Abhängigkeit eines Backends prüfen</strong></summary>

**Windows:**

```powershell
[TEST] Test-NetConnection "<BACKEND>" -Port <PORT>
```

**Linux:**

```bash
[TEST] nc -vz -w 3 "<BACKEND>" <PORT>
```

**macOS:**

```bash
[TEST] nc -vz -w 3 "<BACKEND>" <PORT>
```

**Mögliche Ergebnisse:**

| Ergebnis | Bedeutung |
|---|---|
| Namensauflösung fehlerhaft | DNS-Abhängigkeit gestört |
| Verbindung abgelehnt | Ziel erreichbar, aber kein passender Listener oder aktive Ablehnung |
| Zeitüberschreitung | Filterung, Routingproblem oder nicht reagierendes Ziel möglich |
| TCP-Verbindung erfolgreich | Transportweg bis zum Port funktioniert |
| Anwendung antwortet trotzdem fehlerhaft | Protokoll, TLS, Anmeldung oder Backendfunktion prüfen |

> Der Test muss vom tatsächlichen Anwendungsserver oder aus einem technisch gleichwertigen Netzwerkpfad erfolgen. Ein erfolgreicher Test vom Administrator-Client beweist nicht, dass der Dienstserver denselben Zugriff besitzt.

</details>

---

<details>
<summary><strong>15. HTTP- oder API-Abhängigkeit prüfen</strong></summary>

**Nur Antwortheader eines HTTP- oder HTTPS-Endpunkts anfordern:**

| Betriebssystem | Befehl |
|---|---|
| Windows | `[TEST][SENS] curl.exe -I --connect-timeout 5 "https://<BACKEND>/<PFAD>"` |
| Linux | `[TEST][SENS] curl -I --connect-timeout 5 "https://<BACKEND>/<PFAD>"` |
| macOS | `[TEST][SENS] curl -I --connect-timeout 5 "https://<BACKEND>/<PFAD>"` |

**Ausführliche TLS- und Verbindungsdiagnose:**

| Betriebssystem | Befehl |
|---|---|
| Windows | `[TEST][SENS] curl.exe -v --connect-timeout 5 "https://<BACKEND>/<PFAD>"` |
| Linux | `[TEST][SENS] curl -v --connect-timeout 5 "https://<BACKEND>/<PFAD>"` |
| macOS | `[TEST][SENS] curl -v --connect-timeout 5 "https://<BACKEND>/<PFAD>"` |

**Zu prüfen:**

- Wird die erwartete IP-Adresse verwendet?
- Ist der TCP-Verbindungsaufbau erfolgreich?
- Funktioniert der TLS-Handshake?
- Passt der Zertifikatsname?
- Welcher HTTP-Statuscode wird geliefert?
- Antwortet der erwartete Server?
- Erfolgt eine unerwartete Weiterleitung?
- Ist eine Authentifizierung erforderlich?
- Wie lange dauert die Antwort?

> `-v` kann Header und andere sensible Informationen anzeigen. Zugangstoken oder Sitzungscookies dürfen nicht in die Befehlszeile oder Dokumentation übernommen werden.

</details>

---

<details>
<summary><strong>16. Speicher- und Dateisystemabhängigkeiten prüfen</strong></summary>

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Eingebundene Datenträger | `[RO] Get-Volume` | `[RO] findmnt` | `[RO] mount` |
| Freier Speicherplatz | `[RO] Get-Volume` | `[RO] df -hT` | `[RO] df -h` |
| Bestimmten Pfad prüfen | `[RO] Test-Path "<PFAD>"` | `[RO] findmnt --target "<PFAD>"` | `[RO] df -h "<PFAD>"` |
| Pfadinformationen | `[RO][FILE] Get-Item "<PFAD>"` | `[RO][FILE] stat "<PFAD>"` | `[RO][FILE] stat "<PFAD>"` |
| Schreibrechte des aktuellen Kontos | `[RO][FILE] Get-Acl "<PFAD>"` | `[RO][FILE] namei -l "<PFAD>"` | `[RO][FILE] ls -lde "<PFAD>"` |

**Zu prüfen:**

- Ist das Dateisystem eingehängt?
- Zeigt der Pfad auf das erwartete Ziel?
- Ist ausreichend Speicherplatz vorhanden?
- Sind unter Linux noch Inodes verfügbar?
- Ist das Dateisystem schreibgeschützt?
- Besitzt das Dienstkonto die erforderlichen Rechte?
- Ist ein Netzwerkmount nur scheinbar vorhanden, aber nicht erreichbar?
- Bestehen Dateisperren?
- Hat sich der Mountpfad geändert?
- Ist das Volume nach einem Neustart automatisch eingebunden worden?

> Schreibtests verändern das Dateisystem und dürfen nur gezielt, mit freigegebenem Testpfad und anschließendem Aufräumen durchgeführt werden.

</details>

---

<details>
<summary><strong>17. Zeit- und Synchronisationsabhängigkeit prüfen</strong></summary>

Falsche Systemzeit kann unter anderem folgende Funktionen beeinträchtigen:

- Kerberos-Authentifizierung,
- Zertifikatsprüfung,
- signierte Tokens,
- Protokollkorrelation,
- zeitgesteuerte Aufgaben,
- Datenbankreplikation,
- Clusterentscheidungen,
- Ablaufzeiten und Cache-Gültigkeit.

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Lokale Zeit | `[RO] Get-Date -Format o` | `[RO] date --iso-8601=seconds` | `[RO] date "+%Y-%m-%dT%H:%M:%S%z"` |
| UTC-Zeit | `[RO] (Get-Date).ToUniversalTime().ToString("o")` | `[RO] date -u "+%Y-%m-%dT%H:%M:%SZ"` | `[RO] date -u "+%Y-%m-%dT%H:%M:%SZ"` |
| Zeitzone | `[RO] Get-TimeZone` | `[RO] timedatectl status` | `[RO][PRIV] sudo systemsetup -gettimezone` |
| Zeitstatus | `[RO] w32tm /query /status` | `[RO] timedatectl status` | `[RO] systemsetup -getusingnetworktime` |

**Prüfung:**

- Stimmen Datum und Uhrzeit?
- Ist die richtige Zeitzone eingestellt?
- Ist die Zeitquelle erreichbar?
- Sind Client, Dienstserver und Backend ausreichend synchron?
- Stimmen Protokollzeitstempel tatsächlich überein?
- Verwendet eine Anwendung UTC, während eine andere lokale Zeit protokolliert?

</details>

---

<details>
<summary><strong>18. Authentifizierungsabhängigkeit prüfen</strong></summary>

Typische abhängige Identitätsdienste:

- Active Directory,
- LDAP oder LDAPS,
- Kerberos,
- RADIUS,
- lokale Benutzerverwaltung,
- OAuth- oder OpenID-Connect-Anbieter,
- SAML-Identitätsanbieter,
- Zertifikats- oder Smartcard-Infrastruktur.

**Vor einer Anmeldeprüfung kontrollieren:**

1. Wird der Identitätsserver korrekt aufgelöst?
2. Ist der erforderliche Port erreichbar?
3. Ist die Systemzeit synchron?
4. Ist das Dienstkonto aktiv?
5. Ist das Kennwort beziehungsweise Secret gültig?
6. Ist das Konto gesperrt?
7. Besitzt das Konto die erforderlichen Rechte?
8. Ist das Serverzertifikat gültig?
9. Funktioniert nur die Anmeldung nicht oder auch die gesamte Anwendung?
10. Sind alle Benutzer oder nur einzelne Konten betroffen?

> Kennwörter, Tokens und private Schlüssel dürfen niemals in Diagnoseausgaben, Tickets oder BookStack-Beispiele kopiert werden.

</details>

---

<details>
<summary><strong>19. Gemeinsame Abhängigkeit als Ursache erkennen</strong></summary>

Wenn mehrere Dienste gleichzeitig ausfallen, sollte nach einer gemeinsamen Komponente gesucht werden.

| Beobachtung | Mögliche gemeinsame Abhängigkeit |
|---|---|
| Mehrere Anwendungen können Benutzer nicht anmelden | Verzeichnisdienst, DNS oder Zeitquelle |
| Mehrere Webseiten liefern Backendfehler | Datenbank, Reverse Proxy oder Speicher |
| Mehrere Dienste können keine Dateien schreiben | Volume, Dateisystem oder Berechtigung |
| Nur externe APIs schlagen fehl | Proxy, Internetzugang, DNS oder Zertifikatskette |
| Alle Dienste eines Hosts sind langsam | CPU, RAM, Datenträger oder Virtualisierungsplattform |
| Mehrere Container starten nicht | Container-Runtime, Netzwerk oder Storage |
| Anwendungen an einem Standort sind betroffen | WAN, VPN, DNS oder Firewall |
| Fehler beginnt exakt gleichzeitig | Gemeinsame Änderung oder Infrastrukturkomponente |

**Vorgehen:**

```text
1. Betroffene Dienste auflisten
2. Zeitpunkt jedes Ausfalls vergleichen
3. Gemeinsame DNS-, Netzwerk- und Speicherpfade bestimmen
4. Gemeinsame Datenbanken und Identitätsdienste bestimmen
5. Gemeinsame Änderungen ermitteln
6. Gemeinsame Abhängigkeit direkt prüfen
7. Nach Wiederherstellung alle abhängigen Funktionen testen
```

</details>

---

<details>
<summary><strong>20. Startreihenfolge nicht mit Betriebsbereitschaft verwechseln</strong></summary>

Ein Dienst kann laut Betriebssystem gestartet worden sein, obwohl seine Funktion noch nicht vollständig bereitsteht.

**Beispiel:**

```text
00:00 Datenbankprozess startet
00:02 Dienstverwaltung meldet „läuft“
00:05 Datenbank führt Wiederherstellung aus
00:40 Datenbank nimmt Anmeldungen an
```

Startet die Anwendung bereits bei Sekunde 3, kann ihre Verbindung fehlschlagen, obwohl der Datenbankdienst formal läuft.

Mögliche Lösungen innerhalb eines geplanten Änderungsverfahrens:

- geeignete Bereitschaftsprüfung,
- Wiederholungsversuche mit Begrenzung,
- zunehmende Wartezeiten zwischen Versuchen,
- sinnvoller Verbindungstimeout,
- korrekte systemd-Abhängigkeit,
- orchestrierte Healthchecks,
- Start erst nach erfolgreichem Backendtest,
- Warteschlange für vorübergehend nicht verarbeitbare Aufgaben.

> Eine feste Wartezeit ist häufig weniger zuverlässig als eine echte Bereitschaftsprüfung.

</details>

---

<details>
<summary><strong>21. Auswirkungen vor einem Neustart einer Abhängigkeit prüfen</strong></summary>

Vor dem Neustart eines gemeinsam verwendeten Dienstes müssen die abhängigen Verbraucher bestimmt werden.

**Windows:**

```powershell
[RO] (Get-Service -Name "<DIENSTNAME>").DependentServices |
    Select-Object Name, DisplayName, Status
```

**Linux:**

```bash
[RO] systemctl list-dependencies \
  --reverse \
  --no-pager \
  "<DIENST>"
```

**macOS:**

Da launchd kein allgemeines ausdrückliches Abhängigkeitsmodell besitzt, müssen zusätzlich geprüft werden:

- Herstellerdokumentation,
- aktive Netzwerkverbindungen,
- Konfigurationsdateien,
- Architekturübersicht,
- Monitoring,
- Anwendungsprotokolle,
- bekannte Verbraucher des Dienstes.

**Freigabecheck:**

```text
[ ] Alle bekannten Verbraucher identifiziert
[ ] Aktive Sitzungen und Transaktionen geprüft
[ ] Cluster- oder Failover-Verhalten geprüft
[ ] Wiederverbindungsverhalten der Clients bekannt
[ ] Neustartreihenfolge festgelegt
[ ] Wartungsfenster beziehungsweise Freigabe vorhanden
[ ] Diagnoseinformationen vorab gesichert
[ ] Funktionstests für alle wichtigen Verbraucher vorbereitet
[ ] Rückfallmöglichkeit festgelegt
```

</details>

---

<details>
<summary><strong>22. Abhängigkeitsfehler schrittweise eingrenzen</strong></summary>

**Empfohlene Reihenfolge:**

1. Hauptfunktion und Fehlermeldung bestimmen.
2. Formale Dienstabhängigkeiten erfassen.
3. Architektur und funktionale Abhängigkeiten ergänzen.
4. Kritische und optionale Abhängigkeiten kennzeichnen.
5. Namen der Zielsysteme prüfen.
6. DNS-Auflösung prüfen.
7. Netzwerkport vom tatsächlichen Dienstserver prüfen.
8. TLS- und Zertifikatsprüfung durchführen.
9. Protokollspezifischen Funktionstest durchführen.
10. Authentifizierung mit einem freigegebenen Testkonto prüfen.
11. Speicher- und Ressourcenabhängigkeiten prüfen.
12. Zeitstempel der beteiligten Systeme vergleichen.
13. Protokolle auf Quelle und Ziel korrelieren.
14. Gemeinsame Abhängigkeiten anderer gestörter Dienste prüfen.
15. Erst nach gesicherter Ursache eine Änderung planen.

**Prüfkette:**

```text
Name korrekt?
  ↓
DNS korrekt?
  ↓
Route vorhanden?
  ↓
Port erreichbar?
  ↓
TLS gültig?
  ↓
Protokoll antwortet?
  ↓
Authentifizierung erfolgreich?
  ↓
Berechtigung ausreichend?
  ↓
Fachliche Anfrage erfolgreich?
```

</details>

---

<details>
<summary><strong>23. Typische Fehlinterpretationen</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „Alle Abhängigkeiten stehen in der Dienstverwaltung.“ | Viele funktionale Abhängigkeiten sind nur in der Anwendung konfiguriert |
| „Der erforderliche Dienst läuft, also funktioniert er.“ | Seine fachliche Funktion muss separat geprüft werden |
| „`After=` bedeutet, dass der andere systemd-Dienst zwingend benötigt wird.“ | `After=` legt nur eine Reihenfolge fest |
| „`Requires=` bedeutet automatisch die richtige Startreihenfolge.“ | Dafür kann zusätzlich `After=` oder `Before=` erforderlich sein |
| „Ein erfolgreicher Porttest beweist die Backendfunktion.“ | Nur der Transportweg wurde bestätigt |
| „DNS liefert eine Adresse, also ist das richtige Backend erreicht.“ | Adresse, Zertifikat und Anwendungsantwort müssen geprüft werden |
| „Alle Benutzer sind betroffen, also liegt es am Hauptdienst.“ | Eine gemeinsame Abhängigkeit kann ausgefallen sein |
| „Ein Neustart der Hauptanwendung repariert die Abhängigkeit.“ | Er kann nur neue Verbindungsversuche auslösen |
| „Startreihenfolge beweist Betriebsbereitschaft.“ | Ein Prozess kann laufen, während die Initialisierung noch andauert |
| „Ein optionales Backend kann ignoriert werden.“ | Es kann für einzelne wichtige Funktionen zwingend sein |

</details>

---

<details>
<summary><strong>24. Checkliste zur Abhängigkeitsanalyse</strong></summary>

```text
[ ] Hauptdienst eindeutig bestimmt
[ ] Formale Betriebssystem-Abhängigkeiten erfasst
[ ] Vorwärts gerichtete Abhängigkeiten geprüft
[ ] Rückwärts gerichtete Abhängigkeiten geprüft
[ ] Startreihenfolge getrennt von Anforderung bewertet
[ ] Kritische und optionale Abhängigkeiten unterschieden
[ ] Externe Datenbanken erfasst
[ ] DNS- und Zeitabhängigkeiten erfasst
[ ] Authentifizierungsdienste erfasst
[ ] Speicher- und Dateisystemabhängigkeiten erfasst
[ ] Proxys, Loadbalancer und APIs erfasst
[ ] Container-, Cluster- oder Cloud-Abhängigkeiten berücksichtigt
[ ] DNS-Auflösung vom Dienstserver geprüft
[ ] Zielport vom Dienstserver geprüft
[ ] TLS und Zertifikatsname geprüft
[ ] Protokollspezifischer Funktionstest durchgeführt
[ ] Gemeinsame Abhängigkeiten anderer Störungen geprüft
[ ] Protokollzeitstempel korreliert
[ ] Auswirkungen eines Neustarts bewertet
[ ] Keine Geheimnisse dokumentiert
[ ] Nächsten Diagnoseschritt festgelegt
```

</details>

---

**Bewertung des Ergebnisses**

| Ergebnis | Nächster Schritt |
|---|---|
| Formale Abhängigkeit ist beendet | Status, Startfehler und Protokolle dieser Abhängigkeit prüfen |
| Abhängigkeit ist deaktiviert oder maskiert | Sollzustand und Änderungshistorie klären |
| DNS-Auflösung schlägt fehl | DNS-Konfiguration und verwendeten Namen prüfen |
| Port der Abhängigkeit ist nicht erreichbar | Listener, Firewall und Netzwerkpfad prüfen |
| Port ist erreichbar, Protokolltest scheitert | TLS, Authentifizierung und Anwendung prüfen |
| Speicherpfad fehlt | Mount, Volume, Netzwerk und Berechtigungen prüfen |
| Nur Anmeldung schlägt fehl | Identitätsdienst, Zeit und Dienstkonto prüfen |
| Mehrere Dienste sind gleichzeitig betroffen | Gemeinsame Abhängigkeit priorisiert untersuchen |
| Backend ist erst spät betriebsbereit | Healthcheck, Wiederholungslogik und Startablauf prüfen |
| Alle Abhängigkeiten funktionieren | Hauptdienstkonfiguration und Dienstprotokolle untersuchen |

---

**Merksatz**

> **Die sichtbare Anwendung ist oft nur das letzte Glied einer langen Dienstkette. Die Ursache liegt häufig in einer gemeinsam genutzten, zunächst unsichtbaren Abhängigkeit.**

---

**Weiterführende Quellen**

- [Microsoft Learn – Get-Service](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-service)
- [Microsoft Learn – ServiceController.ServicesDependedOn](https://learn.microsoft.com/dotnet/api/system.serviceprocess.servicecontroller.servicesdependedon)
- [Microsoft Learn – ServiceController.DependentServices](https://learn.microsoft.com/dotnet/api/system.serviceprocess.servicecontroller.dependentservices)
- [Microsoft Learn – sc.exe qc](https://learn.microsoft.com/windows-server/administration/windows-commands/sc-qc)
- [Microsoft Learn – sc.exe enumdepend](https://learn.microsoft.com/windows-server/administration/windows-commands/sc-enumdepend)
- [systemd – systemctl](https://www.freedesktop.org/software/systemd/man/latest/systemctl.html)
- [systemd – systemd.unit](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html)
- [systemd – systemd.service](https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html)
- [Apple – launchctl-Handbuchseite](https://keith.github.io/xcode-man-pages/launchctl.1.html)
- [Apple – launchd.plist-Handbuchseite](https://keith.github.io/xcode-man-pages/launchd.plist.5.html)
- [Microsoft Learn – Test-NetConnection](https://learn.microsoft.com/powershell/module/nettcpip/test-netconnection)
- [curl – offizielle Dokumentation](https://curl.se/docs/manpage.html)

# 4.6 System- und Dienstprotokolle auswerten

System- und Dienstprotokolle dokumentieren Ereignisse, die während des Starts, Betriebs und Beendens eines Dienstes auftreten. Sie können Hinweise auf Konfigurationsfehler, fehlende Berechtigungen, nicht erreichbare Abhängigkeiten, Ressourcenmangel oder Programmabstürze liefern.

> **Grundsatz:**  
> Protokolle werden nicht wahllos nach dem Wort „Fehler“ durchsucht. Zuerst werden Zeitraum, betroffener Dienst, Server und auslösende Aktion festgelegt.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- ein geeignetes Zeitfenster für die Protokollanalyse bestimmen können,
- Windows-Ereignisprotokolle, systemd-Journal und macOS Unified Logging auswerten können,
- nach Dienst, Quelle, Prozess, Ereignis-ID und Priorität filtern können,
- System- und Anwendungsprotokolle zeitlich miteinander verbinden können,
- Ursachen von Folgefehlern unterscheiden können,
- Live-Protokolle kontrolliert beobachten können,
- relevante Protokolle sichern können,
- sensible Inhalte vor einer Weitergabe erkennen können,
- Grenzen und Aufbewahrungsregeln von Protokollen berücksichtigen können.

---

<details>
<summary><strong>1. Beobachtung, Protokollhinweis und Ursache unterscheiden</strong></summary>

| Ebene | Beispiel |
|---|---|
| Benutzerbeobachtung | Anmeldung schlägt um 09:15 Uhr fehl |
| Anwendungsprotokoll | Datenbankverbindung um 09:15:02 Uhr fehlgeschlagen |
| Systemprotokoll | Netzwerkschnittstelle um 09:14:58 Uhr getrennt |
| Backendprotokoll | Keine Anfrage vom Anwendungsserver eingegangen |
| Ursache | Netzwerkschnittstelle verlor aufgrund eines Treiberfehlers die Verbindung |
| Folgefehler | Anwendung meldete anschließend einen Datenbankfehler |

Eine Protokollmeldung kann sein:

- direkte Ursache,
- Folge einer anderen Störung,
- Warnung ohne Bezug zum aktuellen Problem,
- erwarteter Betriebszustand,
- Wiederholungsversuch,
- Ergebnis einer automatischen Wiederherstellung,
- Meldung eines vorgeschalteten oder abhängigen Systems.

> Der erste sichtbare Fehler in einer Anwendung ist nicht zwingend das zeitlich erste technische Ereignis.

</details>

---

<details>
<summary><strong>2. Vor der Suche ein genaues Zeitfenster festlegen</strong></summary>

Folgende Zeitangaben müssen möglichst genau bestimmt werden:

| Information | Beispiel |
|---|---|
| Beginn des Fehlers | `2026-07-31T09:15:00+02:00` |
| Ende beziehungsweise letzter Fehler | `2026-07-31T09:22:00+02:00` |
| Zeitzone | Europe/Berlin, UTC+02:00 |
| Auslösende Aktion | Anmeldung abgesendet |
| Clientzeit | 09:15:00 |
| Serverzeit | 09:15:02 |
| Backendzeit | 07:15:02 UTC |
| Vergleichszeitpunkt | Letzte erfolgreiche Anmeldung um 09:13 Uhr |

**Empfohlener Suchbereich:**

```text
Einige Minuten vor dem ersten sichtbaren Fehler
bis
einige Minuten nach dem letzten beobachteten Fehler
```

**Prüffragen:**

- Verwenden alle Systeme dieselbe Zeitzone?
- Protokolliert eine Anwendung in UTC?
- Sind die Systemuhren synchronisiert?
- Ist der Clientzeitstempel nur auf Sekunden genau?
- Gab es unmittelbar vorher einen Neustart oder eine Änderung?
- Ist das Problem dauerhaft oder nur kurzzeitig aufgetreten?

</details>

---

<details>
<summary><strong>3. Protokollanalyse mit einer klaren Hypothese beginnen</strong></summary>

**Ungeeignete Suche:**

> „Ich suche in allen Protokollen nach Fehlern.“

**Geeignete Suche:**

> „Ich untersuche zwischen 09:10 und 09:20 Uhr die Ereignisse des Anwendungsdienstes, des Service Control Managers und der Datenbankverbindung.“

Eine gute Protokollsuche verwendet möglichst mehrere Filter:

- Zeitfenster,
- Server,
- Dienstname,
- Prozessname,
- Prozess-ID,
- Ereignisquelle,
- Ereignis-ID,
- Priorität,
- Transaktions- oder Korrelations-ID,
- Benutzer oder Sitzung,
- Zielserver,
- Fehlercode.

**Empfohlene Reihenfolge:**

```text
1. Zeitpunkt festlegen
2. Hauptdienst filtern
3. Erste relevante Fehlermeldung bestimmen
4. Einige Ereignisse davor lesen
5. Abhängige Systeme prüfen
6. Fehlercode in offizieller Dokumentation nachschlagen
7. Ereignisse zeitlich zusammenführen
8. Hypothese mit einem gezielten Test überprüfen
```

</details>

---

<details>
<summary><strong>4. Protokollquellen der Betriebssysteme vergleichen</strong></summary>

| Bereich | Windows | Linux mit systemd | macOS |
|---|---|---|---|
| Zentrale Oberfläche | Ereignisanzeige | `journalctl` | Konsole |
| Zentrales Befehlswerkzeug | `Get-WinEvent` | `journalctl` | `log` |
| Systemereignisse | Protokoll `System` | System-Journal | Unified Logging |
| Anwendungsereignisse | Protokoll `Application` oder eigenes Protokoll | Journal oder Anwendungsdatei | Unified Logging oder Anwendungsdatei |
| Dienstverwaltung | Service Control Manager | systemd | launchd |
| Kernelmeldungen | Protokoll `System` | `journalctl -k` | `log show` und Diagnoseberichte |
| Absturzberichte | Windows Error Reporting | Coredump- oder Anwendungsmechanismus | Diagnoseberichte |
| Dateibasierte Logs | Anwendungsspezifisch | Häufig unter `/var/log` oder Produktpfad | Anwendungsspezifisch |

> Nicht jede Anwendung schreibt in das zentrale Betriebssystemprotokoll. Herstellerdokumentation und effektive Dienstkonfiguration müssen zusätzlich geprüft werden.

</details>

---

<details>
<summary><strong>5. Verfügbare Windows-Ereignisprotokolle ermitteln</strong></summary>

**Alle registrierten Protokolle auflisten:**

```powershell
[RO] Get-WinEvent -ListLog *
```

**Nur aktivierte Protokolle anzeigen:**

```powershell
[RO] Get-WinEvent -ListLog * |
    Where-Object IsEnabled |
    Select-Object LogName, RecordCount, FileSize, MaximumSizeInBytes |
    Sort-Object LogName
```

**Bestimmtes Protokoll untersuchen:**

```powershell
[RO] Get-WinEvent -ListLog "System"
```

**Registrierte Ereignisanbieter suchen:**

```powershell
[RO] Get-WinEvent -ListProvider "*<SUCHBEGRIFF>*"
```

**Typische Windows-Protokolle:**

| Protokoll | Typischer Inhalt |
|---|---|
| `System` | Dienste, Treiber, Netzwerk und Betriebssystem |
| `Application` | Anwendungen und Laufzeitumgebungen |
| `Security` | Sicherheitsereignisse und Überwachung |
| `Setup` | Installation und Systemeinrichtung |
| `ForwardedEvents` | Weitergeleitete Ereignisse |
| Anwendungs- und Dienstprotokolle | Komponenten- oder produktspezifische Ereignisse |

> Der Zugriff auf das Sicherheitsprotokoll und bestimmte administrative Protokolle erfordert erhöhte Berechtigungen.

</details>

---

<details>
<summary><strong>6. Letzte Windows-Ereignisse anzeigen</strong></summary>

**Letzte 50 Systemereignisse anzeigen:**

```powershell
[RO] Get-WinEvent -LogName "System" -MaxEvents 50 |
    Select-Object TimeCreated,
                  Id,
                  LevelDisplayName,
                  ProviderName,
                  Message
```

**Letzte 50 Anwendungsereignisse anzeigen:**

```powershell
[RO] Get-WinEvent -LogName "Application" -MaxEvents 50 |
    Select-Object TimeCreated,
                  Id,
                  LevelDisplayName,
                  ProviderName,
                  Message
```

**Neueste Ereignisse zuerst tabellarisch anzeigen:**

```powershell
[RO] Get-WinEvent -LogName "System" -MaxEvents 100 |
    Format-Table TimeCreated,
                 Id,
                 LevelDisplayName,
                 ProviderName,
                 Message -Wrap
```

> `Format-Table` sollte hauptsächlich für die Anzeige verwendet werden. Für Export oder Weiterverarbeitung bleiben die ursprünglichen Ereignisobjekte geeigneter.

</details>

---

<details>
<summary><strong>7. Windows-Ereignisse nach Zeitfenster filtern</strong></summary>

**Ereignisse der letzten Stunde:**

```powershell
[RO] $startTime = (Get-Date).AddHours(-1)

Get-WinEvent -FilterHashtable @{
    LogName   = "System"
    StartTime = $startTime
} |
    Select-Object TimeCreated,
                  Id,
                  LevelDisplayName,
                  ProviderName,
                  Message
```

**Festes Zeitfenster verwenden:**

```powershell
[RO] $startTime = Get-Date "2026-07-31 09:10:00"
$endTime   = Get-Date "2026-07-31 09:20:00"

Get-WinEvent -FilterHashtable @{
    LogName   = "System"
    StartTime = $startTime
    EndTime   = $endTime
} |
    Select-Object TimeCreated,
                  Id,
                  LevelDisplayName,
                  ProviderName,
                  Message
```

**System- und Anwendungsprotokoll gemeinsam durchsuchen:**

```powershell
[RO] Get-WinEvent -FilterHashtable @{
    LogName   = "System", "Application"
    StartTime = $startTime
    EndTime   = $endTime
} |
    Sort-Object TimeCreated |
    Select-Object TimeCreated,
                  LogName,
                  Id,
                  LevelDisplayName,
                  ProviderName,
                  Message
```

> Die Uhrzeitangaben werden im Kontext des ausführenden Systems interpretiert. Zeitzone und Uhrzeitsynchronisation müssen deshalb vor der Korrelation geklärt sein.

</details>

---

<details>
<summary><strong>8. Windows-Ereignisse nach Quelle, ID und Schweregrad filtern</strong></summary>

**Nach Ereignisanbieter filtern:**

```powershell
[RO] Get-WinEvent -FilterHashtable @{
    LogName      = "System"
    ProviderName = "Service Control Manager"
    StartTime    = (Get-Date).AddHours(-2)
}
```

**Nach bestimmten Ereignis-IDs filtern:**

```powershell
[RO] Get-WinEvent -FilterHashtable @{
    LogName      = "System"
    ProviderName = "Service Control Manager"
    Id           = 7000, 7001, 7031, 7034
    StartTime    = (Get-Date).AddHours(-24)
} |
    Select-Object TimeCreated, Id, LevelDisplayName, Message
```

**Nur kritische Ereignisse und Fehler anzeigen:**

```powershell
[RO] Get-WinEvent -FilterHashtable @{
    LogName   = "System"
    Level     = 1, 2
    StartTime = (Get-Date).AddHours(-2)
}
```

Übliche Windows-Ereignisebenen:

| Zahlenwert | Ebene |
|---:|---|
| `1` | Kritisch |
| `2` | Fehler |
| `3` | Warnung |
| `4` | Information |
| `5` | Ausführlich |

> Ereignis-IDs sind nur zusammen mit Anbieter und Protokoll eindeutig zu bewerten. Dieselbe ID kann bei unterschiedlichen Anbietern eine andere Bedeutung besitzen.

</details>

---

<details>
<summary><strong>9. Typische Windows-Dienstereignisse einordnen</strong></summary>

Häufig relevante Ereignisse des Service Control Managers sind:

| Ereignis-ID | Typische Bedeutung |
|---:|---|
| `7000` | Dienst konnte nicht gestartet werden |
| `7001` | Abhängiger Dienst oder Abhängigkeitsgruppe konnte nicht gestartet werden |
| `7009` | Zeitüberschreitung beim Warten auf eine Dienstverbindung |
| `7011` | Zeitüberschreitung bei einer Diensttransaktion |
| `7023` | Dienst wurde mit einem Fehler beendet |
| `7024` | Dienst wurde mit einem dienstspezifischen Fehler beendet |
| `7031` | Dienst wurde unerwartet beendet; Wiederherstellungsaktion kann folgen |
| `7034` | Dienst wurde unerwartet beendet |
| `7035` | Steuerbefehl wurde an einen Dienst gesendet |
| `7036` | Dienst wechselte in einen anderen Zustand |
| `7040` | Startart wurde geändert |
| `7045` | Ein Dienst wurde im System installiert |

**Wichtig:**

- Die konkrete Nachricht muss immer mitgelesen werden.
- Die Bedeutung muss bei Bedarf anhand der Microsoft-Dokumentation und des betroffenen Produkts geprüft werden.
- Ein Service-Control-Manager-Ereignis kann nur die Auswirkung eines internen Anwendungsfehlers melden.
- Für die eigentliche Ursache muss häufig zusätzlich das Anwendungsprotokoll untersucht werden.

</details>

---

<details>
<summary><strong>10. Windows-Ereignisse nach Nachrichtentext durchsuchen</strong></summary>

**Nach einem Dienstnamen innerhalb eines begrenzten Zeitraums suchen:**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = "System", "Application"
    StartTime = (Get-Date).AddHours(-2)
} |
    Where-Object Message -Match "<DIENSTNAME>" |
    Select-Object TimeCreated,
                  LogName,
                  Id,
                  LevelDisplayName,
                  ProviderName,
                  Message
```

**Nach einem Fehlercode suchen:**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = "System", "Application"
    StartTime = (Get-Date).AddHours(-24)
} |
    Where-Object Message -Match "<FEHLERCODE>"
```

> Textfilter mit `Where-Object` werden erst nach dem Lesen der Ereignisse angewendet und können bei großen Protokollen langsam sein. Zeitfenster, Protokoll und Anbieter sollten deshalb bereits serverseitig mit `FilterHashtable` eingeschränkt werden.

</details>

---

<details>
<summary><strong>11. Windows-Ereignisse mit wevtutil prüfen und sichern</strong></summary>

**Informationen zu einem Protokoll anzeigen:**

```powershell
[RO] wevtutil get-log "System"
```

Kurzform:

```powershell
[RO] wevtutil gl "System"
```

**Die letzten Ereignisse eines Protokolls abfragen:**

```powershell
[RO] wevtutil query-events "System" /count:20 /reverse-direction:true /format:text
```

Kurzform:

```powershell
[RO] wevtutil qe "System" /c:20 /rd:true /f:text
```

**Ein vollständiges Ereignisprotokoll exportieren:**

```powershell
[RO][FILE][SENS][PRIV] wevtutil export-log `
    "System" `
    "<AUSGABEDATEI>.evtx"
```

Kurzform:

```powershell
[RO][FILE][SENS][PRIV] wevtutil epl "System" "<AUSGABEDATEI>.evtx"
```

> Eine EVTX-Datei kann Benutzernamen, Rechnernamen, interne Pfade, IP-Adressen und sicherheitsrelevante Ereignisse enthalten. Sie darf nur kontrolliert weitergegeben werden.

</details>

---

<details>
<summary><strong>12. Linux-Journal eines Dienstes anzeigen</strong></summary>

**Gesamtes Journal einer systemd-Unit anzeigen:**

```bash
[RO][SENS][PRIV] sudo journalctl -u "<DIENST>" --no-pager
```

**Neueste Einträge zuerst anzeigen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  --reverse \
  --no-pager
```

**Letzte 100 Einträge anzeigen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  -n 100 \
  --no-pager
```

**Nur Ereignisse des aktuellen Systemstarts:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -b \
  -u "<DIENST>" \
  --no-pager
```

**Ereignisse des vorherigen Systemstarts:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -b -1 \
  -u "<DIENST>" \
  --no-pager
```

> Ob Ereignisse früherer Systemstarts verfügbar sind, hängt von der Journal-Konfiguration und Aufbewahrung ab.

</details>

---

<details>
<summary><strong>13. Linux-Journal nach Zeitfenster filtern</strong></summary>

**Ereignisse seit einer festen Uhrzeit:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  --since "2026-07-31 09:10:00" \
  --no-pager
```

**Festes Start- und Endzeitfenster:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  --since "2026-07-31 09:10:00" \
  --until "2026-07-31 09:20:00" \
  --no-pager
```

**Relative Zeitangabe:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  --since "1 hour ago" \
  --no-pager
```

**Alle Ereignisse des heutigen Tages:**

```bash
[RO][SENS][PRIV] sudo journalctl --since today --no-pager
```

**Zeitstempel mit ISO-Datum ausgeben:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  --since "1 hour ago" \
  --output=short-iso \
  --no-pager
```

</details>

---

<details>
<summary><strong>14. Linux-Journal nach Priorität filtern</strong></summary>

Übliche syslog-Prioritäten:

| Wert | Name | Bedeutung |
|---:|---|---|
| `0` | `emerg` | System unbenutzbar |
| `1` | `alert` | Sofortige Maßnahme erforderlich |
| `2` | `crit` | Kritischer Zustand |
| `3` | `err` | Fehler |
| `4` | `warning` | Warnung |
| `5` | `notice` | Bedeutender normaler Zustand |
| `6` | `info` | Information |
| `7` | `debug` | Debugmeldung |

**Fehler und schwerwiegendere Meldungen eines Dienstes:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  -p err \
  --since "1 hour ago" \
  --no-pager
```

**Warnungen und schwerwiegendere Meldungen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  -p warning \
  --since "1 hour ago" \
  --no-pager
```

**Nur einen bestimmten Prioritätsbereich verwenden:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  -p warning..err \
  --since "1 hour ago" \
  --no-pager
```

> Nicht jede Anwendung verwendet Prioritäten korrekt. Eine relevante Fehlermeldung kann deshalb als `info` oder ohne geeignete Priorität protokolliert worden sein.

</details>

---

<details>
<summary><strong>15. Linux-Journal nach Prozess oder Kennung filtern</strong></summary>

**Nach Prozess-ID filtern:**

```bash
[RO][SENS][PRIV] sudo journalctl _PID=<PID> --no-pager
```

**Nach ausführbarer Datei filtern:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  _EXE="<VOLLSTÄNDIGER_PROGRAMMPFAD>" \
  --no-pager
```

**Nach syslog-Kennung filtern:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -t "<KENNUNG>" \
  --no-pager
```

**Felder eines Ereignisses ausführlich anzeigen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  -n 20 \
  -o verbose \
  --no-pager
```

Mögliche strukturierte Felder:

```text
_SYSTEMD_UNIT
_PID
_UID
_GID
_EXE
_COMM
_HOSTNAME
SYSLOG_IDENTIFIER
PRIORITY
MESSAGE
```

> PID-Filter sind nur für die Lebensdauer der jeweiligen Prozessinstanz geeignet. Nach einem Neustart besitzt der Dienst möglicherweise eine neue PID.

</details>

---

<details>
<summary><strong>16. Linux-Kernel- und Bootmeldungen prüfen</strong></summary>

**Kernelmeldungen des aktuellen Systemstarts:**

```bash
[RO][SENS][PRIV] sudo journalctl -k -b --no-pager
```

**Kernelwarnungen und schwerwiegendere Meldungen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -k \
  -b \
  -p warning \
  --no-pager
```

**Alle Meldungen des aktuellen Systemstarts:**

```bash
[RO][SENS][PRIV] sudo journalctl -b --no-pager
```

**Verfügbare Systemstarts anzeigen:**

```bash
[RO] journalctl --list-boots
```

**Relevante Kernelhinweise können sein:**

- Datenträger- und Dateisystemfehler,
- Netzwerkadapterfehler,
- Speichermangel,
- Prozessbeendigung durch den Out-of-Memory-Mechanismus,
- Treiberprobleme,
- schreibgeschützte Dateisysteme,
- blockierte Aufgaben,
- Hardwarefehler.

</details>

---

<details>
<summary><strong>17. Linux-Journal live beobachten</strong></summary>

**Neue Ereignisse eines Dienstes live anzeigen:**

```bash
[TEST][SENS][PRIV] sudo journalctl \
  -f \
  -u "<DIENST>"
```

**Mit bestehenden letzten Zeilen beginnen:**

```bash
[TEST][SENS][PRIV] sudo journalctl \
  -n 50 \
  -f \
  -u "<DIENST>"
```

**Nur Warnungen und schwerwiegendere Meldungen verfolgen:**

```bash
[TEST][SENS][PRIV] sudo journalctl \
  -f \
  -u "<DIENST>" \
  -p warning
```

**Vorgehen beim kontrollierten Live-Test:**

```text
1. Live-Ansicht starten
2. Genauen Startzeitpunkt notieren
3. Eine einzelne Testaktion ausführen
4. Neue Ereignisse beobachten
5. Testaktion und Ereignisse zeitlich zuordnen
6. Live-Ansicht mit Strg+C beenden
7. Relevante Meldungen dokumentieren
```

> Live-Logging kann große Mengen ausgeben. Der Filter sollte vor dem Test möglichst eng gesetzt werden.

</details>

---

<details>
<summary><strong>18. Linux-Journalgröße und Aufbewahrung prüfen</strong></summary>

**Belegten Speicherplatz des Journals anzeigen:**

```bash
[RO] journalctl --disk-usage
```

**Verfügbare Systemstarts anzeigen:**

```bash
[RO] journalctl --list-boots
```

**Journal-Konfiguration lesen:**

```bash
[RO][FILE] systemd-analyze cat-config systemd/journald.conf
```

Wichtige Konfigurationsbereiche können sein:

```text
Storage
SystemMaxUse
RuntimeMaxUse
MaxRetentionSec
MaxFileSec
RateLimitIntervalSec
RateLimitBurst
```

**Mögliche Gründe für fehlende alte Einträge:**

- Journal wird nur flüchtig gespeichert,
- Größenbegrenzung wurde erreicht,
- Aufbewahrungszeit ist abgelaufen,
- System wurde neu gestartet,
- Protokollrotation hat alte Daten entfernt,
- Rate-Limiting hat Meldungen unterdrückt,
- Anwendung schrieb in eine andere Datei,
- Dienst startete in einem Container mit eigener Protokollierung.

> Aufbewahrungseinstellungen dürfen nicht während einer Störung ungeprüft verändert werden. Zuerst muss der aktuelle Zustand dokumentiert werden.

</details>

---

<details>
<summary><strong>19. Textbasierte Linux-Anwendungsprotokolle prüfen</strong></summary>

Der tatsächliche Protokollpfad muss aus Herstellerdokumentation oder effektiver Konfiguration ermittelt werden.

**Letzte Zeilen einer bekannten Protokolldatei:**

```bash
[RO][FILE][SENS][PRIV] sudo tail -n 100 "<PROTOKOLLDATEI>"
```

**Neue Einträge live verfolgen:**

```bash
[TEST][FILE][SENS][PRIV] sudo tail -F "<PROTOKOLLDATEI>"
```

**Nach einem festen Text suchen:**

```bash
[RO][FILE][SENS][PRIV] sudo grep \
  -n \
  -i \
  -- "<SUCHTEXT>" \
  "<PROTOKOLLDATEI>"
```

**Komprimierte rotierte Protokolle durchsuchen:**

```bash
[RO][FILE][SENS][PRIV] sudo zgrep \
  -n \
  -i \
  -- "<SUCHTEXT>" \
  "<PROTOKOLLDATEI>.gz"
```

**Datei kontrolliert mit Pager öffnen:**

```bash
[RO][FILE][SENS][PRIV] sudo less "<PROTOKOLLDATEI>"
```

Nützliche Tasten in `less`:

| Taste | Funktion |
|---|---|
| `/Text` | Vorwärts suchen |
| `?Text` | Rückwärts suchen |
| `n` | Nächster Treffer |
| `N` | Vorheriger Treffer |
| `G` | Dateiende |
| `g` | Dateianfang |
| `q` | Beenden |

> Keine angenommenen Standardpfade verwenden. Container, Pakete und Hersteller können unterschiedliche Protokollziele konfigurieren.

</details>

---

<details>
<summary><strong>20. macOS Unified Logging nach Zeitraum auswerten</strong></summary>

**Meldungen der letzten Stunde anzeigen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --style compact \
  --no-pager
```

**Meldungen seit dem letzten Systemstart:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last boot \
  --style compact \
  --no-pager
```

**Festes Zeitfenster verwenden:**

```bash
[RO][SENS][PRIV] sudo log show \
  --start "2026-07-31 09:10:00" \
  --end "2026-07-31 09:20:00" \
  --style compact \
  --no-pager
```

**Lokale Zeitzone ausdrücklich verwenden:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --timezone local \
  --style compact \
  --no-pager
```

> Standardmäßig zeigt `log show` nicht zwingend alle Info- und Debugmeldungen. Diese Ebenen werden bei Bedarf ausdrücklich aktiviert.

</details>

---

<details>
<summary><strong>21. macOS-Protokolle nach Prozess filtern</strong></summary>

**Nach Prozessnamen filtern:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'process == "<PROZESS>"' \
  --style compact \
  --no-pager
```

**Nach Prozess-ID filtern:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'processIdentifier == <PID>' \
  --style compact \
  --no-pager
```

**Info-Meldungen einschließen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --info \
  --predicate 'process == "<PROZESS>"' \
  --style compact \
  --no-pager
```

**Info- und Debugmeldungen einschließen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --info \
  --debug \
  --predicate 'process == "<PROZESS>"' \
  --style compact \
  --no-pager
```

> Die Erhöhung des sichtbaren Umfangs kann sehr große Ausgaben erzeugen. Zuerst sollte mit engem Zeitfenster und Prozessfilter gearbeitet werden.

</details>

---

<details>
<summary><strong>22. macOS-Protokolle nach Subsystem und Schweregrad filtern</strong></summary>

**Nach bekanntem Subsystem filtern:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'subsystem == "<SUBSYSTEM>"' \
  --style compact \
  --no-pager
```

**Fehler und Faults eines Prozesses anzeigen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'process == "<PROZESS>" AND (messageType == error OR messageType == fault)' \
  --style compact \
  --no-pager
```

**Nach Text innerhalb der Meldung suchen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'eventMessage CONTAINS[c] "<SUCHTEXT>"' \
  --style compact \
  --no-pager
```

Wichtige Filterfelder:

| Feld | Bedeutung |
|---|---|
| `process` | Name des erzeugenden Prozesses |
| `processIdentifier` | PID |
| `subsystem` | Logisches Subsystem |
| `category` | Kategorie innerhalb des Subsystems |
| `messageType` | Meldungstyp |
| `eventMessage` | Meldungstext |
| `sender` | Bibliothek oder ausführende Komponente |
| `processImagePath` | Programmpfad |

</details>

---

<details>
<summary><strong>23. macOS-Protokolle live beobachten</strong></summary>

**Meldungen eines Prozesses live verfolgen:**

```bash
[TEST][SENS][PRIV] sudo log stream \
  --predicate 'process == "<PROZESS>"' \
  --style compact
```

**Fehler und Faults live verfolgen:**

```bash
[TEST][SENS][PRIV] sudo log stream \
  --predicate 'process == "<PROZESS>" AND (messageType == error OR messageType == fault)' \
  --style compact
```

**Live-Ausgabe zeitlich begrenzen:**

```bash
[TEST][SENS][PRIV] sudo log stream \
  --timeout 5m \
  --predicate 'process == "<PROZESS>"' \
  --style compact
```

**Info-Ebene einbeziehen:**

```bash
[TEST][SENS][PRIV] sudo log stream \
  --level info \
  --predicate 'process == "<PROZESS>"' \
  --style compact
```

> Der Befehl wird ohne Zeitbegrenzung mit `Strg+C` beendet. Eine zeitliche Begrenzung verhindert versehentlich lange laufende Mitschnitte.

</details>

---

<details>
<summary><strong>24. macOS-Protokollarchiv sichern</strong></summary>

**Protokolle der letzten Stunde in ein Logarchiv sammeln:**

```bash
[RO][FILE][SENS][PRIV] sudo log collect \
  --last 1h \
  --output "<AUSGABEDATEI>.logarchive"
```

**Protokolle ab einem festen Zeitpunkt sammeln:**

```bash
[RO][FILE][SENS][PRIV] sudo log collect \
  --start "2026-07-31 09:10:00" \
  --output "<AUSGABEDATEI>.logarchive"
```

Ein `.logarchive` kann später mit der App „Konsole“ oder mit `log show` ausgewertet werden.

**Archiv über die Kommandozeile lesen:**

```bash
[RO][FILE][SENS] log show \
  --archive "<AUSGABEDATEI>.logarchive" \
  --style compact \
  --no-pager
```

> Ein vollständiges macOS-Logarchiv kann umfangreiche und sensible Systeminformationen enthalten. Vor einer externen Weitergabe müssen Zweck, Empfänger und Datenschutz geprüft werden.

</details>

---

<details>
<summary><strong>25. Anwendungsprotokolle unter Windows und macOS berücksichtigen</strong></summary>

Nicht jede Anwendung verwendet ausschließlich das zentrale Systemprotokoll.

Mögliche Protokollziele:

- Windows-Anwendungsprotokoll,
- eigenes Windows-Ereignisprotokoll,
- macOS Unified Logging,
- Textdatei,
- JSON-Datei,
- Datenbank,
- Container-Standardausgabe,
- zentraler Syslog-Server,
- SIEM- oder Monitoringplattform,
- herstellerspezifisches Diagnosepaket.

**Protokollpfad korrekt ermitteln über:**

1. Herstellerdokumentation,
2. wirksame Dienstkonfiguration,
3. Startparameter,
4. Umgebungsvariablen,
5. Dienstkonto,
6. Containerdefinition,
7. Protokollierungs- oder Loggingabschnitt der Anwendung.

> Keine Verzeichnisse oder Dateinamen als gegeben annehmen. Der wirksame Pfad kann durch Installation, Paketierung oder lokale Konfiguration verändert worden sein.

</details>

---

<details>
<summary><strong>26. Containerprotokolle berücksichtigen</strong></summary>

Bei containerisierten Diensten können Protokolle an mehreren Stellen entstehen:

```text
Hostbetriebssystem
  → Container-Runtime
  → Container
  → Prozess im Container
  → Anwendung
  → externes zentrales Logging
```

Mögliche Protokollquellen:

- Runtime-Ereignisse auf dem Host,
- Standardausgabe und Standardfehler des Containers,
- an ein Volume gebundene Anwendungsprotokolle,
- Reverse-Proxy-Protokolle,
- Datenbankprotokolle,
- Orchestrator-Ereignisse,
- Healthcheck-Ausgaben.

**Prüffragen:**

- Wurde der Container neu erstellt?
- Ist die Container-ID gewechselt?
- Wurden alte Containerprotokolle entfernt?
- Schreibt die Anwendung in die Standardausgabe oder in eine Datei?
- Ist das Logverzeichnis dauerhaft eingebunden?
- Gibt es Größenbegrenzung und Rotation?
- Werden Protokolle an einen zentralen Dienst weitergeleitet?
- Enthält die Ausgabe Secrets oder personenbezogene Daten?

> Die konkrete Runtime wird in dieser Seite nicht vorausgesetzt. Die passenden Befehle müssen anhand der tatsächlich eingesetzten Containerplattform ausgewählt werden.

</details>

---

<details>
<summary><strong>27. Protokolle mehrerer Systeme zeitlich korrelieren</strong></summary>

Beispiel:

| Zeit | System | Ereignis |
|---|---|---|
| 09:14:58 | Datenbankserver | Datenträger meldet Schreibfehler |
| 09:15:00 | Datenbankserver | Datenbank beendet Schreibtransaktion mit Fehler |
| 09:15:02 | Anwendungsserver | Datenbankverbindung wird zurückgesetzt |
| 09:15:03 | Webserver | Backend antwortet nicht |
| 09:15:04 | Client | HTTP 503 wird angezeigt |

**Wahrscheinliche Ereigniskette:**

```text
Datenträgerfehler
  → Datenbankfehler
  → Verbindung des Anwendungsservers bricht ab
  → Webserver erhält keine gültige Backendantwort
  → Benutzer sieht HTTP 503
```

**Vorgehen:**

1. Alle Zeitstempel in dieselbe Zeitzone überführen.
2. Erstes technisches Ereignis bestimmen.
3. Vorhergehende Warnungen berücksichtigen.
4. Fehler auf Quell- und Zielsystem vergleichen.
5. Verbindungs- oder Korrelations-IDs verwenden.
6. Ursache und Folge in einer Zeitleiste dokumentieren.
7. Hypothese mit technischen Tests bestätigen.

</details>

---

<details>
<summary><strong>28. Fehlercodes richtig auswerten</strong></summary>

Ein Fehlercode sollte zusammen mit folgendem Kontext dokumentiert werden:

```text
Betriebssystem:
Produkt:
Komponente:
Version:
Protokoll:
Ereignisanbieter:
Ereignis-ID:
Fehlercode:
Vollständige Meldung:
Zeitpunkt:
Auslösende Aktion:
```

**Regeln:**

- Code vollständig übernehmen,
- hexadezimale und dezimale Schreibweise nicht verwechseln,
- Anbieter und Produktversion notieren,
- nur offizielle Herstellerdokumentation als gesicherte Bedeutung behandeln,
- nicht denselben Code aus einem anderen Produkt übertragen,
- innere oder verschachtelte Fehlermeldungen mit erfassen,
- Ursache erst nach Prüfung festlegen.

> Eine Suchmaschinenfundstelle ohne passenden Hersteller-, Versions- und Komponentenkontext ist kein ausreichender Ursachenbeweis.

</details>

---

<details>
<summary><strong>29. Fehlende Protokolle richtig bewerten</strong></summary>

Keine gefundene Meldung bedeutet nicht automatisch, dass kein Fehler auftrat.

Mögliche Gründe:

- falsches Zeitfenster,
- falsche Zeitzone,
- falscher Server,
- falsches Protokoll,
- falscher Prozessname,
- Dienst wurde mit neuer PID gestartet,
- Protokollierung ist deaktiviert,
- Aufbewahrung ist abgelaufen,
- Logrotation hat die Datei verschoben,
- Rate-Limiting unterdrückte Meldungen,
- Anwendung schreibt in eine andere Datei,
- Meldung wurde nur auf dem Backend erzeugt,
- Debugebene war nicht aktiviert,
- Container wurde entfernt,
- Dienst stürzte vor Initialisierung der Protokollierung ab,
- Berechtigung zum Lesen fehlt.

> Das Fehlen einer Meldung ist nur dann aussagekräftig, wenn bekannt ist, dass genau dieses Ereignis an dieser Stelle protokolliert werden müsste.

</details>

---

<details>
<summary><strong>30. Sensible Inhalte in Protokollen erkennen</strong></summary>

Protokolle können enthalten:

- Benutzernamen,
- E-Mail-Adressen,
- IP-Adressen,
- interne Servernamen,
- Dateipfade,
- Dokumentnamen,
- Datenbankabfragen,
- URL-Parameter,
- Sitzungscookies,
- Zugriffstoken,
- API-Schlüssel,
- Authorization-Header,
- personenbezogene Daten,
- interne Geschäfts- und Systeminformationen.

**Vor Weitergabe prüfen:**

```text
[ ] Zweck der Weitergabe geklärt
[ ] Empfänger berechtigt
[ ] Zeitraum auf das Notwendige begrenzt
[ ] Nicht relevante Ereignisse entfernt
[ ] Kennwörter und Token entfernt
[ ] Cookies und Authorization-Header entfernt
[ ] Personenbezogene Daten geschützt
[ ] Interne Infrastrukturinformationen bewertet
[ ] Originaldatei beweissicher aufbewahrt
[ ] Bearbeitete Kopie als solche gekennzeichnet
```

> Das Original darf bei einer Beweissicherung nicht unkontrolliert verändert werden. Für Weitergaben wird eine gesonderte bereinigte Kopie erstellt.

</details>

---

<details>
<summary><strong>31. Relevante Protokollstellen dokumentieren</strong></summary>

**Dokumentationsvorlage:**

```text
Störung:
Server:
Dienst:
Betriebssystem:
Zeitzone:
Untersuchter Zeitraum:
Protokollquelle:
Ereignisanbieter beziehungsweise Prozess:
Ereignis-ID:
Fehlercode:
Zeitstempel:
Vollständige relevante Meldung:
Unmittelbar vorhergehendes Ereignis:
Unmittelbar folgendes Ereignis:
Betroffene Abhängigkeit:
Interpretation:
Beleg für die Interpretation:
Nächster Prüfschritt:
```

**Gute Dokumentation:**

> Um 09:15:02 Uhr protokollierte der Anwendungsdienst eine zurückgesetzte Datenbankverbindung. Zwei Sekunden zuvor meldete der Datenbankserver einen Schreibfehler. Die zeitliche Reihenfolge spricht für einen Zusammenhang, der durch Datenträger- und Datenbankprüfung bestätigt werden muss.

**Unzureichende Dokumentation:**

> In den Logs stand etwas mit Datenbank.

</details>

---

<details>
<summary><strong>32. Typische Fehler bei der Protokollanalyse</strong></summary>

| Fehler | Folge | Bessere Vorgehensweise |
|---|---|---|
| Gesamtes Protokoll ohne Zeitfilter lesen | Relevante Ereignisse gehen in Datenmenge unter | Enges Zeitfenster verwenden |
| Nur Fehlerstufe anzeigen | Relevante Warnungen oder Infos fehlen | Kontext vor und nach dem Fehler lesen |
| Nur Hauptserver prüfen | Backendursache bleibt verborgen | Abhängige Systeme einbeziehen |
| Neueste Meldung als Ursache behandeln | Folgefehler wird verwechselt | Zeitlich erstes relevantes Ereignis suchen |
| Ereignis-ID ohne Anbieter bewerten | Falsche Bedeutung möglich | Anbieter, Protokoll und Version notieren |
| Zeitzonen ignorieren | Ereigniskette wird falsch sortiert | Zeitstempel normalisieren |
| Debuglogging dauerhaft aktivieren | Datenmenge und Datenschutzrisiko steigen | Nur kontrolliert und zeitlich begrenzt |
| Protokoll während Störung löschen | Beweise gehen verloren | Nur lesen und sichern |
| Vollständiges Archiv ungeprüft versenden | Sensible Daten werden offengelegt | Bereinigte Kopie erstellen |
| Einzelne Meldung ohne Funktionstest bewerten | Hypothese bleibt unbestätigt | Gezielten Test durchführen |

</details>

---

<details>
<summary><strong>33. Checkliste zur Protokollanalyse</strong></summary>

```text
[ ] Störung und auslösende Aktion eindeutig beschrieben
[ ] Server und Dienst bestätigt
[ ] Beginn und Ende des Fehlers bestimmt
[ ] Zeitzonen aller beteiligten Systeme geprüft
[ ] Zeitfenster einige Minuten erweitert
[ ] Betriebssystemprotokoll geprüft
[ ] Dienst- beziehungsweise Anwendungsprotokoll geprüft
[ ] Ereignisanbieter oder Prozess gefiltert
[ ] Ereignis-ID und Fehlercode erfasst
[ ] Meldungen unmittelbar vor dem Fehler gelesen
[ ] Meldungen unmittelbar nach dem Fehler gelesen
[ ] Abhängige Systeme geprüft
[ ] Ursache und Folge getrennt
[ ] Prozessneustart und PID-Wechsel berücksichtigt
[ ] Protokollaufbewahrung und Rotation geprüft
[ ] Fehlende Meldungen nicht vorschnell bewertet
[ ] Relevante Protokolle gesichert
[ ] Sensible Inhalte vor Weitergabe entfernt
[ ] Hypothese durch einen technischen Test geprüft
[ ] Ergebnis und nächster Schritt dokumentiert
```

</details>

---

**Bewertung des Ergebnisses**

| Ergebnis | Nächster Schritt |
|---|---|
| Dienst konnte nicht gestartet werden | Exitcode, Konto, Pfad und Konfiguration prüfen |
| Dienst wurde unerwartet beendet | Absturzbericht, Ressourcen und Wiederherstellungsaktion prüfen |
| Abhängigkeit ist nicht erreichbar | DNS-, Netzwerk-, Port- und Backendprüfung durchführen |
| Zugriff wurde verweigert | Dienstkonto, Datei- und Systemberechtigungen prüfen |
| Speicher- oder Datenträgerfehler vorhanden | Ressourcen und Dateisystem untersuchen |
| TLS- oder Zertifikatsfehler vorhanden | Zertifikat, Name, Zeit und Vertrauenskette prüfen |
| Protokoll zeigt Zeitüberschreitung | Zielsystem, Last, Netzwerk und Timeoutursache prüfen |
| Mehrere Systeme zeigen dieselbe Ereigniskette | Gemeinsame Ursache priorisiert untersuchen |
| Keine Meldung gefunden | Zeitfenster, Quelle, Aufbewahrung und Logziel prüfen |
| Protokoll liefert nur einen Folgefehler | Zeitlich frühere Komponente untersuchen |

---

**Merksatz**

> **Ein Protokolleintrag ist ein Beweis für eine aufgezeichnete Beobachtung. Erst Zeitfolge, Systemzusammenhang und ein bestätigender Test machen daraus einen belastbaren Ursachenhinweis.**

---

**Weiterführende Quellen**

- [Microsoft Learn – Get-WinEvent](https://learn.microsoft.com/powershell/module/microsoft.powershell.diagnostics/get-winevent)
- [Microsoft Learn – Erstellen effizienter Ereignisabfragen mit FilterHashtable](https://learn.microsoft.com/powershell/scripting/samples/creating-get-winevent-queries-with-filterhashtable)
- [Microsoft Learn – wevtutil](https://learn.microsoft.com/windows-server/administration/windows-commands/wevtutil)
- [Microsoft Learn – Windows-Ereignisanzeige](https://learn.microsoft.com/shows/inside/event-viewer)
- [systemd – journalctl](https://www.freedesktop.org/software/systemd/man/latest/journalctl.html)
- [systemd – journald.conf](https://www.freedesktop.org/software/systemd/man/latest/journald.conf.html)
- [systemd – systemd-journald.service](https://www.freedesktop.org/software/systemd/man/latest/systemd-journald.service.html)
- [Apple – log-Handbuchseite](https://keith.github.io/xcode-man-pages/log.1.html)
- [Apple – Protokollmeldungen in der Konsole anzeigen](https://support.apple.com/de-de/guide/console/cnsl1012/mac)
- [Apple – Protokollmeldungen und Aktivitäten suchen](https://support.apple.com/de-de/guide/console/cnslbf30b61a/mac)

# 4.7 Dienststartfehler analysieren

Ein Dienststartfehler liegt vor, wenn ein Dienst nicht gestartet werden kann, im Startvorgang hängen bleibt oder unmittelbar nach dem Start wieder beendet wird.

> **Grundsatz:**  
> Nicht mehrfach auf „Starten“ klicken. Zuerst Status, Exitcode, Protokolle und Startkonfiguration sichern, damit die ursprüngliche Fehlerursache nicht durch Folgeereignisse verdeckt wird.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- verschiedene Arten von Dienststartfehlern unterscheiden können,
- Exitcodes und Beendigungsursachen erfassen können,
- Programmpfad und Startparameter prüfen können,
- Fehler des Dienstkontos und der Berechtigungen erkennen können,
- fehlende Abhängigkeiten und Ressourcen identifizieren können,
- Zeitüberschreitungen und sofortige Prozessabbrüche unterscheiden können,
- Startbegrenzungen und Neustartschleifen erkennen können,
- Windows-, systemd- und launchd-Startfehler analysieren können,
- einen kontrollierten Startversuch vorbereiten und auswerten können.

---

<details>
<summary><strong>1. Arten von Dienststartfehlern unterscheiden</strong></summary>

| Fehlerbild | Beschreibung | Mögliche Ursache |
|---|---|---|
| Dienst nicht gefunden | Dienstverwaltung kennt den Namen nicht | Falscher Name, Dienst nicht installiert oder andere Umgebung |
| Dienst deaktiviert | Start wird durch Konfiguration verhindert | Bewusste Deaktivierung oder fehlerhafte Änderung |
| Dienst maskiert | systemd blockiert den Start vollständig | Administrativer Schutz oder fehlerhafte Maskierung |
| Programmdatei fehlt | Angegebene ausführbare Datei ist nicht vorhanden | Unvollständiges Update, Löschung oder falscher Pfad |
| Zugriff verweigert | Dienst darf Programm, Datei oder Ressource nicht verwenden | Konto- oder Berechtigungsfehler |
| Abhängigkeit fehlt | Benötigter Dienst oder Backend ist nicht verfügbar | Dienst-, DNS-, Netzwerk- oder Speicherfehler |
| Start dauert zu lange | Dienst meldet nicht rechtzeitig Betriebsbereitschaft | Blockierte Initialisierung oder langsames Backend |
| Prozess beendet sich sofort | Programm startet und bricht unmittelbar ab | Konfiguration, Portkonflikt oder fehlende Ressource |
| Prozess stürzt ab | Unbehandelte Ausnahme oder schwerer Laufzeitfehler | Softwarefehler, Bibliothek oder inkompatible Version |
| Neustartschleife | Dienst wird automatisch fortlaufend neu gestartet | Wiederherstellungsregel und unveränderte Fehlerursache |
| Startgrenze erreicht | Dienstverwaltung unterbindet weitere Versuche | Zu viele Fehlstarts innerhalb kurzer Zeit |
| Dienst läuft, ist aber nicht bereit | Prozess existiert, Initialisierung ist unvollständig | Backend, Migration, Cache oder Healthcheck |

</details>

---

<details>
<summary><strong>2. Mindestinformationen vor einem neuen Startversuch sichern</strong></summary>

```text
[ ] Datum, Uhrzeit und Zeitzone
[ ] Server und Betriebssystem
[ ] Interner Dienstname beziehungsweise launchd-Label
[ ] Aktueller Dienststatus
[ ] Startart beziehungsweise Aktivierungszustand
[ ] Prozess-ID, falls vorhanden
[ ] Letzter Exitcode
[ ] Dienstspezifischer Exitcode
[ ] Programmpfad und Startparameter
[ ] Dienstkonto
[ ] Formale Abhängigkeiten
[ ] Wiederherstellungs- und Neustartregeln
[ ] Relevante Systemprotokolle
[ ] Relevante Anwendungsprotokolle
[ ] Letzte Konfigurations- oder Softwareänderung
```

> Erst nach dieser Sicherung sollte ein weiterer kontrollierter Startversuch durchgeführt werden.

</details>

---

<details>
<summary><strong>3. Allgemeiner Diagnoseweg bei Startfehlern</strong></summary>

```text
Dienst vorhanden?
  ↓
Aktiviert und nicht blockiert?
  ↓
Programmpfad vorhanden?
  ↓
Startkonfiguration syntaktisch gültig?
  ↓
Dienstkonto gültig?
  ↓
Datei- und Verzeichnisrechte ausreichend?
  ↓
Abhängigkeiten verfügbar?
  ↓
Port und andere Ressourcen verfügbar?
  ↓
Prozess startet?
  ↓
Prozess bleibt aktiv?
  ↓
Dienst meldet Betriebsbereitschaft?
  ↓
Anwendungstest erfolgreich?
```

**Empfohlene Reihenfolge:**

1. Exakten Dienstnamen bestätigen.
2. Aktuellen Status erfassen.
3. Exitcode und Protokolle sichern.
4. Startart und Blockierungen prüfen.
5. Programmpfad und Argumente kontrollieren.
6. Dienstkonto und Berechtigungen prüfen.
7. Abhängigkeiten testen.
8. Portkonflikte und Ressourcen prüfen.
9. Konfiguration mit Herstellerwerkzeug validieren.
10. Einen einzelnen kontrollierten Startversuch durchführen.
11. Protokolle während dieses Versuchs beobachten.
12. Ergebnis dokumentieren und erneut bewerten.

</details>

---

<details>
<summary><strong>4. Windows-Dienststatus und Exitcodes erfassen</strong></summary>

**Grundlegenden Dienststatus anzeigen:**

```powershell
[RO] Get-Service -Name "<DIENSTNAME>"
```

**Erweiterte Dienstinformationen anzeigen:**

```powershell
[RO] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name,
                  DisplayName,
                  State,
                  Status,
                  StartMode,
                  StartName,
                  ProcessId,
                  ExitCode,
                  ServiceSpecificExitCode
```

**Status mit `sc.exe` prüfen:**

```powershell
[RO] sc.exe queryex "<DIENSTNAME>"
```

Wichtige Angaben:

| Angabe | Bedeutung |
|---|---|
| `STATE` | Aktueller Dienstzustand |
| `WIN32_EXIT_CODE` | Windows- beziehungsweise Dienstausgangscode |
| `SERVICE_EXIT_CODE` | Dienstspezifischer Ausgangscode |
| `CHECKPOINT` | Fortschrittswert bei längeren Zustandswechseln |
| `WAIT_HINT` | Vom Dienst geschätzte Wartezeit |
| `PID` | Aktuelle Prozess-ID, sofern vorhanden |

> Ein Exitcode `0` ist nur dann aussagekräftig, wenn der Dienst regulär beendet wurde. Ein Dienst kann trotzdem seine vorgesehene Funktion nicht bereitgestellt haben.

</details>

---

<details>
<summary><strong>5. Windows-Startkonfiguration prüfen</strong></summary>

**Konfiguration des Dienstes anzeigen:**

```powershell
[RO][SENS] sc.exe qc "<DIENSTNAME>"
```

**Konfiguration über CIM anzeigen:**

```powershell
[RO][SENS] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name,
                  StartMode,
                  StartName,
                  PathName,
                  ServiceType,
                  DesktopInteract
```

Zu prüfen sind:

| Feld | Prüffrage |
|---|---|
| `BINARY_PATH_NAME` beziehungsweise `PathName` | Ist der Programmpfad korrekt? |
| Startparameter | Sind Argumente vollständig und korrekt maskiert? |
| `SERVICE_START_NAME` beziehungsweise `StartName` | Wird das vorgesehene Dienstkonto verwendet? |
| `START_TYPE` beziehungsweise `StartMode` | Ist der Dienst deaktiviert? |
| `DEPENDENCIES` | Sind alle formalen Abhängigkeiten vorhanden? |
| `TYPE` beziehungsweise `ServiceType` | Passt die Dienstart zur Anwendung? |

**Wichtig bei Programmpfaden:**

- Programmpfad und Argumente dürfen nicht verwechselt werden.
- Leerzeichen im Pfad erfordern korrekte Anführungszeichen.
- Relative Pfade können im Dienstkontext anders aufgelöst werden.
- Ein Netzlaufwerksbuchstabe aus einer Benutzersitzung steht einem Dienst normalerweise nicht automatisch zur Verfügung.
- Das Dienstkonto muss auf Programm, Arbeitsverzeichnis und Konfiguration zugreifen können.

</details>

---

<details>
<summary><strong>6. Windows-Programmpfad kontrolliert prüfen</strong></summary>

Da `PathName` auch Argumente enthalten kann, darf die gesamte Zeichenfolge nicht ungeprüft an `Test-Path` übergeben werden.

**Konfigurierte Zeichenfolge zunächst nur anzeigen:**

```powershell
[RO][SENS] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name, PathName
```

Anschließend wird der tatsächliche ausführbare Pfad aus der Ausgabe ermittelt und separat geprüft:

```powershell
[RO][FILE] Test-Path -LiteralPath "<AUSFÜHRBARE_DATEI>"
```

**Dateiinformationen anzeigen:**

```powershell
[RO][FILE][SENS] Get-Item -LiteralPath "<AUSFÜHRBARE_DATEI>" |
    Select-Object FullName, Length, CreationTime, LastWriteTime, VersionInfo
```

**Berechtigungen anzeigen:**

```powershell
[RO][FILE][SENS] Get-Acl -LiteralPath "<AUSFÜHRBARE_DATEI>" |
    Format-List
```

Zusätzlich prüfen:

- Ist die Datei tatsächlich vorhanden?
- Wurde sie kürzlich ersetzt oder verschoben?
- Passt die Architektur zum Betriebssystem?
- Sind benötigte Bibliotheken vorhanden?
- Blockiert Sicherheitssoftware die Ausführung?
- Liegt die Datei auf einem beim Start noch nicht verfügbaren Datenträger?
- Ist der Pfad lokal oder von einer Netzwerkressource abhängig?

</details>

---

<details>
<summary><strong>7. Windows-Dienstkonto und Anmelderechte prüfen</strong></summary>

**Dienstkonto anzeigen:**

```powershell
[RO] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name, StartName, State, StartMode
```

Mögliche Kontotypen:

- `LocalSystem`,
- `NT AUTHORITY\LocalService`,
- `NT AUTHORITY\NetworkService`,
- virtuelles Dienstkonto,
- verwaltetes Dienstkonto,
- lokales Benutzerkonto,
- Domänenkonto.

**Zu prüfen:**

- Existiert das Konto?
- Ist es aktiviert oder gesperrt?
- Ist ein hinterlegtes Kennwort abgelaufen oder geändert worden?
- Besitzt es das Recht „Anmelden als Dienst“?
- Darf es die Programmdatei lesen und ausführen?
- Darf es Konfigurations- und Datenverzeichnisse verwenden?
- Darf es Zertifikate und private Schlüssel verwenden?
- Darf es auf Netzwerkressourcen zugreifen?
- Wurde das Konto kürzlich geändert?
- Funktioniert ein verwaltetes Dienstkonto ordnungsgemäß?

> Ein manueller Programmstart als Administrator beweist nicht, dass das Programm unter dem tatsächlichen Dienstkonto funktioniert.

</details>

---

<details>
<summary><strong>8. Typische Windows-Startfehler einordnen</strong></summary>

| Fehler | Typische Bedeutung | Prüfrichtung |
|---|---|---|
| Fehler 2 | Angegebene Datei wurde nicht gefunden | Programmpfad, Bibliothek oder Konfigurationspfad |
| Fehler 5 | Zugriff verweigert | Konto, Rechte oder Sicherheitssoftware |
| Fehler 1068 | Abhängigkeitsdienst oder Abhängigkeitsgruppe konnte nicht gestartet werden | Formale Abhängigkeiten |
| Fehler 1069 | Anmeldung des Dienstkontos fehlgeschlagen | Konto, Kennwort und Anmelderecht |
| Fehler 1053 | Dienst antwortete nicht rechtzeitig auf Start- oder Steuerungsanforderung | Initialisierung, Timeout, Programmfehler |
| Fehler 1067 | Prozess wurde unerwartet beendet | Anwendungsprotokoll, Konfiguration oder Absturz |
| Fehler 1079 | Konto stimmt nicht mit anderen Diensten im gemeinsamen Prozess überein | Dienstkonto und gemeinsam verwendeter Prozess |
| Fehler 193 | Keine gültige Win32-Anwendung | Architektur, Dateityp oder fehlerhafte Programmdatei |

> Die vollständige Fehlermeldung, das betroffene Produkt und die Windows-Version müssen immer mit dokumentiert werden. Die Tabelle ist eine Eingrenzungshilfe, kein Ersatz für die konkrete Herstellerdiagnose.

</details>

---

<details>
<summary><strong>9. Windows-Ereignisse eines Startversuchs auswerten</strong></summary>

**Service-Control-Manager-Ereignisse der letzten Stunde:**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName      = "System"
    ProviderName = "Service Control Manager"
    StartTime    = (Get-Date).AddHours(-1)
} |
    Select-Object TimeCreated,
                  Id,
                  LevelDisplayName,
                  Message
```

**Typische startbezogene Ereignisse filtern:**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName      = "System"
    ProviderName = "Service Control Manager"
    Id           = 7000, 7001, 7009, 7011, 7023, 7024, 7031, 7034
    StartTime    = (Get-Date).AddHours(-24)
} |
    Select-Object TimeCreated, Id, LevelDisplayName, Message
```

**System- und Anwendungsereignisse im festen Zeitfenster verbinden:**

```powershell
[RO][SENS] $startTime = Get-Date "2026-07-31 09:10:00"
$endTime   = Get-Date "2026-07-31 09:20:00"

Get-WinEvent -FilterHashtable @{
    LogName   = "System", "Application"
    StartTime = $startTime
    EndTime   = $endTime
} |
    Sort-Object TimeCreated |
    Select-Object TimeCreated,
                  LogName,
                  ProviderName,
                  Id,
                  LevelDisplayName,
                  Message
```

</details>

---

<details>
<summary><strong>10. Windows-Wiederherstellungsaktionen prüfen</strong></summary>

Ein Dienst kann nach einem Fehlstart oder Absturz automatisch neu gestartet werden.

**Konfigurierte Fehleraktionen anzeigen:**

```powershell
[RO] sc.exe qfailure "<DIENSTNAME>"
```

**Zusätzlichen Fehleraktionsstatus anzeigen:**

```powershell
[RO] sc.exe qfailureflag "<DIENSTNAME>"
```

Mögliche Aktionen:

- keine Aktion,
- Dienst neu starten,
- Programm ausführen,
- Computer neu starten.

**Prüffragen:**

- Wird der Dienst automatisch neu gestartet?
- Nach welcher Wartezeit?
- Wie viele Versuche erfolgen?
- Wann wird der Fehlerzähler zurückgesetzt?
- Wird auch bei einem normalen Prozessende eine Fehleraktion ausgelöst?
- Verändert die Wiederherstellung die sichtbare PID?
- Verdeckt die Automatik einen wiederkehrenden Startfehler?

> Wiederherstellungsregeln dürfen nicht ungeprüft verändert werden. Sie können die Verfügbarkeit und das Verhalten bei Abstürzen erheblich beeinflussen.

</details>

---

<details>
<summary><strong>11. systemd-Status und Startursache unter Linux prüfen</strong></summary>

**Ausführlichen Status anzeigen:**

```bash
[RO][SENS][PRIV] sudo systemctl status "<DIENST>" --no-pager
```

**Wichtige Zustände strukturiert anzeigen:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=LoadState,ActiveState,SubState,UnitFileState,Result,MainPID,ExecMainCode,ExecMainStatus,StatusErrno,NRestarts
```

**Prüfen, ob die Unit aktiviert ist:**

```bash
[RO] systemctl is-enabled "<DIENST>"
```

**Prüfen, ob sie fehlgeschlagen ist:**

```bash
[RO] systemctl is-failed "<DIENST>"
```

**Alle fehlgeschlagenen Units anzeigen:**

```bash
[RO] systemctl --failed --no-pager
```

**Wichtige Angaben:**

| Eigenschaft | Bedeutung |
|---|---|
| `LoadState` | Wurde die Unit korrekt geladen? |
| `ActiveState` | Übergeordneter Aktivzustand |
| `SubState` | Detaillierter Unterzustand |
| `Result` | Ergebnis des letzten Start- oder Laufvorgangs |
| `MainPID` | PID des Hauptprozesses |
| `ExecMainCode` | Art der Prozessbeendigung |
| `ExecMainStatus` | Exitcode oder Signalnummer |
| `StatusErrno` | Gemeldeter Fehlerwert, sofern vorhanden |
| `NRestarts` | Anzahl automatischer Neustarts |

</details>

---

<details>
<summary><strong>12. systemd-Ergebniswerte interpretieren</strong></summary>

Mögliche `Result`-Werte können unter anderem sein:

| Ergebnis | Typische Bedeutung |
|---|---|
| `success` | Vorgang wurde aus Sicht von systemd erfolgreich beendet |
| `exit-code` | Prozess beendete sich mit nicht als erfolgreich bewertetem Exitcode |
| `signal` | Prozess wurde durch ein Signal beendet |
| `core-dump` | Prozess wurde durch Signal beendet und erzeugte einen Core Dump |
| `timeout` | Start-, Stopp- oder Laufzeitgrenze wurde überschritten |
| `watchdog` | Watchdog-Reaktion blieb aus |
| `start-limit-hit` | Zu viele Startversuche in kurzer Zeit |
| `resources` | Benötigte Systemressource konnte nicht bereitgestellt werden |
| `protocol` | Dienst erfüllte das erwartete Startprotokoll nicht |
| `dependency` | Eine benötigte Unit schlug fehl |
| `exec-condition` | Eine konfigurierte Startbedingung verhinderte den Start |

**Beendigungsart:**

| `ExecMainCode` | Grundbedeutung |
|---|---|
| `exited` | Prozess beendete sich über einen Exitcode |
| `killed` | Prozess wurde durch ein Signal beendet |
| `dumped` | Prozess wurde durch Signal beendet und erzeugte möglicherweise einen Dump |

> Die konkrete Bedeutung von `ExecMainStatus` hängt davon ab, ob der Prozess regulär beendet oder durch ein Signal beendet wurde. Zusätzlich muss die Dokumentation des Programms geprüft werden.

</details>

---

<details>
<summary><strong>13. systemd-Unit und wirksame Startparameter prüfen</strong></summary>

**Wirksame Unit einschließlich Drop-ins anzeigen:**

```bash
[RO][FILE][SENS] systemctl cat "<DIENST>"
```

**Wichtige Startparameter strukturiert anzeigen:**

```bash
[RO][SENS] systemctl show "<DIENST>" \
  --property=Type,User,Group,ExecStart,ExecStartPre,ExecStartPost,WorkingDirectory,EnvironmentFiles,FragmentPath,DropInPaths
```

**Unit-Datei formal prüfen:**

```bash
[RO][FILE] systemd-analyze verify "<UNIT-DATEI>"
```

Zu prüfen sind:

- `Type=`,
- `ExecStart=`,
- `ExecStartPre=`,
- `ExecStartPost=`,
- `User=` und `Group=`,
- `WorkingDirectory=`,
- `EnvironmentFile=`,
- `PIDFile=`,
- `RuntimeDirectory=`,
- `StateDirectory=`,
- `TimeoutStartSec=`,
- `Restart=`,
- `RestartSec=`,
- `StartLimitIntervalSec=`,
- `StartLimitBurst=`.

> `systemd-analyze verify` benötigt den tatsächlichen Pfad einer Unit-Datei. Der Pfad sollte mit `systemctl show <DIENST> --property=FragmentPath` ermittelt werden.

</details>

---

<details>
<summary><strong>14. Linux-Programmpfad und Berechtigungen prüfen</strong></summary>

**Konfigurierten Startbefehl anzeigen:**

```bash
[RO][SENS] systemctl show "<DIENST>" --property=ExecStart
```

**Datei des bekannten Programmpfads prüfen:**

```bash
[RO][FILE] stat "<AUSFÜHRBARE_DATEI>"
```

**Dateityp und Architektur prüfen:**

```bash
[RO][FILE] file "<AUSFÜHRBARE_DATEI>"
```

**Berechtigungen aller Pfadbestandteile anzeigen:**

```bash
[RO][FILE] namei -l "<AUSFÜHRBARE_DATEI>"
```

**Dynamische Bibliotheksabhängigkeiten eines geeigneten dynamischen ELF-Programms anzeigen:**

```bash
[RO][FILE][SENS] ldd "<AUSFÜHRBARE_DATEI>"
```

**Wichtiger Sicherheitshinweis:**

`ldd` sollte nicht ungeprüft auf nicht vertrauenswürdige ausführbare Dateien angewendet werden. Abhängig von System und Binärdatei kann die Auswertung Sicherheitsrisiken besitzen.

Alternativ kann bei ELF-Dateien zunächst statisch geprüft werden:

```bash
[RO][FILE] readelf -d "<AUSFÜHRBARE_DATEI>"
```

Zu prüfen:

- Datei vorhanden,
- ausführbar,
- richtige Architektur,
- korrekter Interpreter,
- benötigte Bibliotheken vorhanden,
- Dienstkonto kann alle Pfadbestandteile durchlaufen,
- Arbeitsverzeichnis vorhanden,
- Dateisystem nicht schreibgeschützt,
- Sicherheitsmechanismen wie SELinux oder AppArmor berücksichtigt.

</details>

---

<details>
<summary><strong>15. Linux-Dienstkonto und Dienstkontext prüfen</strong></summary>

**Konfiguriertes Konto anzeigen:**

```bash
[RO] systemctl show "<DIENST>" --property=User,Group,DynamicUser
```

**Benutzerkonto prüfen:**

```bash
[RO] getent passwd "<DIENSTBENUTZER>"
```

**Gruppenmitgliedschaften anzeigen:**

```bash
[RO] id "<DIENSTBENUTZER>"
```

**Arbeitsverzeichnis prüfen:**

```bash
[RO] systemctl show "<DIENST>" --property=WorkingDirectory
```

**Referenzierte Umgebungsdateien anzeigen:**

```bash
[RO][SENS] systemctl show "<DIENST>" --property=EnvironmentFiles
```

Zu prüfen:

- Existiert der Dienstbenutzer?
- Existiert die konfigurierte Gruppe?
- Sind Dateirechte ausreichend?
- Ist ein dynamischer Benutzer vorgesehen?
- Existiert das Arbeitsverzeichnis?
- Kann das Konto Konfigurations- und Datendateien lesen?
- Kann es in erforderliche Verzeichnisse schreiben?
- Kann es privilegierte Ports oder Geräte verwenden?
- Blockieren SELinux, AppArmor oder systemd-Sandboxing den Zugriff?
- Sind Secrets für den Dienstkontext verfügbar?

> Das Starten des Programms als `root` ist kein gültiger Nachweis für die Funktion unter dem tatsächlichen Dienstkonto.

</details>

---

<details>
<summary><strong>16. systemd-Protokolle eines Startfehlers auswerten</strong></summary>

**Protokolle des aktuellen Systemstarts:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -b \
  -u "<DIENST>" \
  --no-pager
```

**Letzte 100 Einträge:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  -n 100 \
  --output=short-iso \
  --no-pager
```

**Fehler und schwerwiegendere Meldungen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  -p err \
  --since "1 hour ago" \
  --no-pager
```

**Dienst- und Systemmeldungen im selben Zeitfenster:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  --since "2026-07-31 09:10:00" \
  --until "2026-07-31 09:20:00" \
  --output=short-iso \
  --no-pager
```

**Kernelmeldungen berücksichtigen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -k \
  -b \
  -p warning \
  --no-pager
```

</details>

---

<details>
<summary><strong>17. systemd-Neustartschleife und Startbegrenzung erkennen</strong></summary>

**Neustartregeln anzeigen:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=Restart,RestartUSec,NRestarts
```

**Startbegrenzung anzeigen:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=StartLimitIntervalUSec,StartLimitBurst,Result
```

Anzeichen:

- `NRestarts` steigt,
- PID wechselt fortlaufend,
- Prozesslaufzeit bleibt sehr kurz,
- `Result=start-limit-hit`,
- Journal zeigt wiederholte identische Startfehler,
- Dienst ist zwischen den Versuchen kurz erreichbar,
- Healthcheck schlägt fortlaufend fehl.

**Fehlerstatus erst nach der Beweissicherung zurücksetzen:**

```bash
[CHANGE][PRIV] sudo systemctl reset-failed "<DIENST>"
```

`reset-failed`:

- startet den Dienst nicht,
- löscht aber den gespeicherten Fehlerzustand,
- setzt bestimmte Zähler für Startbegrenzungen zurück,
- verändert damit Diagnosezustand.

> Dieser Befehl darf deshalb erst nach Dokumentation von `Result`, `NRestarts`, Status und Journal verwendet werden.

</details>

---

<details>
<summary><strong>18. systemd-Diensttypen als mögliche Fehlerursache prüfen</strong></summary>

| `Type=` | Erwartetes Verhalten |
|---|---|
| `simple` | Gestarteter Prozess gilt unmittelbar als Hauptprozess |
| `exec` | Start gilt nach erfolgreichem Ausführen des Programms als erfolgt |
| `forking` | Programm erzeugt Hintergrundprozess; häufig mit PID-Datei |
| `oneshot` | Prozess führt Aufgabe aus und beendet sich wieder |
| `notify` | Dienst meldet systemd ausdrücklich Betriebsbereitschaft |
| `dbus` | Bereitschaft hängt von einem D-Bus-Namen ab |
| `idle` | Ausführung wird verzögert, bis andere Jobs abgearbeitet sind |

Mögliche Fehlkonfigurationen:

- `forking` verwendet falsche oder fehlende PID-Datei,
- `notify`-Dienst sendet keine Bereitschaftsmeldung,
- `oneshot` wird fälschlich als dauerhaft laufender Prozess erwartet,
- Programm forkt, obwohl `Type=simple` ungeeignet konfiguriert wurde,
- Wrapperprozess beendet sich und systemd überwacht nicht den erwarteten Prozess,
- Startbefehl blockiert und erreicht den vorgesehenen Zustand nicht.

> Der korrekte Diensttyp muss anhand der Programmdokumentation und des tatsächlichen Prozessverhaltens bestimmt werden.

</details>

---

<details>
<summary><strong>19. launchd-Status und letzten Exitstatus unter macOS prüfen</strong></summary>

**Systemweiten Dienst prüfen:**

```bash
[RO] launchctl print "system/<LABEL>"
```

**Benutzerbezogenen Dienst prüfen:**

```bash
[RO] launchctl print "gui/$(id -u)/<LABEL>"
```

Relevante Angaben können sein:

```text
state
pid
runs
last exit code
program
arguments
reason
path
```

**Deaktivierungsüberschreibungen prüfen:**

```bash
[RO] launchctl print-disabled system
```

**GUI-Domain des aktuellen Benutzers prüfen:**

```bash
[RO] launchctl print-disabled "gui/$(id -u)"
```

**Wichtig:**

- Fehlende PID kann bei einem bedarfsgesteuerten Job normal sein.
- Ein von null abweichender letzter Exitstatus ist ein Diagnosehinweis.
- Eine steigende Anzahl unter `runs` kann auf wiederholte Startversuche hinweisen.
- Ein Job mit `KeepAlive` kann nach einem Fehler automatisch erneut gestartet werden.
- Häufige schnelle Fehlstarts können von launchd gedrosselt werden.

</details>

---

<details>
<summary><strong>20. launchd-Konfiguration unter macOS prüfen</strong></summary>

**Bekannte systemweite plist anzeigen:**

```bash
[RO][FILE][SENS] plutil -p "/Library/LaunchDaemons/<LABEL>.plist"
```

**Formale plist-Prüfung durchführen:**

```bash
[RO][FILE] plutil -lint "/Library/LaunchDaemons/<LABEL>.plist"
```

**Benutzerbezogene plist prüfen:**

```bash
[RO][FILE][SENS] plutil -p "$HOME/Library/LaunchAgents/<LABEL>.plist"
```

Zu prüfen sind:

| Schlüssel | Prüffrage |
|---|---|
| `Label` | Stimmt das Label mit dem verwendeten Dienstziel überein? |
| `Program` | Existiert das Programm? |
| `ProgramArguments` | Sind Programm und Argumente korrekt angeordnet? |
| `WorkingDirectory` | Existiert das Arbeitsverzeichnis? |
| `UserName` | Existiert das Konto und besitzt es die nötigen Rechte? |
| `GroupName` | Existiert die Gruppe? |
| `KeepAlive` | Wird ein fehlerhafter Prozess wiederholt gestartet? |
| `RunAtLoad` | Soll der Job beim Laden gestartet werden? |
| `StandardOutPath` | Kann die Datei beziehungsweise das Verzeichnis verwendet werden? |
| `StandardErrorPath` | Kann die Fehlerausgabe geschrieben werden? |
| `EnvironmentVariables` | Sind erforderliche Variablen vorhanden? |

> `ProgramArguments` ist ein Array. Das erste Element bezeichnet üblicherweise das auszuführende Programm, wenn nicht zusätzlich `Program` angegeben wurde.

</details>

---

<details>
<summary><strong>21. macOS-Programmpfad und Berechtigungen prüfen</strong></summary>

**Programmdatei prüfen:**

```bash
[RO][FILE] stat "<AUSFÜHRBARE_DATEI>"
```

**Dateityp und Architektur anzeigen:**

```bash
[RO][FILE] file "<AUSFÜHRBARE_DATEI>"
```

**Berechtigungen und erweiterte Zugriffslisten anzeigen:**

```bash
[RO][FILE][SENS] ls -lde "<AUSFÜHRBARE_DATEI>"
```

**Code-Signatur anzeigen und prüfen:**

```bash
[RO][FILE][SENS] codesign \
  --verify \
  --deep \
  --strict \
  --verbose=2 \
  "<AUSFÜHRBARE_DATEI>"
```

**Gatekeeper-Bewertung für einen geeigneten Anwendungstyp prüfen:**

```bash
[RO][FILE][SENS] spctl \
  --assess \
  --type execute \
  --verbose=4 \
  "<AUSFÜHRBARE_DATEI>"
```

**Hinweise:**

- `codesign` prüft die Signatur, beweist aber nicht die vollständige Dienstfunktion.
- `spctl` ist nicht für jede Art von Binärdatei gleich aussagekräftig.
- Datenschutz- und Sicherheitsmechanismen können den Zugriff eines Daemons einschränken.
- Ein erfolgreicher Start im Terminal beweist nicht die Funktion innerhalb der launchd-Domain.

</details>

---

<details>
<summary><strong>22. macOS-Protokolle eines Startfehlers auswerten</strong></summary>

**Nach Prozess suchen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'process == "<PROZESS>"' \
  --style compact \
  --no-pager
```

**Nach launchd- und Prozessmeldungen suchen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'process == "launchd" OR process == "<PROZESS>"' \
  --style compact \
  --no-pager
```

**Fehler und Faults anzeigen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate '(process == "launchd" OR process == "<PROZESS>") AND (messageType == error OR messageType == fault)' \
  --style compact \
  --no-pager
```

**Live-Beobachtung während eines kontrollierten Startversuchs:**

```bash
[TEST][SENS][PRIV] sudo log stream \
  --timeout 5m \
  --predicate 'process == "launchd" OR process == "<PROZESS>"' \
  --style compact
```

</details>

---

<details>
<summary><strong>23. launchctl-Fehlercode unter macOS übersetzen</strong></summary>

Wenn ein `launchctl`-Befehl einen numerischen Fehlercode liefert, kann dieser mit `launchctl error` lesbarer dargestellt werden.

**Automatische Einordnung versuchen:**

```bash
[RO] launchctl error <FEHLERCODE>
```

**POSIX-Fehlerbereich angeben:**

```bash
[RO] launchctl error posix <FEHLERCODE>
```

**Mach-Fehlerbereich angeben:**

```bash
[RO] launchctl error mach <FEHLERCODE>
```

**Bootstrap-Fehlerbereich angeben:**

```bash
[RO] launchctl error bootstrap <FEHLERCODE>
```

> Die übersetzte Meldung beschreibt den technischen Fehlerbereich. Die konkrete Ursache muss weiterhin anhand von plist, Programmpfad, Berechtigungen und Protokollen bestimmt werden.

</details>

---

<details>
<summary><strong>24. Kontrollierten Startversuch durchführen</strong></summary>

Ein Startversuch verändert den Dienstzustand und kann Folgeprozesse, Netzwerkverbindungen oder automatische Wiederherstellungsaktionen auslösen.

| Betriebssystem | Startbefehl |
|---|---|
| Windows | `[CHANGE][PRIV] Start-Service -Name "<DIENSTNAME>"` |
| Linux | `[CHANGE][PRIV] sudo systemctl start "<DIENST>"` |
| macOS systemweit | `[CHANGE][PRIV] sudo launchctl kickstart "system/<LABEL>"` |
| macOS Benutzerkontext | `[CHANGE] launchctl kickstart "gui/$(id -u)/<LABEL>"` |

**macOS – PID bei erfolgreichem kickstart ausgeben:**

```bash
[CHANGE][PRIV] sudo launchctl kickstart \
  -p \
  "system/<LABEL>"
```

**Ablauf:**

```text
1. Aktuellen Status und Protokolle sichern
2. Live-Protokollansicht vorbereiten
3. Genaue Startzeit notieren
4. Genau einen Startversuch ausführen
5. Rückgabemeldung vollständig erfassen
6. Dienststatus sofort prüfen
7. Prozess-ID und Laufzeit prüfen
8. Listener prüfen
9. Neue Protokollmeldungen sichern
10. Anwendungstest durchführen
11. Keine weiteren Versuche ohne neue Erkenntnis starten
```

</details>

---

<details>
<summary><strong>25. Manuellen Programmstart nur kontrolliert verwenden</strong></summary>

Ein direkter Programmstart kann zusätzliche Fehlermeldungen auf der Konsole sichtbar machen. Er ist aber nicht automatisch sicher oder mit dem Dienststart gleichwertig.

Vorher prüfen:

- erlaubt der Hersteller einen Konsolen- oder Vordergrundmodus?
- ist der Dienstprozess wirklich beendet?
- würde eine zweite Instanz denselben Port oder dieselben Dateien verwenden?
- werden beim Start Datenbanken oder Dateien verändert?
- welches Benutzerkonto muss verwendet werden?
- welche Umgebungsvariablen setzt die Dienstverwaltung?
- welches Arbeitsverzeichnis wird erwartet?
- welche Limits und Sicherheitsrichtlinien gelten?
- existiert ein ausdrücklich dokumentierter Diagnoseparameter?

**Der manuelle Start kann sich unterscheiden durch:**

| Eigenschaft | Dienststart | Manueller Start |
|---|---|---|
| Benutzerkonto | Dienstkonto | Aktueller Terminalbenutzer |
| Arbeitsverzeichnis | Konfiguriert oder systemabhängig | Aktuelles Verzeichnis |
| Umgebungsvariablen | Dienstspezifisch | Shell- beziehungsweise Benutzervariablen |
| Berechtigungen | Dienstkontext | Benutzer- oder Administratorkontext |
| Netzwerkressourcen | Dienstabhängig | Benutzersitzung |
| Sicherheitsrichtlinien | Dienstmanager und Sandbox | Terminalkontext |
| Standardausgabe | Journal, Datei oder Ereignisprotokoll | Terminal |

> Deshalb wird kein generischer Direktstartbefehl verwendet. Der korrekte Diagnosemodus muss aus der offiziellen Dokumentation der jeweiligen Anwendung stammen.

</details>

---

<details>
<summary><strong>26. Häufige technische Ursachen eines sofortigen Abbruchs</strong></summary>

- Syntaxfehler in der Konfiguration,
- fehlende Konfigurationsdatei,
- falscher Programmpfad,
- fehlende Bibliothek oder Laufzeitumgebung,
- falsche Prozessorarchitektur,
- Port bereits belegt,
- ungültiges Zertifikat oder fehlender privater Schlüssel,
- Dienstkonto besitzt keine Leserechte,
- Datenverzeichnis ist nicht beschreibbar,
- Volume oder Netzfreigabe fehlt,
- Datenbank nicht erreichbar,
- DNS-Auflösung fehlerhaft,
- Umgebungsvariable fehlt,
- Secret oder Kennwort ungültig,
- Lizenz fehlt oder ist abgelaufen,
- Datenmigration ist fehlgeschlagen,
- PID-Datei kann nicht erstellt werden,
- Sperrdatei einer alten Instanz ist vorhanden,
- Sicherheitssoftware blockiert die Ausführung,
- Speicher oder Dateideskriptoren sind erschöpft.

</details>

---

<details>
<summary><strong>27. Zeitüberschreitung beim Dienststart analysieren</strong></summary>

Ein Timeout bedeutet zunächst, dass ein erwarteter Zustand nicht innerhalb der vorgesehenen Zeit erreicht wurde.

Mögliche Ursachen:

- DNS-Abfrage dauert zu lange,
- Datenbank ist nicht bereit,
- Netzwerkspeicher antwortet nicht,
- Anwendung führt eine lange Migration durch,
- Dienst wartet auf eine gesperrte Datei,
- Portbindung blockiert,
- Dienst meldet seine Bereitschaft nicht korrekt,
- Diensttyp passt nicht zum Programmverhalten,
- Hardware oder Datenträger ist langsam,
- Entschlüsselung oder Zertifikatsprüfung hängt,
- Dienst wartet auf interaktive Eingabe,
- Endlosschleife während der Initialisierung.

**Prüfung:**

```text
1. Startzeit genau feststellen
2. Letzte Meldung vor dem Timeout ermitteln
3. Prozesszustand während des Wartens prüfen
4. CPU- und I/O-Verhalten beobachten
5. Netzwerkverbindungen des Prozesses prüfen
6. Abhängigkeiten direkt testen
7. Herstellerdokumentation zur Initialisierung prüfen
8. Timeout nicht erhöhen, bevor die Warteursache bekannt ist
```

> Eine Vergrößerung des Timeouts kann einen langsamen, aber legitimen Start ermöglichen. Sie kann jedoch ebenso einen eigentlichen Fehler nur länger verbergen.

</details>

---

<details>
<summary><strong>28. Portkonflikt als Startursache prüfen</strong></summary>

**Windows:**

```powershell
[RO] Get-NetTCPConnection `
  -State Listen `
  -LocalPort <PORT> `
  -ErrorAction SilentlyContinue |
    Select-Object LocalAddress, LocalPort, OwningProcess
```

**Linux:**

```bash
[RO][PRIV] sudo ss -lntp "sport = :<PORT>"
```

**macOS:**

```bash
[RO][PRIV] sudo lsof \
  -nP \
  -iTCP:<PORT> \
  -sTCP:LISTEN
```

Wenn der Port belegt ist:

1. PID feststellen.
2. Prozessname bestimmen.
3. Dienstzuordnung prüfen.
4. Bindungsadresse kontrollieren.
5. Prüfen, ob eine alte Instanz läuft.
6. Container- oder Proxybelegung berücksichtigen.
7. Keinen Prozess ungeprüft beenden.
8. Sollkonfiguration und letzte Änderungen prüfen.

</details>

---

<details>
<summary><strong>29. Ressourcenmangel als Startursache prüfen</strong></summary>

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Freier Speicherplatz | `[RO] Get-Volume` | `[RO] df -hT` | `[RO] df -h` |
| Arbeitsspeicher | `[RO] Get-CimInstance Win32_OperatingSystem \| Select-Object TotalVisibleMemorySize,FreePhysicalMemory` | `[RO] free -h` | `[RO] vm_stat` |
| Prozessübersicht | `[RO] Get-Process \| Sort-Object WorkingSet64 -Descending` | `[RO] top` | `[RO] top -o mem` |
| Dateisystemzustand | `[RO] Get-Volume` | `[RO] findmnt` | `[RO] mount` |
| Offene Dateien des Prozesses | Betriebssystemspezifische Prozesswerkzeuge | `[RO][PRIV] sudo lsof -p <PID>` | `[RO][PRIV] sudo lsof -p <PID>` |

Mögliche Startfehler:

- Datenträger vollständig belegt,
- keine freien Inodes unter Linux,
- Arbeitsspeicher erschöpft,
- Auslagerung überlastet,
- Dateisystem schreibgeschützt,
- maximales Prozesslimit erreicht,
- Dateideskriptorlimit erreicht,
- temporäres Verzeichnis nicht verfügbar,
- Laufzeitverzeichnis kann nicht erstellt werden.

</details>

---

<details>
<summary><strong>30. Letzte Änderungen priorisiert untersuchen</strong></summary>

Besonders relevant sind Änderungen an:

- Programmversion,
- Dienstdatei oder plist,
- Windows-Dienstkonfiguration,
- systemd-Unit oder Drop-in,
- Dienstkonto oder Kennwort,
- Dateiberechtigungen,
- Zertifikaten,
- Port und Bindungsadresse,
- Firewall,
- Datenbankversion oder Schema,
- Bibliotheken und Laufzeitumgebung,
- Umgebungsvariablen,
- Secrets,
- Mounts und Volumes,
- Containern oder Images,
- Sicherheitssoftware,
- Betriebssystemupdates.

**Zeitlicher Vergleich:**

```text
Letzter erfolgreicher Start
  → Änderung
  → erster fehlgeschlagener Start
```

> Ein zeitlicher Zusammenhang ist ein starker Hinweis, aber noch kein Beweis. Die betroffene Konfiguration oder Komponente muss technisch geprüft werden.

</details>

---

<details>
<summary><strong>31. Typische Fehlinterpretationen</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „Der Startknopf zeigt einen Fehler, also ist Windows beziehungsweise systemd defekt.“ | Die Dienstverwaltung meldet häufig nur den Fehler des gestarteten Programms |
| „Exitcode 0 bedeutet, der Dienst funktioniert.“ | Nur die gemeldete Beendigung wurde als erfolgreich bewertet |
| „Der Prozess war kurz sichtbar, also startete der Dienst erfolgreich.“ | Er kann während der Initialisierung abgebrochen sein |
| „Manueller Start als Administrator funktioniert, also stimmen die Dienstrechte.“ | Der Dienst verwendet einen anderen Kontext |
| „Mehr Startversuche erhöhen die Chance auf Erfolg.“ | Sie können Protokolle überlagern und Startbegrenzungen auslösen |
| „Timeout erhöhen löst den Fehler.“ | Die eigentliche Warteursache bleibt möglicherweise bestehen |
| „Die Konfigurationsdatei ist syntaktisch gültig, also ist sie fachlich korrekt.“ | Pfade, Konten und Backends können weiterhin falsch sein |
| „Der Port ist frei, also muss der Dienst starten.“ | Viele weitere Startvoraussetzungen bleiben ungeprüft |
| „Ein Neustartzähler beweist einen Softwarefehler.“ | Auch fehlende Abhängigkeiten oder Rechte können Wiederholungen auslösen |
| „Fehlerstatus zurücksetzen repariert den Dienst.“ | Nur gespeicherter Zustand und Zähler werden zurückgesetzt |

</details>

---

<details>
<summary><strong>32. Checkliste zur Analyse eines Dienststartfehlers</strong></summary>

```text
[ ] Exakten Dienstnamen beziehungsweise Label bestätigt
[ ] Richtigen Server und richtige Umgebung bestätigt
[ ] Aktuellen Status gesichert
[ ] Exitcode und dienstspezifischen Exitcode erfasst
[ ] Relevante Protokolle vor neuem Startversuch gesichert
[ ] Startart und Deaktivierung geprüft
[ ] systemd-Maskierung beziehungsweise launchd-Override geprüft
[ ] Programmpfad und Startparameter geprüft
[ ] Programmdatei vorhanden
[ ] Dateityp und Architektur geprüft
[ ] Dienstkonto und Gruppe geprüft
[ ] Datei- und Verzeichnisrechte geprüft
[ ] Arbeitsverzeichnis geprüft
[ ] Umgebungs- und Konfigurationsdateien ermittelt
[ ] Formale Abhängigkeiten geprüft
[ ] Externe Backends geprüft
[ ] Portkonflikt ausgeschlossen
[ ] Speicherplatz und Arbeitsspeicher geprüft
[ ] Neustartregeln und Startbegrenzungen geprüft
[ ] Letzte Änderungen erfasst
[ ] Genau einen kontrollierten Startversuch durchgeführt
[ ] Prozess, PID und Laufzeit danach geprüft
[ ] Listener und Anwendungsfunktion geprüft
[ ] Ursache, Maßnahme und Ergebnis dokumentiert
```

</details>

---

**Bewertung des Ergebnisses**

| Ergebnis | Nächster Schritt |
|---|---|
| Dienst nicht vorhanden | Installation, Dienstname und Zielsystem prüfen |
| Dienst deaktiviert oder maskiert | Grund und Sollzustand vor Änderung klären |
| Programmdatei fehlt | Installation, Update und Dateisystem untersuchen |
| Zugriff verweigert | Dienstkonto, Rechte und Sicherheitsrichtlinien prüfen |
| Abhängigkeit schlägt fehl | Betroffene Abhängigkeit separat analysieren |
| Port ist belegt | Besitzenden Prozess und Konfiguration untersuchen |
| Konfiguration ist ungültig | Fehlerstelle mit Herstellerwerkzeug bestimmen |
| Prozess beendet sich mit Exitcode | Produktspezifische Bedeutung des Codes prüfen |
| Prozess wird durch Signal beendet | Signalursache, Ressourcen und Absturzdiagnose prüfen |
| Start läuft in Timeout | Letzte Initialisierungsphase und Abhängigkeiten untersuchen |
| Startgrenze wurde erreicht | Fehlerzustand sichern und Grund der Fehlstarts beheben |
| Dienst startet und bleibt aktiv | Listener und Anwendungstest durchführen |

---

**Merksatz**

> **Ein Dienststartfehler ist selten mit einem weiteren Startversuch erklärt. Entscheidend ist die erste Phase, in der Sollzustand und tatsächlicher Startablauf voneinander abweichen.**

---

**Weiterführende Quellen**

- [Microsoft Learn – Win32_Service](https://learn.microsoft.com/windows/win32/cimwin32prov/win32-service)
- [Microsoft Learn – sc.exe query](https://learn.microsoft.com/de-de/windows-server/administration/windows-commands/sc-query)
- [Microsoft Learn – sc.exe qc](https://learn.microsoft.com/windows-server/administration/windows-commands/sc-qc)
- [Microsoft Learn – sc.exe qfailure](https://learn.microsoft.com/windows-server/administration/windows-commands/sc-qfailure)
- [Microsoft Learn – Get-WinEvent](https://learn.microsoft.com/powershell/module/microsoft.powershell.diagnostics/get-winevent)
- [systemd – systemctl](https://www.freedesktop.org/software/systemd/man/latest/systemctl.html)
- [systemd – systemd.service](https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html)
- [systemd – systemd.exec](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html)
- [systemd – systemd-analyze](https://www.freedesktop.org/software/systemd/man/latest/systemd-analyze.html)
- [systemd – journalctl](https://www.freedesktop.org/software/systemd/man/latest/journalctl.html)
- [Apple – launchctl-Handbuchseite](https://keith.github.io/xcode-man-pages/launchctl.1.html)
- [Apple – launchd.plist-Handbuchseite](https://keith.github.io/xcode-man-pages/launchd.plist.5.html)
- [Apple – plutil-Handbuchseite](https://keith.github.io/xcode-man-pages/plutil.1.html)
- [Apple – log-Handbuchseite](https://keith.github.io/xcode-man-pages/log.1.html)

# 4.8 Konfigurationsfehler untersuchen

Ein Dienst kann installiert, gestartet und über den vorgesehenen Port erreichbar sein, aber aufgrund einer fehlerhaften oder veralteten Konfiguration trotzdem nicht richtig funktionieren.

> **Grundsatz:**  
> Nicht irgendeine Konfigurationsdatei prüfen, sondern zuerst feststellen, welche Konfiguration der laufende Dienst tatsächlich verwendet.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- Konfigurationsquelle und wirksame Konfiguration unterscheiden können,
- Syntax- und Inhaltsfehler getrennt untersuchen können,
- Konfigurationshierarchien und Überschreibungen erkennen können,
- Dateipfade, Eigentümer und Berechtigungen prüfen können,
- Umgebungsvariablen und Startparameter berücksichtigen können,
- Konfigurationsstände sicher vergleichen können,
- Hashwerte und Änderungszeitpunkte erfassen können,
- versionsabhängige Konfigurationsfehler erkennen können,
- Änderungen kontrolliert vorbereiten und rückgängig machen können,
- Geheimnisse in Konfigurationsdateien schützen können.

---

<details>
<summary><strong>1. Arten von Konfigurationsfehlern unterscheiden</strong></summary>

| Fehlerart | Beispiel |
|---|---|
| Syntaxfehler | Fehlende Klammer oder ungültiges Trennzeichen |
| Tippfehler | Falscher Schlüsselname oder Hostname |
| Datentypfehler | Text statt Zahl oder `true` statt erwarteter Zeichenfolge |
| Wertebereichsfehler | Port außerhalb des gültigen Bereichs |
| Fehlender Pflichtwert | Datenbankadresse nicht angegeben |
| Falscher Dateipfad | Zertifikat oder Datenverzeichnis nicht gefunden |
| Falsche Berechtigung | Dienstkonto kann Datei nicht lesen |
| Falsche Eigentümerschaft | Datei gehört nicht dem vorgesehenen Konto |
| Überschreibung | Lokales Drop-in ersetzt den erwarteten Wert |
| Versionskonflikt | Option wird von neuer Version nicht mehr unterstützt |
| Formatfehler | JSON, XML, YAML oder plist ist formal ungültig |
| Kodierungsfehler | Falsche Zeichenkodierung oder Byte Order Mark |
| Zeilenendefehler | Windows-Zeilenenden stören ein Unix-Werkzeug |
| Umgebungsfehler | Variable ist im Terminal, aber nicht im Dienstkontext vorhanden |
| Geheimnisfehler | Kennwort, Token oder Schlüssel fehlt beziehungsweise ist abgelaufen |
| Zielsystemfehler | Konfiguration zeigt auf Test- statt Produktivsystem |
| Reihenfolgefehler | Spätere Datei überschreibt eine frühere Einstellung |
| Neustart fehlt | Datei wurde geändert, Dienst verwendet aber noch alten Zustand |
| Reload ungeeignet | Dienst unterstützt kein dynamisches Neuladen |
| Konfiguration nicht eingebunden | Bearbeitete Datei wird vom Dienst gar nicht geladen |

</details>

---

<details>
<summary><strong>2. Konfigurationsquelle und wirksame Konfiguration unterscheiden</strong></summary>

Eine Anwendung kann Einstellungen aus mehreren Quellen beziehen:

```text
Programmstandardwerte
  → Hauptkonfigurationsdatei
  → eingebundene Zusatzdateien
  → lokale Überschreibungen
  → Umgebungsvariablen
  → Startparameter
  → zentrale Konfigurationsverwaltung
  → zur Laufzeit gespeicherte Einstellungen
```

Später ausgewertete Quellen können frühere Werte überschreiben. Die genaue Priorität ist produktspezifisch.

| Begriff | Bedeutung |
|---|---|
| Standardwert | Vom Programm verwendeter Wert ohne eigene Konfiguration |
| Quelldatei | Datei, in der eine Einstellung gespeichert ist |
| Include | Zusätzlich geladene Konfigurationsdatei |
| Drop-in | Ergänzende oder überschreibende Konfiguration |
| Startparameter | Beim Programmstart übergebener Wert |
| Umgebungsvariable | Einstellung aus dem Prozesskontext |
| Wirksame Konfiguration | Tatsächlich vom Dienst verwendeter Gesamtzustand |
| Laufzeitkonfiguration | Nach dem Start möglicherweise intern veränderter Zustand |

> Eine korrekt aussehende Hauptdatei beweist nicht, dass ihr Wert tatsächlich wirksam ist.

</details>

---

<details>
<summary><strong>3. Vor jeder Prüfung den Konfigurationspfad belegen</strong></summary>

Der Konfigurationspfad sollte aus mindestens einer belastbaren Quelle stammen:

1. offizielle Herstellerdokumentation,
2. Dienststartparameter,
3. systemd-Unit beziehungsweise launchd-plist,
4. Windows-Dienstkonfiguration,
5. Anwendungsausgabe zur wirksamen Konfiguration,
6. Installations- oder Deploymentdokumentation,
7. Containerdefinition,
8. Protokollmeldung beim Dienststart.

**Nicht ausreichend:**

- vermuteter Standardpfad,
- Dateiname einer anderen Installation,
- alte Internetanleitung,
- Konfiguration aus einer anderen Produktversion,
- gleichnamige Datei im Benutzerverzeichnis.

**Zu dokumentieren:**

```text
Dienst:
Produkt und Version:
Konfigurationsquelle:
Tatsächlicher Pfad:
Weitere Includes:
Umgebungsdateien:
Startparameter:
Konfigurationspriorität:
Zeitpunkt der Prüfung:
```

</details>

---

<details>
<summary><strong>4. Konfigurationsquelle unter Windows ermitteln</strong></summary>

**Dienstpfad und Startparameter anzeigen:**

```powershell
[RO][SENS] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name, StartName, PathName
```

**Alternative mit sc.exe:**

```powershell
[RO][SENS] sc.exe qc "<DIENSTNAME>"
```

Anschließend sind zu prüfen:

- enthält `PathName` einen Konfigurationsparameter?
- wird ein Arbeitsverzeichnis vorausgesetzt?
- verweist der Dienst auf einen Wrapper oder Launcher?
- liest der Wrapper eine weitere Konfiguration?
- wird eine Java-, .NET- oder Skript-Laufzeit aufgerufen?
- stammen Einstellungen aus der Registrierung?
- verwendet die Anwendung ein eigenes Windows-Ereignisprotokoll?
- existieren lokale und globale Konfigurationsdateien?

> Programmpfad und Argumente werden in `PathName` gemeinsam dargestellt. Sie müssen bei der Auswertung sorgfältig getrennt werden.

</details>

---

<details>
<summary><strong>5. Konfigurationsquelle unter Linux mit systemd ermitteln</strong></summary>

**Wirksame Unit und Drop-ins anzeigen:**

```bash
[RO][FILE][SENS] systemctl cat "<DIENST>"
```

**Wichtige Pfade und Startparameter anzeigen:**

```bash
[RO][SENS] systemctl show "<DIENST>" \
  --property=FragmentPath,DropInPaths,ExecStart,WorkingDirectory,EnvironmentFiles
```

**Umgebungswerte anzeigen:**

```bash
[RO][SENS] systemctl show "<DIENST>" --property=Environment
```

**Systemweite Konfigurationsdateien eines systemd-Bestandteils zusammenführen:**

```bash
[RO][FILE] systemd-analyze cat-config "<KONFIGURATIONSNAME>"
```

`systemd-analyze cat-config` ist für unterstützte Konfigurationshierarchien von systemd-Komponenten gedacht. Es ist kein universeller Parser für beliebige Anwendungen.

**Zu prüfen:**

- welche Unit-Datei wurde geladen?
- existieren lokale Drop-ins?
- wird eine Umgebungsdatei verwendet?
- überschreibt `ExecStart` einen Paketstandard?
- wird ein Wrapper oder Startskript verwendet?
- enthält der Dienst einen Konfigurationsparameter?
- wird die Konfiguration über mehrere Dateien zusammengesetzt?

</details>

---

<details>
<summary><strong>6. Konfigurationsquelle unter macOS ermitteln</strong></summary>

**Systemweiten launchd-Job anzeigen:**

```bash
[RO] launchctl print "system/<LABEL>"
```

**Benutzerbezogenen Job anzeigen:**

```bash
[RO] launchctl print "gui/$(id -u)/<LABEL>"
```

**Bekannte plist lesbar anzeigen:**

```bash
[RO][FILE][SENS] plutil -p "/Library/LaunchDaemons/<LABEL>.plist"
```

**Benutzerbezogene plist anzeigen:**

```bash
[RO][FILE][SENS] plutil -p "$HOME/Library/LaunchAgents/<LABEL>.plist"
```

Relevante plist-Schlüssel:

```text
Program
ProgramArguments
WorkingDirectory
EnvironmentVariables
UserName
GroupName
StandardOutPath
StandardErrorPath
```

Zusätzlich kann eine Anwendung Einstellungen aus dem macOS-Preferences-System verwenden.

**Bekannte Preferences-Domain lesend anzeigen:**

```bash
[RO][SENS] defaults read "<DOMAIN>"
```

**Einzelnen bekannten Schlüssel lesen:**

```bash
[RO][SENS] defaults read "<DOMAIN>" "<SCHLÜSSEL>"
```

> `defaults read` liest Preferences-Domains. Es ist kein allgemeines Werkzeug für die zuverlässige Bearbeitung beliebiger plist-Dateien.

</details>

---

<details>
<summary><strong>7. Dateiexistenz und Metadaten vergleichen</strong></summary>

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Existenz prüfen | `[RO][FILE] Test-Path -LiteralPath "<DATEI>"` | `[RO][FILE] test -f "<DATEI>"` | `[RO][FILE] test -f "<DATEI>"` |
| Metadaten anzeigen | `[RO][FILE] Get-Item -LiteralPath "<DATEI>"` | `[RO][FILE] stat "<DATEI>"` | `[RO][FILE] stat "<DATEI>"` |
| Dateityp prüfen | `[RO][FILE] Get-Item -LiteralPath "<DATEI>" \| Select-Object FullName,Length,Extension` | `[RO][FILE] file "<DATEI>"` | `[RO][FILE] file "<DATEI>"` |
| Eigentümer und Rechte | `[RO][FILE][SENS] Get-Acl -LiteralPath "<DATEI>"` | `[RO][FILE] stat -c '%U %G %A %a %n' "<DATEI>"` | `[RO][FILE] stat -f '%Su %Sg %Sp %N' "<DATEI>"` |
| Symbolischen Link anzeigen | `[RO][FILE] Get-Item -LiteralPath "<DATEI>" \| Select-Object FullName,LinkType,Target` | `[RO][FILE] readlink "<DATEI>"` | `[RO][FILE] readlink "<DATEI>"` |

**Zu prüfen:**

- existiert die Datei?
- ist es wirklich eine reguläre Datei?
- handelt es sich um einen symbolischen Link?
- zeigt der Link auf das erwartete Ziel?
- stimmen Eigentümer und Gruppe?
- ist die Datei leer oder ungewöhnlich klein?
- wurde sie zum Störungszeitpunkt verändert?
- liegt sie auf dem erwarteten Dateisystem?
- kann das Dienstkonto alle übergeordneten Verzeichnisse durchlaufen?

> Ein Änderungszeitpunkt beweist nur, dass sich Dateimetadaten oder Dateiinhalt geändert haben. Er beweist nicht, wer die fachliche Änderung vorgenommen hat.

</details>

---

<details>
<summary><strong>8. Berechtigungen aller Pfadbestandteile prüfen</strong></summary>

Ein Dienst benötigt nicht nur Rechte auf die Datei selbst. Er muss auch die übergeordneten Verzeichnisse erreichen können.

**Windows – Datei und übergeordnetes Verzeichnis:**

```powershell
[RO][FILE][SENS] Get-Acl -LiteralPath "<DATEI>" |
    Format-List
```

```powershell
[RO][FILE][SENS] Get-Acl -LiteralPath "<VERZEICHNIS>" |
    Format-List
```

**Linux – vollständigen Pfad zerlegen:**

```bash
[RO][FILE] namei -l "<DATEI>"
```

**Linux – ACL anzeigen:**

```bash
[RO][FILE][SENS] getfacl "<DATEI>"
```

`getfacl` ist nicht auf jeder Minimalinstallation vorhanden.

**macOS – Datei und erweiterte ACL anzeigen:**

```bash
[RO][FILE][SENS] ls -lde "<DATEI>"
```

**macOS – alle Pfadbestandteile prüfen:**

```bash
[RO][FILE] ls -lde "<VERZEICHNIS>" "<DATEI>"
```

Mögliche Fehler:

- Datei ist lesbar, aber Verzeichnis nicht durchsuchbar,
- Dienstkonto darf Konfiguration lesen, aber keine temporäre Datei erzeugen,
- Konfiguration verweist auf ein nicht zugängliches Zertifikat,
- ACL widerspricht den einfachen Dateirechten,
- Eigentümer wurde bei einer Wiederherstellung verändert,
- Datei liegt auf einem schreibgeschützten Volume.

</details>

---

<details>
<summary><strong>9. Hashwert einer Konfiguration erfassen</strong></summary>

Ein kryptografischer Hashwert hilft festzustellen, ob zwei Dateien denselben Inhalt besitzen. Er zeigt nicht, welcher Inhalt fachlich richtig ist.

| Betriebssystem | SHA-256-Befehl |
|---|---|
| Windows | `[RO][FILE] Get-FileHash -Algorithm SHA256 -LiteralPath "<DATEI>"` |
| Linux | `[RO][FILE] sha256sum "<DATEI>"` |
| macOS | `[RO][FILE] shasum -a 256 "<DATEI>"` |

**Mögliche Verwendung:**

- Produktiv- und Referenzdatei vergleichen,
- Zustand vor einer Änderung dokumentieren,
- prüfen, ob Deployment wirklich neue Datei ausgeliefert hat,
- Konfigurationsdrift erkennen,
- gesicherte Kopie eindeutig zuordnen.

**Wichtig:**

- unterschiedliche Hashwerte beweisen einen Inhaltsunterschied,
- gleiche Hashwerte beweisen mit sehr hoher Sicherheit gleichen Dateiinhalt,
- Dateiname, Eigentümer und Berechtigungen werden nicht inhaltlich verglichen,
- Hashwerte geheimer Dateien dürfen je nach Sicherheitsvorgabe ebenfalls geschützt werden.

</details>

---

<details>
<summary><strong>10. Zwei Konfigurationsstände vergleichen</strong></summary>

**Windows – zeilenweiser Vergleich:**

```powershell
[RO][FILE][SENS] Compare-Object `
    (Get-Content -LiteralPath "<REFERENZDATEI>") `
    (Get-Content -LiteralPath "<AKTUELLE_DATEI>")
```

Bedeutung der Seitenindikatoren:

| Indikator | Bedeutung |
|---|---|
| `<=` | Zeile befindet sich nur in der Referenz |
| `=>` | Zeile befindet sich nur in der aktuellen Datei |

**Linux:**

```bash
[RO][FILE][SENS] diff -u "<REFERENZDATEI>" "<AKTUELLE_DATEI>"
```

**macOS:**

```bash
[RO][FILE][SENS] diff -u "<REFERENZDATEI>" "<AKTUELLE_DATEI>"
```

**Hinweise:**

- `diff` liefert bei Unterschieden üblicherweise einen Rückgabecode ungleich null, obwohl das Werkzeug technisch korrekt gearbeitet hat.
- Unterschiedliche Reihenfolge kann als Änderung erscheinen.
- Kommentare und Leerzeichen können Unterschiede erzeugen, ohne die Funktion zu verändern.
- Bei strukturierten Formaten sollte zusätzlich die semantische Wirkung geprüft werden.
- Referenzdatei und aktuelle Datei müssen zur gleichen Produktversion passen.
- Secrets dürfen nicht ungefiltert in die Vergleichsausgabe gelangen.

</details>

---

<details>
<summary><strong>11. JSON-Konfiguration prüfen</strong></summary>

**Windows PowerShell:**

```powershell
[RO][FILE][SENS] Test-Json `
    -Json (Get-Content -LiteralPath "<DATEI>.json" -Raw)
```

**JSON einlesen und strukturiert anzeigen:**

```powershell
[RO][FILE][SENS] Get-Content -LiteralPath "<DATEI>.json" -Raw |
    ConvertFrom-Json
```

**Linux mit installiertem jq:**

```bash
[RO][FILE][SENS] jq empty "<DATEI>.json"
```

**macOS mit plutil:**

```bash
[RO][FILE] plutil -lint "<DATEI>.json"
```

**JSON lesbar ausgeben, ohne Quelldatei zu verändern:**

```bash
[RO][FILE][SENS] plutil \
  -convert json \
  -o - \
  -- "<DATEI>.json"
```

**Zu beachten:**

- syntaktisch gültiges JSON kann fachlich falsche Werte enthalten,
- doppelte Schlüssel können von Parsern unterschiedlich behandelt werden,
- Kommentare sind im eigentlichen JSON-Standard nicht vorgesehen,
- Datentypen wie Zahl, Zeichenfolge und Boolean müssen stimmen,
- Produktschema und Pflichtfelder müssen zusätzlich geprüft werden.

</details>

---

<details>
<summary><strong>12. XML- und plist-Konfiguration prüfen</strong></summary>

**Beliebiges XML unter Windows PowerShell einlesen:**

```powershell
[RO][FILE][SENS] [xml](
    Get-Content -LiteralPath "<DATEI>.xml" -Raw
)
```

Ein Parserfehler weist auf ungültiges XML hin. Ein erfolgreiches Einlesen beweist noch keine Gültigkeit gegenüber einem Produktschema.

**Linux mit installiertem xmllint:**

```bash
[RO][FILE] xmllint --noout "<DATEI>.xml"
```

**macOS – plist-Syntax prüfen:**

```bash
[RO][FILE] plutil -lint "<DATEI>.plist"
```

**macOS – plist lesbar anzeigen:**

```bash
[RO][FILE][SENS] plutil -p "<DATEI>.plist"
```

**macOS – Typ eines bekannten plist-Schlüssels prüfen:**

```bash
[RO][FILE] plutil \
  -type "<SCHLÜSSELPFAD>" \
  "<DATEI>.plist"
```

**Zu unterscheiden:**

| Prüfung | Aussage |
|---|---|
| XML syntaktisch lesbar | Grundlegende XML-Struktur ist gültig |
| plist mit `plutil -lint` gültig | Property-List-Format ist syntaktisch gültig |
| Schema gültig | Felder und Struktur entsprechen einem definierten Schema |
| Fachlich gültig | Werte funktionieren für das konkrete Produkt |
| Wirksam | Anwendung verwendet diese Werte tatsächlich |

</details>

---

<details>
<summary><strong>13. YAML-, INI- und proprietäre Formate prüfen</strong></summary>

Für YAML, INI und herstellerspezifische Formate gibt es kein einzelnes betriebssystemübergreifendes Standardwerkzeug, das gleichzeitig Syntax und fachliche Gültigkeit zuverlässig prüft.

**Geeignete Reihenfolge:**

1. offizielles Validierungswerkzeug des Produkts verwenden,
2. produktspezifischen Testmodus verwenden,
3. unterstütztes Schema verwenden,
4. Parser nur aus einer vertrauenswürdigen Quelle verwenden,
5. Ausgabe mit der verwendeten Produktversion dokumentieren.

**Typische YAML-Fehler:**

- falsche Einrückung,
- Tabulator statt Leerzeichen,
- unbeabsichtigte Typumwandlung,
- falsch gesetzte Anführungszeichen,
- ungültige Liste oder Zuordnung,
- doppelte Schlüssel,
- nicht aufgelöste Referenz,
- mehrere Dokumente in einer Datei.

**Typische INI-Fehler:**

- falscher Abschnitt,
- doppelter Schlüssel,
- unerwartete Groß- und Kleinschreibung,
- falsches Trennzeichen,
- ungültige Escape-Sequenz,
- Wert im falschen Abschnitt,
- Kommentarzeichen wird als Wert interpretiert.

> Keine beliebigen Online-Validatoren für produktive Konfigurationen verwenden. Dateien können interne Adressen, Konten, Tokens oder andere Geheimnisse enthalten.

</details>

---

<details>
<summary><strong>14. systemd-Unit-Dateien und Überschreibungen prüfen</strong></summary>

**Wirksame Unit anzeigen:**

```bash
[RO][FILE][SENS] systemctl cat "<DIENST>"
```

**Unit formal prüfen:**

```bash
[RO][FILE] systemd-analyze verify "<UNIT-DATEI>"
```

**Lokale Abweichungen von ausgelieferten Unit-Dateien anzeigen:**

```bash
[RO][FILE][SENS] systemd-delta
```

**Nur Abweichungen für systemd-Systemkonfigurationen anzeigen:**

```bash
[RO][FILE][SENS] systemd-delta --type=overridden,extended
```

Mögliche Kategorien von `systemd-delta`:

| Kategorie | Bedeutung |
|---|---|
| `overridden` | Ursprüngliche Datei wurde vollständig überschrieben |
| `extended` | Drop-in ergänzt oder verändert Einstellungen |
| `masked` | Unit ist maskiert |
| `equivalent` | Dateien sind inhaltlich gleichwertig |
| `redirected` | Datei verweist auf ein anderes Ziel |

**Besonders prüfen:**

- wurde `ExecStart` in einem Drop-in ersetzt?
- blieb eine alte Überschreibung nach einem Update bestehen?
- verweist `EnvironmentFile` auf eine alte Datei?
- wurde eine Hersteller-Unit unter `/usr` direkt verändert?
- enthält ein Drop-in eine leere Zuweisung, die einen früheren Wert zurücksetzt?
- wurde eine Unit versehentlich maskiert?

</details>

---

<details>
<summary><strong>15. launchd-plist unter macOS prüfen</strong></summary>

**Syntax prüfen:**

```bash
[RO][FILE] plutil -lint "/Library/LaunchDaemons/<LABEL>.plist"
```

**Struktur lesbar anzeigen:**

```bash
[RO][FILE][SENS] plutil -p "/Library/LaunchDaemons/<LABEL>.plist"
```

**Label gezielt auslesen:**

```bash
[RO][FILE] plutil \
  -extract Label raw \
  "/Library/LaunchDaemons/<LABEL>.plist"
```

**Programmpfad gezielt auslesen:**

```bash
[RO][FILE][SENS] plutil \
  -extract Program raw \
  "/Library/LaunchDaemons/<LABEL>.plist"
```

Falls kein `Program`-Schlüssel vorhanden ist, kann der Programmpfad im ersten Element von `ProgramArguments` stehen.

**Erstes Argument auslesen:**

```bash
[RO][FILE][SENS] plutil \
  -extract ProgramArguments.0 raw \
  "/Library/LaunchDaemons/<LABEL>.plist"
```

**Zu prüfen:**

- Dateiname und `Label` stimmen sinnvoll überein,
- `Program` oder erstes `ProgramArguments`-Element ist korrekt,
- Programmpfad ist absolut,
- Arbeitsverzeichnis existiert,
- Dienstkonto und Gruppe existieren,
- Ausgabe- und Fehlerpfade sind beschreibbar,
- Datentypen der Schlüssel stimmen,
- Startbedingungen widersprechen sich nicht,
- Datei liegt in der richtigen launchd-Domain.

</details>

---

<details>
<summary><strong>16. Umgebungsvariablen als Fehlerquelle untersuchen</strong></summary>

Eine Variable kann in der interaktiven Shell vorhanden sein, aber im Dienstkontext fehlen.

Typische verwendete Variablen:

```text
PATH
HOME
TEMP
TMP
LANG
LC_ALL
HTTP_PROXY
HTTPS_PROXY
NO_PROXY
DATABASE_URL
CONFIG_PATH
CERT_PATH
```

**Windows – Umgebungsvariablen der aktuellen Sitzung:**

```powershell
[RO][SENS] Get-ChildItem Env:
```

**Windows – maschinenweite Variable lesen:**

```powershell
[RO][SENS] [Environment]::GetEnvironmentVariable(
    "<VARIABLE>",
    "Machine"
)
```

**Linux – für systemd konfigurierte Dienstvariablen anzeigen:**

```bash
[RO][SENS] systemctl show "<DIENST>" \
  --property=Environment,EnvironmentFiles
```

**macOS – launchd-Job und plist prüfen:**

```bash
[RO][SENS] launchctl print "system/<LABEL>"
```

```bash
[RO][FILE][SENS] plutil -p "/Library/LaunchDaemons/<LABEL>.plist"
```

**Wichtig:**

- `sudo` kann Umgebungsvariablen verändern oder entfernen,
- Systemdienste besitzen häufig ein reduziertes `PATH`,
- `$HOME` kann fehlen oder auf ein anderes Verzeichnis zeigen,
- Proxyvariablen können nur in einer Benutzersitzung gesetzt sein,
- Variablennamen können unter Unix-Systemen Groß- und Kleinschreibung unterscheiden,
- Variablen können Secrets enthalten.

> Die vollständige Umgebung eines produktiven Prozesses darf nicht ungeprüft ausgegeben oder weitergegeben werden.

</details>

---

<details>
<summary><strong>17. Relative Pfade und Arbeitsverzeichnis prüfen</strong></summary>

Folgende Konfiguration kann problematisch sein:

```text
config/application.conf
certificates/server.crt
logs/application.log
./data
```

Relative Pfade werden vom Arbeitsverzeichnis des Prozesses aus aufgelöst. Dieses kann beim Dienststart anders sein als beim manuellen Start.

**Windows – Dienstpfad anzeigen:**

```powershell
[RO][SENS] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name, PathName
```

**Linux – Arbeitsverzeichnis anzeigen:**

```bash
[RO] systemctl show "<DIENST>" --property=WorkingDirectory
```

**macOS – plist prüfen:**

```bash
[RO][FILE][SENS] plutil -p "/Library/LaunchDaemons/<LABEL>.plist"
```

**Prüffragen:**

- enthält die Konfiguration relative Pfade?
- welches Arbeitsverzeichnis verwendet der Dienst?
- existiert der Pfad in diesem Kontext?
- besitzt das Dienstkonto Zugriff?
- zeigt ein symbolischer Link auf das erwartete Ziel?
- verhält sich der manuelle Start nur deshalb anders?

> Für Serverdienste sind eindeutig dokumentierte absolute Pfade meist leichter nachvollziehbar. Ob sie unterstützt werden, entscheidet jedoch die Produktkonfiguration.

</details>

---

<details>
<summary><strong>18. Zeichenkodierung und Zeilenenden prüfen</strong></summary>

**Windows – Anfangsbytes einer Datei anzeigen:**

```powershell
[RO][FILE] Format-Hex -LiteralPath "<DATEI>" |
    Select-Object -First 5
```

**Linux – Dateityp und mögliche Kodierungshinweise:**

```bash
[RO][FILE] file "<DATEI>"
```

**macOS:**

```bash
[RO][FILE] file "<DATEI>"
```

Typische Probleme:

- UTF-8 mit oder ohne Byte Order Mark,
- UTF-16 statt UTF-8,
- ungültige Bytefolge,
- Windows-Zeilenende `CRLF`,
- Unix-Zeilenende `LF`,
- unsichtbares Steuerzeichen,
- nicht brechendes Leerzeichen,
- Tabulator in YAML,
- typografische statt gerader Anführungszeichen,
- falsche Normalisierung von Unicode-Zeichen.

**Unsichtbare Zeichen unter Linux oder macOS darstellen:**

```bash
[RO][FILE][SENS] sed -n 'l' "<DATEI>"
```

> Eine Konvertierung verändert die Datei und darf erst nach Sicherung, Freigabe und Kenntnis des erwarteten Formats durchgeführt werden.

</details>

---

<details>
<summary><strong>19. Include-Dateien und Konfigurationshierarchie prüfen</strong></summary>

Eine Hauptdatei kann weitere Dateien laden:

```text
Hauptdatei
  → conf.d/*.conf
  → lokale Überschreibung
  → geheime Umgebungsdatei
  → automatisch generierte Datei
```

**Zu prüfen:**

- welche Include-Anweisungen existieren?
- in welcher Reihenfolge werden Dateien geladen?
- werden Platzhalter oder Wildcards verwendet?
- existiert eine alte Sicherungsdatei mit passender Endung im Include-Verzeichnis?
- wird eine automatisch generierte Datei manuell überschrieben?
- gibt es environment-, mandanten- oder hostabhängige Dateien?
- wird eine Datei aufgrund falscher Endung ignoriert?
- verweist ein Include auf einen nicht vorhandenen Pfad?
- wird dieselbe Einstellung mehrfach definiert?
- gewinnt der erste oder der letzte Wert?

> Die Lade- und Überschreibungsreihenfolge muss aus der Dokumentation des konkreten Produkts entnommen werden.

</details>

---

<details>
<summary><strong>20. Versionskompatibilität der Konfiguration prüfen</strong></summary>

Nach einem Update können Einstellungen:

- umbenannt,
- entfernt,
- als veraltet markiert,
- in einen anderen Abschnitt verschoben,
- mit verändertem Datentyp erwartet,
- mit neuem Standardwert versehen,
- sicherheitsbedingt deaktiviert,
- durch ein neues Format ersetzt worden sein.

**Zu dokumentieren:**

```text
Vorherige Produktversion:
Aktuelle Produktversion:
Version der Konfigurationsvorlage:
Datum der letzten Konfigurationsänderung:
Migrationshinweise gelesen:
Veraltete Optionen:
Neue Pflichtwerte:
Geänderte Standardwerte:
```

**Prüfquellen:**

1. offizielle Versionshinweise,
2. Upgrade- oder Migrationsanleitung,
3. Beispielkonfiguration derselben Version,
4. produktspezifischer Konfigurationstest,
5. Startprotokoll mit Warnungen zu veralteten Optionen.

> Eine Beispieldatei aus einer neueren oder älteren Version darf nicht ungeprüft als Referenz verwendet werden.

</details>

---

<details>
<summary><strong>21. Secrets und Zugangsdaten sicher behandeln</strong></summary>

Konfigurationsdateien können enthalten:

- Kennwörter,
- API-Schlüssel,
- Datenbank-Verbindungszeichenfolgen,
- private Schlüssel,
- Zugriffstoken,
- Sitzungsschlüssel,
- LDAP-Bindekennwörter,
- Cloud-Zugangsdaten,
- interne URLs mit eingebetteten Zugangsdaten.

**Regeln:**

```text
[ ] Keine vollständige Geheimdatei in ein Ticket kopieren
[ ] Keine Secrets in Terminalbefehle mit Protokollierung einsetzen
[ ] Keine produktive Konfiguration in Online-Validatoren hochladen
[ ] Keine privaten Schlüssel mit Vergleichsausgaben veröffentlichen
[ ] Nur bereinigte Kopien weitergeben
[ ] Originaldatei geschützt aufbewahren
[ ] Dateirechte vor und nach einer Maßnahme prüfen
[ ] Kompromittierte Geheimnisse nicht nur zurückändern, sondern rotieren
```

**Unsichere Darstellung:**

```text
DATABASE_URL=postgres://admin:Kennwort@db-server/database
```

**Bereinigte Darstellung:**

```text
DATABASE_URL=postgres://<BENUTZER>:<ENTFERNT>@<DB-SERVER>/<DATENBANK>
```

</details>

---

<details>
<summary><strong>22. Containerkonfiguration berücksichtigen</strong></summary>

Bei Containern können Einstellungen stammen aus:

- Image-Standardwerten,
- Umgebungsvariablen,
- Compose- oder Orchestrator-Definition,
- Secrets,
- Config-Objekten,
- eingebundenen Dateien,
- persistenten Volumes,
- Startbefehl oder Entrypoint,
- Reverse-Proxy-Konfiguration.

**Prüffragen:**

- welche Image-Version wird tatsächlich ausgeführt?
- wurde der Container nach einer Änderung neu erstellt?
- ist die richtige Datei in den Container eingebunden?
- wurde eine Datei oder ein ganzes Verzeichnis gemountet?
- verdeckt ein Mount eine im Image vorhandene Datei?
- verwendet der Container die erwarteten Umgebungsvariablen?
- enthält der Startbefehl eine Überschreibung?
- wurde ein Secret aktualisiert?
- ist die Konfiguration persistent?
- unterscheidet sich die Hostdatei von der Datei im Container?
- verwendet die Anwendung intern einen anderen Pfad?

> Eine Änderung an einer Hostdatei ist nur wirksam, wenn genau diese Datei in den Container eingebunden und von der Anwendung verwendet wird.

</details>

---

<details>
<summary><strong>23. Konfiguration vor einer Änderung beweissicher erfassen</strong></summary>

Mindestens erfassen:

| Information | Zweck |
|---|---|
| Vollständiger Pfad | Eindeutige Dateiidentifikation |
| Dateigröße | Plausibilitätsprüfung |
| Änderungszeit | Zeitlicher Zusammenhang |
| Eigentümer und Rechte | Zugriffskontrolle |
| SHA-256-Hash | Inhaltsidentifikation |
| Produktversion | Kompatibilitätsprüfung |
| Dienststartparameter | Nachweis der Verwendung |
| Include-Dateien | Vollständige Konfigurationskette |
| Wirksame Werte | Tatsächlicher Zustand |
| Geheimnisstatus | Schutzbedarf |
| Sicherungspfad | Rückfallmöglichkeit |

**Dokumentationsvorlage:**

```text
Dienst:
Produktversion:
Konfigurationsdatei:
Weitere Konfigurationsquellen:
Eigentümer:
Berechtigungen:
Änderungszeit:
SHA-256:
Wirksame Konfiguration geprüft:
Syntaxprüfung:
Herstellervalidierung:
Auffälliger Wert:
Letzte bekannte funktionierende Version:
Geplante Änderung:
Rückfallmöglichkeit:
```

</details>

---

<details>
<summary><strong>24. Kontrollierter Änderungsablauf</strong></summary>

Eine Konfigurationsänderung besteht nicht nur aus dem Bearbeiten einer Datei.

```text
1. Ursache und Sollwert bestimmen
2. Produktversion und Dokumentation prüfen
3. Originalzustand dokumentieren
4. Geschützte Sicherung erstellen
5. Genau eine fachliche Änderung durchführen
6. Syntax validieren
7. Produktspezifischen Konfigurationstest ausführen
8. Unterschied zur Ausgangsversion prüfen
9. Eigentümer und Berechtigungen kontrollieren
10. Reload oder Neustart nach Dokumentation planen
11. Protokolle während der Aktivierung beobachten
12. Technischen und fachlichen Funktionstest durchführen
13. Nebenwirkungen prüfen
14. Bei Fehlschlag kontrolliert zurückrollen
15. Ursache, Änderung und Ergebnis dokumentieren
```

**Risiken:**

- eine Sicherung im aktiven Include-Verzeichnis wird mitgeladen,
- Editor verändert Eigentümer oder Berechtigungen,
- temporäre Datei erhält falsche Zugriffsrechte,
- Reload wird unterstützt, übernimmt aber nicht alle Werte,
- Neustart unterbricht aktive Transaktionen,
- alte Konfiguration passt nicht mehr zur aktualisierten Software,
- Rückrollen der Datei reicht nach einer Datenmigration nicht aus.

</details>

---

<details>
<summary><strong>25. Reload, Neustart und Neuerstellung unterscheiden</strong></summary>

| Maßnahme | Wirkung |
|---|---|
| Reload | Dienst liest unterstützte Konfigurationsbereiche neu ein |
| Neustart | Prozess wird beendet und neu gestartet |
| Systemneustart | Gesamtes Betriebssystem startet neu |
| Containerneustart | Gleiche Containerinstanz wird erneut gestartet |
| Containerneuerstellung | Container wird aus Definition und Image neu erzeugt |
| Redeployment | Anwendung und Konfiguration werden erneut bereitgestellt |

**Prüffragen:**

- unterstützt der Dienst einen Reload?
- welche Einstellungen werden beim Reload übernommen?
- benötigt die Änderung einen vollständigen Neustart?
- wird die Datei nur beim Installieren eingelesen?
- wird Konfiguration in eine Datenbank importiert?
- wird der Container bei einer Neuerstellung mit identischen Parametern erzeugt?
- bleiben Volumes und Secrets erhalten?
- gehen Diagnoseinformationen beim Neustart verloren?

> Nicht jeder Dienst übernimmt jede Einstellung durch einen Reload. Die unterstützte Aktivierungsmethode muss aus der Produktdokumentation stammen.

</details>

---

<details>
<summary><strong>26. Typische Fehlinterpretationen</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „Die Datei ist syntaktisch gültig, also funktioniert die Konfiguration.“ | Werte, Pfade und Abhängigkeiten können trotzdem falsch sein |
| „Ich habe die Standarddatei geprüft.“ | Der Dienst kann eine andere Datei verwenden |
| „Die Datei wurde geändert, also nutzt der Prozess den neuen Wert.“ | Reload oder Neustart kann fehlen |
| „Der Wert steht nur einmal in der Hauptdatei.“ | Include, Variable oder Startparameter kann ihn überschreiben |
| „Manueller Start funktioniert.“ | Die Shell kann andere Variablen und Rechte besitzen |
| „Gleicher Dateiname bedeutet gleiche Konfiguration.“ | Inhalt muss mit Hash oder Vergleich geprüft werden |
| „Der neueste Änderungszeitpunkt zeigt den Verursacher.“ | Er zeigt nur eine Dateiänderung |
| „Die Beispielkonfiguration ist immer korrekt.“ | Sie muss zur eingesetzten Version passen |
| „Eine Sicherungsdatei im Konfigurationsordner ist ungefährlich.“ | Wildcard-Includes können sie mitladen |
| „Zurückkopieren der Datei stellt alles wieder her.“ | Daten-, Schema- oder Laufzeitänderungen können bestehen bleiben |

</details>

---

<details>
<summary><strong>27. Checkliste zur Konfigurationsanalyse</strong></summary>

```text
[ ] Richtigen Dienst und richtige Produktversion bestätigt
[ ] Tatsächliche Konfigurationsquelle ermittelt
[ ] Startparameter geprüft
[ ] Umgebungsvariablen berücksichtigt
[ ] Hauptdatei und Includes erfasst
[ ] Überschreibungsreihenfolge geklärt
[ ] Wirksame Konfiguration ermittelt
[ ] Datei vorhanden und nicht leer
[ ] Symbolische Links geprüft
[ ] Eigentümer und Berechtigungen geprüft
[ ] Arbeitsverzeichnis berücksichtigt
[ ] Syntax mit geeignetem Werkzeug geprüft
[ ] Produktspezifische Validierung durchgeführt
[ ] Pflichtwerte und Datentypen geprüft
[ ] Pfade und Zielsysteme geprüft
[ ] Port- und Protokollwerte geprüft
[ ] Versionskompatibilität geprüft
[ ] Referenzdatei gehört zur gleichen Version
[ ] Hash und Änderungszeit dokumentiert
[ ] Unterschiede zur funktionierenden Version geprüft
[ ] Secrets geschützt
[ ] Ausgangszustand gesichert
[ ] Genau eine Änderung geplant
[ ] Aktivierungsmethode geklärt
[ ] Rückfallmöglichkeit vorbereitet
[ ] Funktionstest festgelegt
```

</details>

---

**Bewertung des Ergebnisses**

| Ergebnis | Nächster Schritt |
|---|---|
| Falsche Datei wurde geprüft | Tatsächliche Konfigurationsquelle untersuchen |
| Syntax ungültig | Fehlerstelle sichern und nach Produktschema korrigieren |
| Syntax gültig, Wert aber falsch | Sollwert und Abhängigkeit prüfen |
| Datei wird überschrieben | Konfigurationspriorität und übergeordnete Quelle prüfen |
| Dienst verwendet alte Werte | Unterstützten Reload oder Neustart planen |
| Pfad existiert nicht | Deployment, Mount und Dateisystem prüfen |
| Dienstkonto kann Datei nicht lesen | Berechtigung und Eigentümer untersuchen |
| Option ist veraltet | Migrationsdokumentation der eingesetzten Version prüfen |
| Umgebungsvariable fehlt | Tatsächlichen Dienstkontext prüfen |
| Konfigurationen unterscheiden sich | Änderung fachlich bewerten und Ursache bestimmen |
| Konfiguration ist korrekt und wirksam | Berechtigungen, Ressourcen und Anwendung untersuchen |

---

**Merksatz**

> **Nicht die Datei, die ein Administrator bearbeitet, ist entscheidend, sondern die Konfiguration, die der Dienst im tatsächlichen Laufzeitkontext wirksam verwendet.**

---

**Weiterführende Quellen**

- [Microsoft Learn – Get-CimInstance](https://learn.microsoft.com/powershell/module/cimcmdlets/get-ciminstance)
- [Microsoft Learn – Get-FileHash](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/get-filehash)
- [Microsoft Learn – Compare-Object](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/compare-object)
- [Microsoft Learn – Test-Json](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/test-json)
- [Microsoft Learn – Get-Acl](https://learn.microsoft.com/powershell/module/microsoft.powershell.security/get-acl)
- [systemd – systemctl](https://www.freedesktop.org/software/systemd/man/latest/systemctl.html)
- [systemd – systemd-analyze](https://www.freedesktop.org/software/systemd/man/latest/systemd-analyze.html)
- [systemd – systemd-delta](https://www.freedesktop.org/software/systemd/man/latest/systemd-delta.html)
- [systemd – systemd.unit](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html)
- [Apple – plutil-Handbuchseite](https://keith.github.io/xcode-man-pages/plutil.1.html)
- [Apple – defaults-Handbuchseite](https://keith.github.io/xcode-man-pages/defaults.1.html)
- [Apple – launchctl-Handbuchseite](https://keith.github.io/xcode-man-pages/launchctl.1.html)
- [Apple – launchd.plist-Handbuchseite](https://keith.github.io/xcode-man-pages/launchd.plist.5.html)

# 4.9 Benutzer-, Dienstkonto- und Berechtigungsfehler

Jeder Dienst arbeitet in einem bestimmten Sicherheitskontext. Dieser entscheidet, auf welche Dateien, Verzeichnisse, Netzwerkressourcen, Zertifikate, Ports und Betriebssystemfunktionen der Dienst zugreifen darf.

> **Grundsatz:**  
> Ein erfolgreicher Zugriff als Administrator beweist nicht, dass das tatsächliche Dienstkonto denselben Zugriff besitzt.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- das verwendete Dienstkonto bestimmen können,
- Benutzer, Gruppen und Sicherheitskennungen prüfen können,
- Dateirechte und ACLs auswerten können,
- lokale und entfernte Berechtigungen unterscheiden können,
- fehlende Anmelderechte und gesperrte Konten erkennen können,
- den Zugriff im tatsächlichen Dienstkontext testen können,
- SELinux-, AppArmor- und macOS-Datenschutzbeschränkungen berücksichtigen können,
- Berechtigungsprobleme beheben, ohne unnötig weitreichende Rechte zu vergeben.

---

<details>
<summary><strong>1. Sicherheitskontext eines Dienstes verstehen</strong></summary>

Der Sicherheitskontext kann unter anderem enthalten:

- Benutzerkonto,
- primäre Gruppe,
- zusätzliche Gruppen,
- Sicherheitskennung beziehungsweise UID,
- Zugriffstoken,
- Benutzerrechte und Privilegien,
- Dateisystem-ACLs,
- Netzwerkidentität,
- Integritäts- und Sicherheitsstufe,
- SELinux- oder AppArmor-Kontext,
- systemd-Sandboxing,
- macOS-Datenschutzfreigaben,
- Containerbenutzer und Capabilities.

Bei jedem Zugriff bewertet das System mehrere Faktoren:

```text
Dienstkonto
  + Gruppenmitgliedschaften
  + lokale Rechte
  + ACLs des Zielobjekts
  + übergeordnete Verzeichnisrechte
  + Sicherheitsrichtlinien
  + Dienst- oder Containerbeschränkungen
  = effektiver Zugriff
```

</details>

---

<details>
<summary><strong>2. Authentifizierung und Autorisierung unterscheiden</strong></summary>

| Begriff | Leitfrage | Beispiel |
|---|---|---|
| Authentifizierung | Wer ist der Dienst? | Anmeldung als Dienstkonto |
| Autorisierung | Was darf dieses Konto? | Leserechte auf Konfigurationsdatei |
| Identifikation | Welches Konto wird verwendet? | UID, SID oder Benutzername |
| Gruppenmitgliedschaft | Welche Rollen besitzt das Konto? | Mitglied der Datenbankgruppe |
| Privileg | Welche Systemoperation ist erlaubt? | Binden an privilegierten Port |
| ACL | Welche Rechte gelten auf einem Objekt? | Schreiben in Datenverzeichnis |
| Sicherheitsrichtlinie | Welche zusätzliche Kontrolle greift? | SELinux oder macOS TCC |

**Typische Trennung:**

```text
Anmeldung fehlgeschlagen
  → Authentifizierungsproblem

Anmeldung erfolgreich, Zugriff verweigert
  → Autorisierungsproblem
```

</details>

---

<details>
<summary><strong>3. Typische Fehlerbilder eines Dienstkontos</strong></summary>

| Fehlerbild | Mögliche Ursache |
|---|---|
| Dienst startet nicht | Konto ungültig oder Anmelderecht fehlt |
| Zugriff verweigert | Datei-, ACL- oder Sicherheitsrichtlinienfehler |
| Lokaler Zugriff funktioniert, Netzwerkzugriff nicht | Andere Netzwerkidentität oder fehlende Remote-Berechtigung |
| Manueller Start funktioniert | Administrator besitzt mehr Rechte als Dienstkonto |
| Dienst funktioniert bis zum Kennwortwechsel | Hinterlegtes Dienstkennwort ist veraltet |
| Nur eine Datei ist nicht zugänglich | Abweichender Eigentümer oder ACL |
| Schreiben scheitert, Lesen funktioniert | Schreibrecht auf Datei oder Verzeichnis fehlt |
| Datei kann gelesen, aber nicht ersetzt werden | Änderungsrecht auf Verzeichnis fehlt |
| Programm ist ausführbar, startet aber nicht | Bibliothek, Arbeitsverzeichnis oder Sicherheitsrichtlinie blockiert |
| Zugriff funktioniert nach Anmeldung, aber nicht beim Boot | Benutzersitzung oder Netzlaufwerk fehlt |
| macOS-Dienst erhält trotz POSIX-Rechten keinen Zugriff | Datenschutzkontrolle oder Sandbox blockiert |
| Linux-Dienst erhält trotz Modus `777` keinen Zugriff | SELinux, AppArmor, Mountoption oder systemd-Sandboxing |

</details>

---

<details>
<summary><strong>4. Dienstkonto unter Windows bestimmen</strong></summary>

**Dienstkonto und Status anzeigen:**

```powershell
[RO] Get-CimInstance Win32_Service -Filter "Name='<DIENSTNAME>'" |
    Select-Object Name,
                  DisplayName,
                  State,
                  StartMode,
                  StartName,
                  ProcessId
```

**Alternative mit sc.exe:**

```powershell
[RO][SENS] sc.exe qc "<DIENSTNAME>"
```

Relevant ist:

```text
SERVICE_START_NAME
```

Typische Windows-Dienstkonten:

| Konto | Grundlegende Einordnung |
|---|---|
| `LocalSystem` | Sehr weitreichende lokale Rechte |
| `LocalService` | Begrenzte lokale Rechte |
| `NetworkService` | Begrenzte lokale Rechte, Netzwerkzugriff typischerweise als Computerkonto |
| Virtuelles Dienstkonto | Dienstbezogene lokale Identität |
| Lokales Benutzerkonto | Gilt primär auf dem lokalen System |
| Domänenkonto | Kann abhängig von Berechtigungen auf Domänenressourcen zugreifen |
| Gruppenverwaltetes Dienstkonto | Durch Active Directory verwaltetes Dienstkonto |

> Das Konto sollte nur die für den Dienst benötigten Rechte besitzen. Die Vergabe von Administratorrechten ist keine geeignete Standardlösung für ein Berechtigungsproblem.

</details>

---

<details>
<summary><strong>5. Aktuellen Windows-Benutzerkontext anzeigen</strong></summary>

Diese Befehle zeigen den Kontext der aktuellen Sitzung – nicht automatisch den Kontext des Dienstes.

**Benutzername anzeigen:**

```powershell
[RO] whoami
```

**Benutzer und SID anzeigen:**

```powershell
[RO] whoami /user
```

**Gruppen anzeigen:**

```powershell
[RO][SENS] whoami /groups
```

**Privilegien anzeigen:**

```powershell
[RO][SENS] whoami /priv
```

**Gesamten aktuellen Sicherheitskontext anzeigen:**

```powershell
[RO][SENS] whoami /all
```

> Die Ausgabe ist als Vergleich hilfreich. Sie darf aber nicht auf das Dienstkonto übertragen werden, wenn der Befehl in einer Administrator- oder Benutzersitzung ausgeführt wurde.

</details>

---

<details>
<summary><strong>6. Lokales Windows-Konto und Gruppen prüfen</strong></summary>

**Lokales Konto suchen:**

```powershell
[RO] Get-LocalUser -Name "<BENUTZER>" -ErrorAction SilentlyContinue
```

**Status eines lokalen Kontos anzeigen:**

```powershell
[RO][SENS] Get-LocalUser -Name "<BENUTZER>" |
    Select-Object Name,
                  Enabled,
                  LastLogon,
                  PasswordExpires,
                  PasswordRequired,
                  UserMayChangePassword
```

**Mitgliedschaften einer lokalen Gruppe anzeigen:**

```powershell
[RO][SENS] Get-LocalGroupMember -Group "<GRUPPE>"
```

**Alle lokalen Gruppen anzeigen:**

```powershell
[RO] Get-LocalGroup
```

**Einschränkungen:**

- `Get-LocalUser` prüft keine Domänenkonten.
- Domänenkonten benötigen Active-Directory-Werkzeuge oder eine Abfrage durch zuständige Administratoren.
- Gruppenmitgliedschaften können verschachtelt sein.
- Änderungen an Gruppenmitgliedschaften werden nicht in jedem laufenden Zugriffstoken sofort wirksam.
- Ein Dienstneustart kann erforderlich sein, damit ein neues Zugriffstoken erzeugt wird.

</details>

---

<details>
<summary><strong>7. Windows-Dateirechte mit Get-Acl prüfen</strong></summary>

**ACL einer Datei anzeigen:**

```powershell
[RO][FILE][SENS] Get-Acl -LiteralPath "<DATEI>" |
    Format-List
```

**Zugriffsregeln übersichtlich anzeigen:**

```powershell
[RO][FILE][SENS] (Get-Acl -LiteralPath "<DATEI>").Access |
    Select-Object IdentityReference,
                  FileSystemRights,
                  AccessControlType,
                  IsInherited,
                  InheritanceFlags,
                  PropagationFlags
```

**ACL eines Verzeichnisses anzeigen:**

```powershell
[RO][FILE][SENS] (Get-Acl -LiteralPath "<VERZEICHNIS>").Access |
    Select-Object IdentityReference,
                  FileSystemRights,
                  AccessControlType,
                  IsInherited
```

Wichtige Felder:

| Feld | Bedeutung |
|---|---|
| `IdentityReference` | Konto oder Gruppe |
| `FileSystemRights` | Zugewiesene Rechte |
| `Allow` | Erlaubende Regel |
| `Deny` | Verweigernde Regel |
| `IsInherited` | Regel wurde von übergeordnetem Objekt geerbt |
| `Owner` | Eigentümer des Objekts |

> Eine explizite Verweigerung kann eine erlaubende Berechtigung überstimmen. Die effektive Bewertung hängt jedoch von der vollständigen ACL und dem Zugriffstoken ab.

</details>

---

<details>
<summary><strong>8. Windows-Dateirechte mit icacls prüfen</strong></summary>

**ACL einer Datei oder eines Verzeichnisses anzeigen:**

```powershell
[RO][FILE][SENS] icacls "<PFAD>"
```

**ACLs unterhalb eines Verzeichnisses anzeigen:**

```powershell
[RO][FILE][SENS] icacls "<VERZEICHNIS>" /T /C
```

`/T` durchsucht Unterverzeichnisse rekursiv und kann bei großen Verzeichnisbäumen eine sehr umfangreiche Ausgabe erzeugen.

Typische Rechtekürzel:

| Kürzel | Bedeutung |
|---|---|
| `F` | Vollzugriff |
| `M` | Ändern |
| `RX` | Lesen und Ausführen |
| `R` | Lesen |
| `W` | Schreiben |
| `D` | Löschen |
| `N` | Kein Zugriff |
| `I` | Geerbte Regel |

Typische Vererbungskennzeichnungen:

| Kürzel | Bedeutung |
|---|---|
| `OI` | Vererbung an Dateien |
| `CI` | Vererbung an Unterverzeichnisse |
| `IO` | Regel gilt nur durch Vererbung |
| `NP` | Keine weitere Vererbung |

> Auf dieser Diagnoseseite wird `icacls` nur lesend verwendet. Parameter wie `/grant`, `/deny`, `/remove` oder `/reset` verändern Berechtigungen.

</details>

---

<details>
<summary><strong>9. Effektive Windows-Rechte mit AccessChk untersuchen</strong></summary>

`AccessChk` ist ein zusätzliches Microsoft-Sysinternals-Werkzeug und nicht Bestandteil jeder Windows-Installation.

**Grundlegende Prüfung eines Kontos auf einen bekannten Pfad:**

```powershell
[RO][FILE][SENS] accesschk.exe `
    -nobanner `
    -v `
    "<KONTO>" `
    "<PFAD>"
```

**Prüfung eines Verzeichnisses:**

```powershell
[RO][FILE][SENS] accesschk.exe `
    -nobanner `
    -d `
    -v `
    "<KONTO>" `
    "<VERZEICHNIS>"
```

Vor Verwendung prüfen:

- stammt das Werkzeug direkt von Microsoft Sysinternals?
- ist seine Verwendung im Unternehmen erlaubt?
- wird die passende Werkzeugversion verwendet?
- wird tatsächlich das Dienstkonto geprüft?
- enthält die Ausgabe sensible ACL- und Kontoinformationen?

> Wenn AccessChk nicht vorhanden oder nicht freigegeben ist, wird es nicht ungeprüft heruntergeladen oder auf einem Produktivserver installiert.

</details>

---

<details>
<summary><strong>10. Erforderliche Windows-Dienstprivilegien prüfen</strong></summary>

**Vom Dienst angeforderte Privilegien anzeigen:**

```powershell
[RO] sc.exe qprivs "<DIENSTNAME>"
```

**Wiederherstellungs- und Dienstkonfiguration ergänzend prüfen:**

```powershell
[RO] sc.exe qfailure "<DIENSTNAME>"
```

```powershell
[RO][SENS] sc.exe qc "<DIENSTNAME>"
```

**Wichtig:**

- `sc.exe qprivs` zeigt für den Dienst konfigurierte erforderliche Privilegien.
- Es beweist nicht allein, dass das Konto alle notwendigen Objektberechtigungen besitzt.
- Benutzerrechte wie „Anmelden als Dienst“ werden durch lokale oder domänenbasierte Sicherheitsrichtlinien vergeben.
- Domänenrichtlinien können lokale Einstellungen überschreiben.
- Fehlende Rechte erscheinen häufig im System- oder Sicherheitsprotokoll.

</details>

---

<details>
<summary><strong>11. Windows-Anmeldefehler des Dienstkontos untersuchen</strong></summary>

Typische Ursachen:

- falsches Kennwort,
- Kennwort abgelaufen,
- Konto deaktiviert,
- Konto gesperrt,
- „Anmelden als Dienst“ fehlt,
- „Anmelden als Dienst verweigern“ greift,
- Domänencontroller nicht erreichbar,
- Zeitabweichung verhindert Authentifizierung,
- verwaltetes Dienstkonto nicht korrekt eingerichtet,
- Dienst verwendet altes hinterlegtes Kennwort.

**Service-Control-Manager-Ereignisse prüfen:**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName      = "System"
    ProviderName = "Service Control Manager"
    StartTime    = (Get-Date).AddHours(-2)
} |
    Select-Object TimeCreated,
                  Id,
                  LevelDisplayName,
                  Message
```

**Sicherheitsereignisse erfordern entsprechende Berechtigungen:**

```powershell
[RO][SENS][PRIV] Get-WinEvent -FilterHashtable @{
    LogName   = "Security"
    StartTime = (Get-Date).AddHours(-2)
} |
    Select-Object TimeCreated,
                  Id,
                  ProviderName,
                  Message
```

> Das Sicherheitsprotokoll kann sehr viele sensible Informationen enthalten. Es sollte mit passenden Ereignis-IDs, Zeitfenstern und zuständigen Sicherheitsadministratoren ausgewertet werden.

</details>

---

<details>
<summary><strong>12. Windows-Netzwerkidentität des Dienstkontos berücksichtigen</strong></summary>

Der lokale Kontoname ist nicht zwingend die Identität, die ein entfernter Server sieht.

| Dienstkonto | Mögliche Netzwerkidentität |
|---|---|
| Lokales Benutzerkonto | Auf entferntem System nicht automatisch bekannt |
| `LocalService` | Netzwerkzugriff typischerweise anonym beziehungsweise sehr begrenzt |
| `NetworkService` | Zugriff im Domänenumfeld typischerweise als Computerkonto |
| `LocalSystem` | Zugriff im Domänenumfeld typischerweise als Computerkonto |
| Domänenkonto | Eigenes Domänenkonto |
| gMSA | Verwaltete Domänenidentität |

**Prüffragen:**

- Welche Identität sieht der Fileserver oder Datenbankserver?
- besitzt das Computerkonto Zugriff?
- besitzt nur der angemeldete Administrator Zugriff?
- wird Kerberos oder NTLM verwendet?
- stimmt der verwendete Servername mit dem erwarteten Dienstprinzipal überein?
- wird ein Laufwerksbuchstabe statt eines UNC-Pfads verwendet?
- ist das Dienstkonto auf der Zielressource berechtigt?
- existiert eine lokale und eine Freigabeberechtigung?

> Bei einer Windows-Freigabe müssen sowohl die Freigabeberechtigung als auch die NTFS-Berechtigung den benötigten Zugriff erlauben.

</details>

---

<details>
<summary><strong>13. Dienstkonto unter Linux bestimmen</strong></summary>

**systemd-Dienstkonto anzeigen:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=User,Group,DynamicUser,SupplementaryGroups
```

**Wirksame Unit prüfen:**

```bash
[RO][FILE][SENS] systemctl cat "<DIENST>"
```

**Benutzerkonto auflösen:**

```bash
[RO] getent passwd "<DIENSTBENUTZER>"
```

**Gruppenkonto auflösen:**

```bash
[RO] getent group "<DIENSTGRUPPE>"
```

**UID, primäre und zusätzliche Gruppen anzeigen:**

```bash
[RO] id "<DIENSTBENUTZER>"
```

**Wichtig:**

- eine leere `User=`-Eigenschaft bedeutet bei einem Systemdienst normalerweise, dass keine abweichende Benutzeridentität konfiguriert wurde,
- `DynamicUser=yes` erzeugt eine dynamisch verwaltete Identität,
- zusätzliche Gruppen können über `SupplementaryGroups=` gesetzt werden,
- ein Container kann innerhalb seines Namespaces andere UID-Zuordnungen verwenden.

</details>

---

<details>
<summary><strong>14. POSIX-Dateirechte unter Linux verstehen</strong></summary>

Beispiel:

```text
-rwxr-x--- 1 appuser appgroup 4096 Jul 31 09:00 application
```

Interpretation:

| Bereich | Bedeutung |
|---|---|
| `-` | Reguläre Datei |
| `rwx` | Eigentümer darf lesen, schreiben und ausführen |
| `r-x` | Gruppe darf lesen und ausführen |
| `---` | Andere besitzen keine Rechte |
| `appuser` | Eigentümer |
| `appgroup` | Gruppe |

Rechte:

| Recht | Datei | Verzeichnis |
|---|---|---|
| `r` | Dateiinhalt lesen | Verzeichnisinhalt auflisten |
| `w` | Dateiinhalt verändern | Einträge anlegen oder entfernen |
| `x` | Datei ausführen | Verzeichnis durchlaufen und Objekte erreichen |

> Schreibrecht auf einer Datei und Schreibrecht auf dem übergeordneten Verzeichnis sind unterschiedliche Berechtigungen. Das Ersetzen oder Löschen einer Datei hängt häufig vom Verzeichnisrecht ab.

</details>

---

<details>
<summary><strong>15. Linux-Dateirechte und Pfadbestandteile prüfen</strong></summary>

**Dateirechte anzeigen:**

```bash
[RO][FILE] ls -ld "<DATEI>"
```

**Numerische und symbolische Rechte anzeigen:**

```bash
[RO][FILE] stat -c '%U %G %A %a %n' "<DATEI>"
```

**Alle Bestandteile eines Pfads prüfen:**

```bash
[RO][FILE] namei -l "<DATEI>"
```

**Verzeichnis und Zieldatei gemeinsam prüfen:**

```bash
[RO][FILE] ls -ld "<VERZEICHNIS>" "<DATEI>"
```

**Prüffragen:**

- darf das Dienstkonto jedes übergeordnete Verzeichnis durchlaufen?
- darf es die Datei lesen?
- darf es das Verzeichnis beschreiben?
- stimmen Eigentümer und Gruppe?
- greift das Gruppenrecht wirklich, weil das Konto Mitglied ist?
- ist das Dateisystem schreibgeschützt?
- verhindern Mountoptionen die Ausführung?
- handelt es sich um einen symbolischen Link?

</details>

---

<details>
<summary><strong>16. Linux-ACLs prüfen</strong></summary>

**ACL einer Datei anzeigen:**

```bash
[RO][FILE][SENS] getfacl "<DATEI>"
```

**ACL eines Verzeichnisses anzeigen:**

```bash
[RO][FILE][SENS] getfacl "<VERZEICHNIS>"
```

Mögliche Ausgabe:

```text
user::rw-
user:appuser:r--
group::r--
mask::r--
other::---
```

Wichtige Elemente:

| Eintrag | Bedeutung |
|---|---|
| `user::` | Rechte des Eigentümers |
| `user:name:` | Rechte eines bestimmten Benutzers |
| `group::` | Rechte der Eigentümergruppe |
| `group:name:` | Rechte einer bestimmten Gruppe |
| `mask::` | Maximale wirksame Rechte benannter Benutzer und Gruppen |
| `other::` | Rechte aller übrigen Benutzer |
| `default:` | Standard-ACL für neu erstellte Unterobjekte |

> Die ACL-Maske kann weitergehende angezeigte Einzelrechte begrenzen. Deshalb müssen sowohl Eintrag als auch `mask` bewertet werden.

</details>

---

<details>
<summary><strong>17. Linux-Zugriff im tatsächlichen Benutzerkontext testen</strong></summary>

Die folgenden Tests lesen oder verändern die Zieldatei nicht. Sie prüfen nur, ob der angegebene Zugriff laut Betriebssystem möglich ist.

**Leserecht prüfen:**

```bash
[TEST][PRIV] sudo -u "<DIENSTBENUTZER>" \
  test -r "<DATEI>"
```

**Schreibrecht prüfen:**

```bash
[TEST][PRIV] sudo -u "<DIENSTBENUTZER>" \
  test -w "<DATEI>"
```

**Ausführungsrecht prüfen:**

```bash
[TEST][PRIV] sudo -u "<DIENSTBENUTZER>" \
  test -x "<AUSFÜHRBARE_DATEI>"
```

**Verzeichniszugriff prüfen:**

```bash
[TEST][PRIV] sudo -u "<DIENSTBENUTZER>" \
  test -x "<VERZEICHNIS>"
```

**Rückgabecode unmittelbar anzeigen:**

```bash
[TEST][PRIV] sudo -u "<DIENSTBENUTZER>" \
  test -r "<DATEI>"

echo $?
```

| Rückgabecode | Bedeutung |
|---:|---|
| `0` | Bedingung erfüllt |
| ungleich `0` | Bedingung nicht erfüllt oder Prüfung nicht möglich |

**Einschränkung:**

Ein erfolgreicher `test -r`- oder `test -w`-Befehl beweist nicht, dass SELinux, AppArmor, Anwendungssandboxing oder produktspezifische Regeln jeden späteren Zugriff erlauben.

</details>

---

<details>
<summary><strong>18. Linux-Sonderrechte und Mountoptionen berücksichtigen</strong></summary>

**Mountoptionen des Zielpfads anzeigen:**

```bash
[RO][FILE] findmnt --target "<PFAD>"
```

Mögliche relevante Optionen:

| Option | Bedeutung |
|---|---|
| `ro` | Dateisystem ist schreibgeschützt |
| `rw` | Dateisystem ist beschreibbar |
| `noexec` | Direkte Ausführung von Dateien auf diesem Dateisystem wird verhindert |
| `nosuid` | Setuid- und Setgid-Wirkung wird eingeschränkt |
| `nodev` | Gerätedateien werden nicht interpretiert |

**Dateirechte einschließlich Sonderbits anzeigen:**

```bash
[RO][FILE] stat -c '%A %a %U %G %n' "<DATEI>"
```

Mögliche Sonderbits:

- Setuid,
- Setgid,
- Sticky Bit.

> Sonderrechte dürfen nicht als schnelle Problembehebung gesetzt werden. Eine falsche Verwendung kann erhebliche Sicherheitsrisiken erzeugen.

</details>

---

<details>
<summary><strong>19. SELinux als zusätzliche Zugriffskontrolle prüfen</strong></summary>

Diese Befehle sind nur auf Systemen mit installiertem SELinux-Werkzeug relevant.

**SELinux-Status anzeigen:**

```bash
[RO] getenforce
```

Mögliche Ergebnisse:

| Zustand | Bedeutung |
|---|---|
| `Enforcing` | Richtlinien werden durchgesetzt |
| `Permissive` | Verstöße werden protokolliert, aber nicht blockiert |
| `Disabled` | SELinux ist deaktiviert |

**SELinux-Kontext einer Datei anzeigen:**

```bash
[RO][FILE][SENS] ls -lZ "<DATEI>"
```

**Prozesskontext anzeigen:**

```bash
[RO][SENS] ps -eZ |
    grep -- "<PROZESS>"
```

**Aktuelle AVC-Verweigerungen suchen:**

```bash
[RO][SENS][PRIV] sudo ausearch -m AVC -ts recent
```

**Wichtig:**

- klassische Dateirechte können korrekt sein, während SELinux blockiert,
- ein falscher Dateikontext kann nach manuellem Kopieren entstehen,
- SELinux sollte nicht pauschal deaktiviert werden,
- eine Richtlinienänderung muss auf den tatsächlich benötigten Zugriff begrenzt sein,
- automatisch erzeugte Freigaberegeln müssen fachlich und sicherheitstechnisch geprüft werden.

</details>

---

<details>
<summary><strong>20. AppArmor als zusätzliche Zugriffskontrolle prüfen</strong></summary>

Diese Befehle gelten nur, wenn AppArmor installiert und aktiv ist.

**AppArmor-Status anzeigen:**

```bash
[RO][PRIV] sudo aa-status
```

**Kernel- und Systemmeldungen nach Verweigerungen durchsuchen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -k \
  --since "1 hour ago" |
    grep -i -- "apparmor"
```

**Mögliche Zustände:**

| Zustand | Bedeutung |
|---|---|
| Enforce | Profilregeln werden durchgesetzt |
| Complain | Verstöße werden protokolliert, aber normalerweise nicht blockiert |
| Unconfined | Prozess wird nicht durch ein AppArmor-Profil eingeschränkt |

> AppArmor darf nicht pauschal deaktiviert werden. Zuerst müssen Profil, verweigerter Pfad und tatsächlich erforderlicher Zugriff bestimmt werden.

</details>

---

<details>
<summary><strong>21. systemd-Sandboxing und Capabilities prüfen</strong></summary>

Auch ohne SELinux oder AppArmor kann systemd einen Dienst zusätzlich einschränken.

**Sicherheitsrelevante Eigenschaften anzeigen:**

```bash
[RO][SENS] systemctl show "<DIENST>" \
  --property=NoNewPrivileges,ProtectSystem,ProtectHome,PrivateTmp,PrivateDevices,ReadOnlyPaths,ReadWritePaths,InaccessiblePaths,CapabilityBoundingSet,AmbientCapabilities
```

Mögliche Einschränkungen:

| Eigenschaft | Mögliche Wirkung |
|---|---|
| `ProtectSystem=` | Teile des Dateisystems werden schreibgeschützt |
| `ProtectHome=` | Zugriff auf Benutzerverzeichnisse wird eingeschränkt |
| `PrivateTmp=` | Dienst erhält eigenes temporäres Verzeichnis |
| `PrivateDevices=` | Zugriff auf Geräte wird eingeschränkt |
| `ReadOnlyPaths=` | Bestimmte Pfade werden schreibgeschützt |
| `ReadWritePaths=` | Ausgewählte Pfade werden beschreibbar gemacht |
| `InaccessiblePaths=` | Pfade werden unzugänglich |
| `NoNewPrivileges=` | Erwerb neuer Privilegien wird verhindert |
| `CapabilityBoundingSet=` | Verfügbare Linux-Capabilities werden begrenzt |

> Ein erfolgreicher Zugriff aus einer normalen Shell beweist nicht, dass derselbe Pfad innerhalb der systemd-Sandbox verfügbar ist.

</details>

---

<details>
<summary><strong>22. Dienstkonto unter macOS bestimmen</strong></summary>

**Systemweiten launchd-Job anzeigen:**

```bash
[RO] launchctl print "system/<LABEL>"
```

**launchd-plist anzeigen:**

```bash
[RO][FILE][SENS] plutil -p "/Library/LaunchDaemons/<LABEL>.plist"
```

Relevante Schlüssel:

```text
UserName
GroupName
Program
ProgramArguments
WorkingDirectory
EnvironmentVariables
```

Falls `UserName` bei einem systemweiten LaunchDaemon nicht gesetzt ist, muss der tatsächliche Ausführungskontext anhand von launchd-Konfiguration und laufendem Prozess geprüft werden.

**Ausführungskonto eines laufenden Prozesses anzeigen:**

```bash
[RO][SENS] ps -p <PID> \
  -o user,uid,gid,pid,ppid,command
```

</details>

---

<details>
<summary><strong>23. Benutzer und Gruppen unter macOS prüfen</strong></summary>

**UID, GID und Gruppen eines Kontos anzeigen:**

```bash
[RO] id "<BENUTZER>"
```

**Lokales Benutzerkonto über Directory Service anzeigen:**

```bash
[RO][SENS] dscl . -read "/Users/<BENUTZER>"
```

**Bestimmte lokale Gruppe anzeigen:**

```bash
[RO][SENS] dscl . -read "/Groups/<GRUPPE>"
```

**Gruppenmitgliedschaft prüfen:**

```bash
[RO] dsmemberutil checkmembership \
  -U "<BENUTZER>" \
  -G "<GRUPPE>"
```

**Hinweise:**

- `dscl .` bezieht sich auf den lokalen Verzeichnisknoten,
- Netzwerk- oder Verzeichnisdienstkonten können weitere Werkzeuge erfordern,
- Gruppenmitgliedschaften können aus mehreren Verzeichnisquellen stammen,
- der aktuelle Prozess kann noch ein älteres Gruppen- und Berechtigungstoken verwenden.

</details>

---

<details>
<summary><strong>24. POSIX-Rechte und ACLs unter macOS prüfen</strong></summary>

**Rechte, Eigentümer und ACL anzeigen:**

```bash
[RO][FILE][SENS] ls -lde "<DATEI>"
```

**Erweiterte Attribute zusätzlich anzeigen:**

```bash
[RO][FILE][SENS] ls -lde@ "<DATEI>"
```

**Dateiflags anzeigen:**

```bash
[RO][FILE][SENS] ls -ldeO "<DATEI>"
```

**Metadaten strukturiert anzeigen:**

```bash
[RO][FILE] stat -f '%Su %Sg %Sp %N' "<DATEI>"
```

Mögliche zusätzliche Einflussfaktoren:

- POSIX-Rechte,
- ACL-Einträge,
- erweiterte Attribute,
- Dateiflags,
- schreibgeschütztes Volume,
- Datenschutzkontrollen,
- Sandbox,
- System Integrity Protection.

> Ein `+` in der Ausgabe von `ls -l` weist auf ACL-Einträge hin. Ein `@` weist auf erweiterte Attribute hin.

</details>

---

<details>
<summary><strong>25. Zugriff unter macOS im Benutzerkontext testen</strong></summary>

**Leserecht prüfen:**

```bash
[TEST][PRIV] sudo -u "<DIENSTBENUTZER>" \
  test -r "<DATEI>"
```

**Schreibrecht prüfen:**

```bash
[TEST][PRIV] sudo -u "<DIENSTBENUTZER>" \
  test -w "<DATEI>"
```

**Ausführungsrecht prüfen:**

```bash
[TEST][PRIV] sudo -u "<DIENSTBENUTZER>" \
  test -x "<AUSFÜHRBARE_DATEI>"
```

**Rückgabecode anzeigen:**

```bash
[TEST][PRIV] sudo -u "<DIENSTBENUTZER>" \
  test -r "<DATEI>"

echo $?
```

> Dieser Test bildet nicht automatisch den vollständigen launchd-, Sandbox- oder Datenschutzkontext eines Dienstes nach.

</details>

---

<details>
<summary><strong>26. macOS-Datenschutzkontrollen berücksichtigen</strong></summary>

macOS schützt unter anderem Zugriffe auf:

- Schreibtisch,
- Dokumente,
- Downloads,
- iCloud Drive,
- Netzwerkvolumes,
- Wechselmedien,
- Daten anderer Anwendungen,
- Kontakte und Kalender,
- Kamera und Mikrofon,
- Automation,
- Bedienungshilfen,
- vollständigen Festplattenzugriff.

Ein Zugriff kann trotz korrekter POSIX-Rechte und ACLs verweigert werden.

**Protokolle nach dem Prozess durchsuchen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'process == "<PROZESS>"' \
  --style compact \
  --no-pager
```

**Nach möglichen Zugriffsverweigerungen suchen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'process == "<PROZESS>" AND (messageType == error OR messageType == fault)' \
  --style compact \
  --no-pager
```

**Wichtig:**

- Datenschutzfreigaben werden über Systemeinstellungen oder Unternehmensverwaltung vergeben,
- Full Disk Access ist eine weitreichende Berechtigung,
- Freigaben dürfen nur vertrauenswürdigen und tatsächlich benötigten Programmen erteilt werden,
- die Datenschutzdatenbank darf nicht manuell manipuliert werden,
- ein Terminaltest kann andere Datenschutzrechte als der eigentliche Dienst besitzen.

</details>

---

<details>
<summary><strong>27. macOS System Integrity Protection und Dateiflags berücksichtigen</strong></summary>

**SIP-Status anzeigen:**

```bash
[RO] csrutil status
```

System Integrity Protection schützt bestimmte Systembereiche auch vor weitreichenden Benutzerkonten.

**Dateiflags prüfen:**

```bash
[RO][FILE] ls -ldeO "<DATEI>"
```

Mögliche Einflussfaktoren:

- geschützter Systempfad,
- unveränderliches Dateiflag,
- schreibgeschütztes Systemvolume,
- signierter Systembestandteil,
- Sandbox- oder Datenschutzregel.

> SIP darf nicht als allgemeine Fehlerbehebung deaktiviert werden. Zuerst muss geklärt werden, warum eine Anwendung auf einen geschützten Systembereich zugreifen möchte.

</details>

---

<details>
<summary><strong>28. Netzwerkfreigaben und entfernte Ressourcen prüfen</strong></summary>

Bei einer entfernten Ressource existieren mindestens zwei Berechtigungsebenen:

```text
Lokaler Dienstkontext
  → Netzwerkidentität
  → Authentifizierung am Ziel
  → Freigabe- oder Dienstberechtigung
  → Dateisystem- oder Objektberechtigung
```

**Prüffragen:**

- welche Identität wird am Zielsystem verwendet?
- existiert das Konto dort?
- ist das Konto gesperrt oder abgelaufen?
- besitzt es Freigabe- und Dateisystemrechte?
- ist Kerberos, NTLM, LDAP oder Zertifikatsauthentifizierung vorgesehen?
- funktioniert nur interaktiver Zugriff?
- wird ein benutzerbezogener Mount verwendet?
- ist das Ziel beim Systemstart bereits verfügbar?
- ist das verwendete Secret aktuell?
- protokolliert das Zielsystem den abgelehnten Zugriff?

> Die Berechtigungsprüfung muss auch auf dem Zielsystem erfolgen. Der Quellserver kann häufig nur feststellen, dass der Zugriff abgelehnt wurde.

</details>

---

<details>
<summary><strong>29. Containerbenutzer und Hostrechte berücksichtigen</strong></summary>

Ein Containerprozess kann innerhalb und außerhalb des Containers unterschiedliche Identitätsdarstellungen besitzen.

Zu prüfen sind:

- UID und GID im Container,
- UID- und GID-Zuordnung auf dem Host,
- Eigentümer des eingebundenen Volumes,
- Rootless- oder Rootful-Betrieb,
- User-Namespace,
- Container-Capabilities,
- schreibgeschützte Mounts,
- SELinux-Label des Volumes,
- Secrets und Config-Mounts,
- Netzwerkidentität des Dienstes.

Typisches Fehlerbild:

```text
Datei auf dem Host gehört UID 1000
Containerprozess läuft als UID 1001
Volume ist nur für UID 1000 beschreibbar
Anwendung meldet „Permission denied“
```

> Ein Wechsel des Containers auf Benutzer `root` ist keine geeignete Standardlösung. Zuerst müssen vorgesehene UID, GID und Volume-Berechtigungen aus der Image- beziehungsweise Herstellerdokumentation ermittelt werden.

</details>

---

<details>
<summary><strong>30. Leserecht, Schreibrecht und Änderungsrecht praktisch unterscheiden</strong></summary>

| Gewünschte Aktion | Typischer benötigter Zugriff |
|---|---|
| Dateiinhalt lesen | Leserecht auf Datei und Durchlaufrecht auf Verzeichnisse |
| Dateiinhalt verändern | Schreibrecht auf Datei |
| Neue Datei anlegen | Schreib- und Durchlaufrecht auf Verzeichnis |
| Datei ersetzen | Rechte auf Datei und beziehungsweise oder Verzeichnis, abhängig vom Verfahren |
| Datei löschen | Lösch- beziehungsweise Verzeichnisrecht |
| Programm ausführen | Ausführungsrecht und Zugriff auf Bibliotheken |
| Verzeichnis auflisten | Leserecht auf Verzeichnis |
| Pfad durchlaufen | Ausführungsrecht auf Verzeichnis |
| Logdatei erzeugen | Schreibrecht auf Zielverzeichnis |
| Socketdatei erstellen | Schreibrecht auf Laufzeitverzeichnis |

> Viele Anwendungen speichern eine Konfiguration, indem sie eine neue Datei erzeugen und anschließend die alte Datei ersetzen. Dafür kann Schreibrecht auf der ursprünglichen Datei allein unzureichend sein.

</details>

---

<details>
<summary><strong>31. Berechtigungsproblem sicher reproduzieren</strong></summary>

Ein geeigneter Test verändert möglichst wenig und verwendet das tatsächliche Konto.

**Testablauf:**

```text
1. Dienstkonto bestimmen
2. Zielobjekt und benötigte Aktion bestimmen
3. Aktuelle Rechte und ACLs sichern
4. Sicherheitsrichtlinien prüfen
5. Lesenden Zugriff im Dienstkontext testen
6. Protokolle auf Quelle und Ziel beobachten
7. Nur bei Bedarf einen freigegebenen Schreibtest verwenden
8. Ergebnis und Rückgabecode dokumentieren
9. Testdateien vollständig entfernen
10. Keine Rechte auf Verdacht erweitern
```

**Ungeeigneter Test:**

```text
Als Administrator Datei öffnen
```

**Besserer Test:**

```text
Mit tatsächlicher Dienstidentität exakt den benötigten Zugriff prüfen
```

</details>

---

<details>
<summary><strong>32. Warum chmod 777 oder Vollzugriff keine geeignete Diagnose ist</strong></summary>

Eine pauschale Rechteerweiterung:

- verschleiert die ursprünglich fehlende Einzelberechtigung,
- kann vertrauliche Daten offenlegen,
- erhöht das Risiko einer Manipulation,
- kann Sicherheitsrichtlinien verletzen,
- behebt SELinux, AppArmor oder TCC möglicherweise trotzdem nicht,
- kann nach Updates oder Wiederherstellungen bestehen bleiben,
- erschwert die spätere Rücknahme,
- widerspricht dem Prinzip der minimalen Rechte.

**Besseres Vorgehen:**

1. benötigte Aktion bestimmen,
2. tatsächliches Dienstkonto bestimmen,
3. aktuell fehlende Einzelberechtigung bestimmen,
4. vorgesehene Herstellerberechtigung prüfen,
5. kleinste ausreichende Änderung planen,
6. Änderung dokumentieren,
7. Funktion testen,
8. überflüssige Rechte ausschließen.

</details>

---

<details>
<summary><strong>33. Gruppenmitgliedschaft richtig bewerten</strong></summary>

Eine neue Gruppenmitgliedschaft ist nicht immer sofort in jedem Prozess wirksam.

Mögliche Gründe:

- laufender Prozess besitzt ein altes Zugriffstoken,
- Benutzer muss sich neu anmelden,
- Dienst muss kontrolliert neu gestartet werden,
- Gruppenmitgliedschaft wird zwischengespeichert,
- verschachtelte Gruppe wird verzögert ausgewertet,
- Domänencontroller sind noch nicht repliziert,
- Container besitzt eigene Benutzer- und Gruppendatenbank.

**Prüfung:**

```text
Konto Mitglied der Gruppe?
  ↓
Gruppe auf Zielobjekt berechtigt?
  ↓
ACL-Maske oder Deny-Regel berücksichtigt?
  ↓
Aktuelles Zugriffstoken enthält die Gruppe?
  ↓
Dienstprozess nach Änderung neu authentifiziert?
```

> Ein Neustart darf erst nach Erfassung des Ausgangszustands und Prüfung der Auswirkungen erfolgen.

</details>

---

<details>
<summary><strong>34. Typische Fehlinterpretationen</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „Administrator kann zugreifen, also stimmen die Rechte.“ | Dienstkonto besitzt einen anderen Sicherheitskontext |
| „Die Datei hat Leserecht, also kann der Dienst sie öffnen.“ | Übergeordnete Verzeichnisse und Sicherheitsrichtlinien zählen ebenfalls |
| „Der Benutzer steht in der ACL, also ist der Zugriff erlaubt.“ | Deny-Regeln, Gruppen und ACL-Masken können das Ergebnis verändern |
| „Linux-Modus 777 erlaubt immer alles.“ | SELinux, AppArmor, Mountoptionen und Sandbox können weiter blockieren |
| „Root darf auf jeden macOS-Pfad zugreifen.“ | SIP und Datenschutzkontrollen können zusätzliche Grenzen setzen |
| „Lokales Dienstkonto verwendet denselben Namen am Fileserver.“ | Die Netzwerkidentität kann eine andere sein |
| „Gruppenänderung ist sofort wirksam.“ | Laufender Prozess kann ein altes Token besitzen |
| „Schreibrecht auf Datei erlaubt das Ersetzen der Datei.“ | Dafür können Rechte auf dem Verzeichnis erforderlich sein |
| „Full Disk Access ist die einfachste Lösung.“ | Es ist eine sehr weitreichende Sicherheitsfreigabe |
| „Der Dienst benötigt Administratorrechte.“ | Meist muss nur eine konkrete Ressource passend berechtigt werden |

</details>

---

<details>
<summary><strong>35. Checkliste zur Berechtigungsanalyse</strong></summary>

```text
[ ] Tatsächliches Dienstkonto bestimmt
[ ] Benutzerkonto existiert und ist aktiviert
[ ] Kontosperre und Kennwortstatus geprüft
[ ] Primäre und zusätzliche Gruppen erfasst
[ ] UID, GID beziehungsweise SID dokumentiert
[ ] Dienstanmelderecht geprüft
[ ] Verweigernde Richtlinien berücksichtigt
[ ] Zieldatei und benötigte Aktion bestimmt
[ ] Rechte aller Pfadbestandteile geprüft
[ ] Eigentümer und Gruppe geprüft
[ ] ACLs und Vererbung geprüft
[ ] ACL-Maske beziehungsweise Deny-Regeln berücksichtigt
[ ] Dateisystem-Mountoptionen geprüft
[ ] Zugriff im tatsächlichen Konto getestet
[ ] Lokalen und entfernten Zugriff getrennt geprüft
[ ] Netzwerkidentität des Dienstes bestimmt
[ ] Zielsystemprotokoll geprüft
[ ] SELinux beziehungsweise AppArmor berücksichtigt
[ ] systemd-Sandboxing berücksichtigt
[ ] macOS-Datenschutz und SIP berücksichtigt
[ ] Container-UID und Volume-Rechte berücksichtigt
[ ] Keine pauschale Rechteerweiterung durchgeführt
[ ] Kleinste notwendige Änderung bestimmt
[ ] Ausgangsberechtigungen vor Änderung gesichert
[ ] Funktion und Sicherheit nach Änderung geprüft
```

</details>

---

**Bewertung des Ergebnisses**

| Ergebnis | Nächster Schritt |
|---|---|
| Dienstkonto ungültig oder gesperrt | Kontostatus und Verwaltungsprozess prüfen |
| Dienstanmeldung schlägt fehl | Kennwort, Anmelderecht und Richtlinien prüfen |
| Datei kann nicht gelesen werden | Pfad-, Datei- und ACL-Rechte prüfen |
| Datei lesbar, aber nicht schreibbar | Datei- und Verzeichnisrechte getrennt prüfen |
| Lokaler Zugriff funktioniert, Remotezugriff nicht | Netzwerkidentität und Zielberechtigung prüfen |
| Klassische Rechte stimmen, Zugriff bleibt verweigert | SELinux, AppArmor, Sandbox oder macOS-Datenschutz prüfen |
| Gruppenrecht fehlt im laufenden Prozess | Token- beziehungsweise Prozessneuerstellung planen |
| Container kann Volume nicht beschreiben | UID-, GID-, Mount- und Sicherheitslabel prüfen |
| Zugriff funktioniert nur als Administrator | Fehlende Einzelberechtigung des Dienstkontos bestimmen |
| Alle Berechtigungen stimmen | Ressourcen, Konfiguration und Anwendungslogik untersuchen |

---

**Merksatz**

> **Berechtigungen werden nicht danach bewertet, was ein Administrator darf, sondern danach, was das tatsächliche Dienstkonto im echten Laufzeit- und Zielsystemkontext darf.**

---

**Weiterführende Quellen**

- [Microsoft Learn – Service User Accounts](https://learn.microsoft.com/windows/win32/services/service-user-accounts)
- [Microsoft Learn – About Service Logon Accounts](https://learn.microsoft.com/windows/win32/ad/about-service-logon-accounts)
- [Microsoft Learn – whoami](https://learn.microsoft.com/windows-server/administration/windows-commands/whoami)
- [Microsoft Learn – Get-Acl](https://learn.microsoft.com/powershell/module/microsoft.powershell.security/get-acl)
- [Microsoft Learn – icacls](https://learn.microsoft.com/windows-server/administration/windows-commands/icacls)
- [Microsoft Sysinternals – AccessChk](https://learn.microsoft.com/sysinternals/downloads/accesschk)
- [Microsoft Learn – sc.exe qprivs](https://learn.microsoft.com/windows-server/administration/windows-commands/sc-qprivs)
- [Linux-Handbuch – credentials](https://man7.org/linux/man-pages/man7/credentials.7.html)
- [Linux-Handbuch – path_resolution](https://man7.org/linux/man-pages/man7/path_resolution.7.html)
- [Linux-Handbuch – acl](https://man7.org/linux/man-pages/man5/acl.5.html)
- [Linux-Handbuch – getfacl](https://man7.org/linux/man-pages/man1/getfacl.1.html)
- [systemd – systemd.exec](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html)
- [Apple Platform Security – Zugriff von Apps auf Dateien](https://support.apple.com/de-de/guide/security/secddd1d86a6/web)
- [Apple Support – Einstellungen für Datenschutz und Sicherheit](https://support.apple.com/de-de/guide/mac-help/mchl211c911f/mac)
- [Apple Support – Dateiberechtigungen und umask](https://support.apple.com/de-de/101914)
- [Apple – launchd.plist-Handbuchseite](https://keith.github.io/xcode-man-pages/launchd.plist.5.html)

# 4.10 Ressourcenengpässe erkennen

Ein Dienst kann korrekt konfiguriert sein und trotzdem langsam, instabil oder nicht erreichbar werden, wenn ihm oder dem Gesamtsystem benötigte Ressourcen fehlen.

> **Grundsatz:**  
> Ein einzelner hoher Messwert beweist noch keinen Engpass. Entscheidend sind Messdauer, Vergleichswerte, Auslastungsursache und der zeitliche Zusammenhang mit der Störung.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- CPU-, Arbeitsspeicher- und I/O-Engpässe erkennen können,
- Lastspitzen von dauerhaftem Ressourcenmangel unterscheiden können,
- System- und Prozesswerte getrennt untersuchen können,
- physischen, virtuellen und residenten Speicher unterscheiden können,
- Paging und Swapping richtig bewerten können,
- Datenträgerlatenz und Warteschlangen berücksichtigen können,
- Handle-, Thread-, Prozess- und Dateideskriptorgrenzen prüfen können,
- Ressourcenwerte über mehrere Messpunkte beobachten können,
- Betriebssystemprotokolle nach Ressourcenfehlern durchsuchen können,
- Ergebnisse mit dem Zeitpunkt einer Dienststörung verbinden können.

---

<details>
<summary><strong>1. Welche Ressourcen können einen Dienst begrenzen?</strong></summary>

| Ressource | Typisches Fehlerbild |
|---|---|
| CPU | Hohe Antwortzeiten, Zeitüberschreitungen, verzögerte Verarbeitung |
| Arbeitsspeicher | Paging, Prozessabbrüche, fehlgeschlagene Allokationen |
| Swap beziehungsweise Auslagerungsdatei | Hohe Latenz durch Speicherauslagerung |
| Datenträger-I/O | Lange Wartezeiten, blockierte Prozesse, langsame Datenbank |
| Speicherplatz | Schreiben, Starten oder Protokollieren schlägt fehl |
| Inodes | Linux kann trotz freiem Speicherplatz keine Dateien anlegen |
| Dateideskriptoren | Neue Dateien oder Sockets können nicht geöffnet werden |
| Windows-Handles | Zugriff auf Dateien, Registry, Events oder Prozesse schlägt fehl |
| Threads | Neue Aufgaben oder Verbindungen können nicht verarbeitet werden |
| Prozesslimit | Neue Prozesse können nicht erzeugt werden |
| Netzwerkbandbreite | Langsame Übertragung und Warteschlangen |
| Verbindungspool | Neue Datenbank- oder HTTP-Verbindungen warten |
| Portbereich | Neue ausgehende TCP-Verbindungen schlagen fehl |
| GPU oder Beschleuniger | Spezialisierte Berechnung kann nicht ausgeführt werden |
| Quota | Benutzer oder Dienst darf keine weiteren Daten speichern |
| Containerlimit | Dienst erreicht CPU-, RAM- oder Prozessgrenze des Containers |

</details>

---

<details>
<summary><strong>2. Auslastung und Engpass unterscheiden</strong></summary>

| Zustand | Beschreibung |
|---|---|
| Auslastung | Eine Ressource wird verwendet |
| Hohe Auslastung | Ressource wird stark verwendet, Dienst funktioniert aber noch |
| Sättigung | Neue Arbeit muss warten |
| Engpass | Ressourcenbegrenzung beeinträchtigt die benötigte Funktion |
| Überlast | Eingehende Arbeit übersteigt dauerhaft die Verarbeitungskapazität |
| Ressourcenleck | Verbrauch steigt, obwohl abgeschlossene Arbeit Ressourcen freigeben sollte |
| Grenzwertfehler | Konfiguriertes Limit wird vor der technischen Kapazität erreicht |

**Beispiel:**

```text
CPU-Auslastung: 95 %
Antwortzeit:     normal
Warteschlange:   niedrig
Fehler:          keine
```

Das ist hohe Auslastung, aber noch kein bewiesener Engpass.

```text
CPU-Auslastung: 95 %
Antwortzeit:     stark erhöht
Warteschlange:   wächst
Timeouts:        vorhanden
```

Hier besteht ein belastbarer Hinweis auf CPU-Sättigung.

</details>

---

<details>
<summary><strong>3. Immer über mehrere Messpunkte prüfen</strong></summary>

Eine Momentaufnahme kann zufällig während einer kurzen Lastspitze entstehen.

**Empfohlene Messstruktur:**

```text
Zeitpunkt
CPU gesamt
CPU des Dienstprozesses
verfügbarer Arbeitsspeicher
Swap- beziehungsweise Paging-Aktivität
Datenträger-I/O und Wartezeit
Anzahl aktiver Anfragen
Anwendungsantwortzeit
Fehlerrate
```

**Sinnvolle Vergleichszeiträume:**

- unmittelbar vor der Störung,
- während der Störung,
- unmittelbar danach,
- normaler Vergleichszeitraum,
- gleiche Uhrzeit an einem störungsfreien Tag,
- Zustand vor und nach einer Maßnahme.

> Ein Messwerkzeug erzeugt selbst Last. Abtastrate, Anzahl der Messwerte und Detailgrad müssen zum System passen.

</details>

---

<details>
<summary><strong>4. Schnellübersicht für Windows, Linux und macOS</strong></summary>

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Systemlaufzeit | `[RO] (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime` | `[RO] uptime` | `[RO] uptime` |
| Logische Prozessoren | `[RO] (Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors` | `[RO] nproc` | `[RO] sysctl -n hw.logicalcpu` |
| Prozessübersicht | `[RO] Get-Process` | `[RO] top` | `[RO] top` |
| Speicherübersicht | `[RO] Get-CimInstance Win32_OperatingSystem` | `[RO] free -h` | `[RO] memory_pressure` |
| Swap | `[RO] Get-CimInstance Win32_PageFileUsage` | `[RO] swapon --show` | `[RO] sysctl vm.swapusage` |
| Datenträgerübersicht | `[RO] Get-Volume` | `[RO] iostat` | `[RO] iostat` |
| Prozesslimits | Betriebssystemspezifisch | `[RO][FILE] cat /proc/<PID>/limits` | `[RO] launchctl limit` |
| Systemprotokolle | `[RO] Get-WinEvent` | `[RO][PRIV] sudo journalctl` | `[RO][PRIV] sudo log show` |

</details>

---

<details>
<summary><strong>5. CPU-Grunddaten unter Windows prüfen</strong></summary>

**Anzahl logischer Prozessoren anzeigen:**

```powershell
[RO] Get-CimInstance Win32_ComputerSystem |
    Select-Object NumberOfProcessors,
                  NumberOfLogicalProcessors
```

**Gesamte CPU-Auslastung als Momentaufnahme:**

```powershell
[RO] Get-CimInstance `
    Win32_PerfFormattedData_PerfOS_Processor `
    -Filter "Name='_Total'" |
    Select-Object Name,
                  PercentProcessorTime,
                  PercentUserTime,
                  PercentPrivilegedTime,
                  PercentIdleTime
```

**Mehrere Messpunkte mit Get-Counter erfassen:**

```powershell
[RO] Get-Counter `
    -Counter '\Processor(_Total)\% Processor Time' `
    -SampleInterval 2 `
    -MaxSamples 5
```

> Die Namen klassischer Windows-Leistungsindikatoren können auf lokalisierten Windows-Systemen übersetzt sein. Falls ein Counterpfad nicht gefunden wird, müssen die auf diesem System vorhandenen Zählersätze ermittelt werden.

**Verfügbare Zählersätze suchen:**

```powershell
[RO] Get-Counter -ListSet * |
    Select-Object CounterSetName |
    Sort-Object CounterSetName
```

</details>

---

<details>
<summary><strong>6. CPU-verbrauchende Windows-Prozesse ermitteln</strong></summary>

**Prozesse nach kumulierter CPU-Zeit sortieren:**

```powershell
[RO] Get-Process |
    Sort-Object CPU -Descending |
    Select-Object -First 15 Id,
                           ProcessName,
                           CPU,
                           StartTime
```

Die Eigenschaft `CPU` enthält die gesamte bisher verbrauchte Prozessorzeit des Prozesses in Sekunden. Sie ist kein momentaner Prozentwert.

**Momentane Prozessauslastung über formatierte Leistungsdaten:**

```powershell
[RO] Get-CimInstance Win32_PerfFormattedData_PerfProc_Process |
    Where-Object Name -NotIn "_Total", "Idle" |
    Sort-Object PercentProcessorTime -Descending |
    Select-Object -First 15 Name,
                           IDProcess,
                           PercentProcessorTime,
                           ThreadCount,
                           WorkingSetPrivate
```

**Bestimmte PID untersuchen:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id,
                  ProcessName,
                  StartTime,
                  CPU,
                  Threads,
                  HandleCount
```

> Die Prozess-CPU-Ausgabe kann bei mehreren logischen Prozessoren anders skaliert wirken als die gesamte Systemauslastung. Werte müssen im Kontext des verwendeten Messwerkzeugs interpretiert werden.

</details>

---

<details>
<summary><strong>7. Arbeitsspeicher unter Windows prüfen</strong></summary>

**Gesamten und freien physischen Speicher anzeigen:**

```powershell
[RO] Get-CimInstance Win32_OperatingSystem |
    Select-Object @{
        Name="TotalRAM_GiB"
        Expression={[math]::Round($_.TotalVisibleMemorySize / 1MB, 2)}
    }, @{
        Name="FreeRAM_GiB"
        Expression={[math]::Round($_.FreePhysicalMemory / 1MB, 2)}
    }, @{
        Name="FreeVirtualMemory_GiB"
        Expression={[math]::Round($_.FreeVirtualMemory / 1MB, 2)}
    }
```

Die CIM-Werte werden hier von KiB in GiB umgerechnet.

**Speicherindikatoren als Momentaufnahme:**

```powershell
[RO] Get-CimInstance Win32_PerfFormattedData_PerfOS_Memory |
    Select-Object AvailableMBytes,
                  PercentCommittedBytesInUse,
                  PagesPerSec,
                  PageReadsPerSec,
                  PageWritesPerSec,
                  PoolPagedBytes,
                  PoolNonpagedBytes
```

**Mehrere Messpunkte des verfügbaren Speichers:**

```powershell
[RO] Get-Counter `
    -Counter '\Memory\Available MBytes' `
    -SampleInterval 2 `
    -MaxSamples 5
```

> Ein niedriger Wert bei „freiem“ Speicher ist nicht automatisch ein Fehler, weil Betriebssysteme ungenutzten Speicher als Cache verwenden. Verfügbarer Speicher, Paging-Aktivität und Anwendungsfunktion müssen gemeinsam betrachtet werden.

</details>

---

<details>
<summary><strong>8. Speicherverbrauch von Windows-Prozessen prüfen</strong></summary>

**Nach Working Set sortieren:**

```powershell
[RO] Get-Process |
    Sort-Object WorkingSet64 -Descending |
    Select-Object -First 15 Id,
                           ProcessName,
                           @{
                               Name="WorkingSet_MiB"
                               Expression={[math]::Round($_.WorkingSet64 / 1MB, 2)}
                           },
                           @{
                               Name="PrivateMemory_MiB"
                               Expression={[math]::Round($_.PrivateMemorySize64 / 1MB, 2)}
                           }
```

**Bestimmten Prozess untersuchen:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id,
                  ProcessName,
                  WorkingSet64,
                  PrivateMemorySize64,
                  VirtualMemorySize64,
                  PagedMemorySize64,
                  PeakWorkingSet64
```

| Wert | Bedeutung |
|---|---|
| `WorkingSet64` | Derzeit im physischen Speicher befindliche Seiten |
| `PrivateMemorySize64` | Privat zugeordneter Speicher |
| `VirtualMemorySize64` | Virtueller Adressraum |
| `PagedMemorySize64` | Auslagerungsfähiger Speicher |
| `PeakWorkingSet64` | Bisheriger Höchstwert des Working Sets |

> Virtueller Speicher darf nicht direkt mit physisch belegtem RAM gleichgesetzt werden.

</details>

---

<details>
<summary><strong>9. Windows-Auslagerungsdatei prüfen</strong></summary>

**Nutzung der Auslagerungsdatei anzeigen:**

```powershell
[RO] Get-CimInstance Win32_PageFileUsage |
    Select-Object Name,
                  AllocatedBaseSize,
                  CurrentUsage,
                  PeakUsage
```

Die Größen werden üblicherweise in MiB angegeben.

**Konfiguration der Auslagerungsdatei anzeigen:**

```powershell
[RO] Get-CimInstance Win32_PageFileSetting |
    Select-Object Name,
                  InitialSize,
                  MaximumSize
```

Mögliche Hinweise auf Speicherdruck:

- `PercentCommittedBytesInUse` bleibt sehr hoch,
- verfügbarer Speicher bleibt niedrig,
- Page Reads steigen dauerhaft,
- Anwendungen melden fehlenden virtuellen Speicher,
- Prozesse werden beendet,
- Antwortzeiten verschlechtern sich parallel zur Paging-Aktivität.

> Das Vorhandensein einer verwendeten Auslagerungsdatei ist nicht automatisch ein Fehler. Entscheidend ist eine dauerhaft hohe Paging-Aktivität zusammen mit Leistungsproblemen.

</details>

---

<details>
<summary><strong>10. Windows-Datenträger-I/O prüfen</strong></summary>

**Formatierte Datenträgerleistungsdaten anzeigen:**

```powershell
[RO] Get-CimInstance Win32_PerfFormattedData_PerfDisk_PhysicalDisk |
    Where-Object Name -ne "_Total" |
    Select-Object Name,
                  DiskReadsPerSec,
                  DiskWritesPerSec,
                  DiskReadBytesPerSec,
                  DiskWriteBytesPerSec,
                  AvgDiskQueueLength,
                  CurrentDiskQueueLength,
                  PercentDiskTime
```

**Mehrere Messpunkte mit Get-Counter:**

```powershell
[RO] Get-Counter `
    -Counter '\PhysicalDisk(*)\Avg. Disk sec/Read',
             '\PhysicalDisk(*)\Avg. Disk sec/Write',
             '\PhysicalDisk(*)\Current Disk Queue Length' `
    -SampleInterval 2 `
    -MaxSamples 5
```

Auch hier können lokalisierte Leistungsindikatornamen abweichen.

**Zu prüfen:**

- steigt die Warteschlange dauerhaft?
- sind Lese- oder Schreiblatenzen erhöht?
- ist nur ein Datenträger betroffen?
- korreliert die I/O-Last mit dem Dienstfehler?
- erzeugt Sicherung, Virenscan oder Update gleichzeitig Last?
- ist das Volume lokal, virtuell oder netzwerkbasiert?
- meldet das System zusätzlich Datenträgerfehler?

</details>

---

<details>
<summary><strong>11. Windows-Handles und Threads prüfen</strong></summary>

**Gesamtanzahl von Prozessen, Threads und Handles:**

```powershell
[RO] Get-CimInstance Win32_PerfFormattedData_PerfOS_System |
    Select-Object Processes, Threads
```

```powershell
[RO] Get-CimInstance Win32_PerfFormattedData_PerfOS_Objects |
    Select-Object Processes,
                  Threads,
                  Events,
                  Mutexes,
                  Sections,
                  Semaphores
```

**Prozesse nach Handleanzahl sortieren:**

```powershell
[RO] Get-Process |
    Sort-Object HandleCount -Descending |
    Select-Object -First 15 Id,
                           ProcessName,
                           HandleCount,
                           @{
                               Name="ThreadCount"
                               Expression={$_.Threads.Count}
                           }
```

**Bestimmten Prozess prüfen:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id,
                  ProcessName,
                  HandleCount,
                  @{
                      Name="ThreadCount"
                      Expression={$_.Threads.Count}
                  }
```

Ein mögliches Ressourcenleck zeigt sich eher durch kontinuierliches Wachstum als durch einen einzelnen hohen Wert.

</details>

---

<details>
<summary><strong>12. Windows-Protokolle nach Ressourcenfehlern durchsuchen</strong></summary>

**Systemereignisse der letzten zwei Stunden:**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = "System"
    StartTime = (Get-Date).AddHours(-2)
    Level     = 1, 2, 3
} |
    Select-Object TimeCreated,
                  ProviderName,
                  Id,
                  LevelDisplayName,
                  Message
```

**System- und Anwendungsereignisse gemeinsam:**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = "System", "Application"
    StartTime = (Get-Date).AddHours(-2)
} |
    Where-Object Message -Match "memory|resource|disk|paging|quota|handle|thread" |
    Sort-Object TimeCreated |
    Select-Object TimeCreated,
                  LogName,
                  ProviderName,
                  Id,
                  Message
```

> Textfilter hängen von Sprache und Formulierung der Ereignismeldung ab. Anbieter, Ereignis-ID und Zeitfenster sind zuverlässigere zusätzliche Filter.

</details>

---

<details>
<summary><strong>13. CPU und Load Average unter Linux prüfen</strong></summary>

**Systemlaufzeit und Load Average anzeigen:**

```bash
[RO] uptime
```

**Nur Load Average anzeigen:**

```bash
[RO][FILE] cat /proc/loadavg
```

**Anzahl verfügbarer Verarbeitungseinheiten anzeigen:**

```bash
[RO] nproc
```

**Interaktive Prozessübersicht:**

```bash
[RO] top
```

**Nach CPU-Verbrauch sortieren:**

```bash
[RO] ps -eo pid,ppid,user,stat,%cpu,%mem,etime,comm \
  --sort=-%cpu |
  head -n 16
```

**Falls sysstat installiert ist – CPU je Prozessor messen:**

```bash
[RO] mpstat -P ALL 2 5
```

> `mpstat`, `pidstat` und `iostat` gehören häufig zum Paket `sysstat`, sind aber nicht auf jeder Installation vorhanden.

</details>

---

<details>
<summary><strong>14. Linux Load Average richtig interpretieren</strong></summary>

Die drei Load-Average-Werte beziehen sich üblicherweise auf ungefähr:

```text
1 Minute
5 Minuten
15 Minuten
```

Load Average ist nicht dasselbe wie CPU-Prozent. Unter Linux werden dabei auch bestimmte Prozesse in nicht unterbrechbarem Wartezustand berücksichtigt.

**Grobe Einordnung:**

```text
Load Average
geteilt durch
Anzahl verfügbarer CPUs
```

Dies ist nur eine Orientierung.

| Beobachtung | Mögliche Interpretation |
|---|---|
| Hoher Load und hohe CPU-Nutzung | CPU-Sättigung möglich |
| Hoher Load und niedrige CPU-Nutzung | I/O-Wartezustände möglich |
| Kurzzeitig hoher 1-Minuten-Wert | Lastspitze |
| Hohe 1-, 5- und 15-Minuten-Werte | Länger andauernde Belastung |
| Load steigt, Warteschlange wächst | System verarbeitet Arbeit nicht schnell genug |

> Ein Load-Wert von `4` ist auf einem System mit zwei CPUs anders zu bewerten als auf einem System mit 32 CPUs.

</details>

---

<details>
<summary><strong>15. Linux-CPU über mehrere Messpunkte prüfen</strong></summary>

**Systemweite Messreihe mit vmstat:**

```bash
[RO] vmstat 2 5
```

Wichtige Spalten:

| Spalte | Bedeutung |
|---|---|
| `r` | Ausführungsbereite Prozesse |
| `b` | Prozesse in blockiertem Zustand |
| `us` | CPU-Zeit im Benutzerbereich |
| `sy` | CPU-Zeit im Kernelbereich |
| `id` | Leerlauf |
| `wa` | I/O-Wartezeit |
| `st` | Durch Hypervisor entnommene CPU-Zeit |
| `si` | Swap-In |
| `so` | Swap-Out |

> Die erste Zeile von `vmstat` kann Durchschnittswerte seit dem Systemstart darstellen. Für eine aktuelle Bewertung sind die folgenden Intervallzeilen wichtiger.

**Bestimmten Prozess mit installiertem pidstat beobachten:**

```bash
[RO] pidstat -p <PID> 2 5
```

**Alle Prozesse mit hoher CPU-Aktivität beobachten:**

```bash
[RO] pidstat -u 2 5
```

</details>

---

<details>
<summary><strong>16. Arbeitsspeicher unter Linux prüfen</strong></summary>

**Lesbare Speicherübersicht:**

```bash
[RO] free -h
```

**Kernel-Speicherinformationen:**

```bash
[RO][FILE] cat /proc/meminfo
```

Wichtige Werte:

| Wert | Bedeutung |
|---|---|
| `MemTotal` | Gesamter physischer Speicher |
| `MemFree` | Vollständig ungenutzter Speicher |
| `MemAvailable` | Schätzung des für neue Anwendungen verfügbaren Speichers |
| `Buffers` | Pufferspeicher |
| `Cached` | Dateicache |
| `SwapTotal` | Gesamter Swap |
| `SwapFree` | Freier Swap |
| `Dirty` | Noch nicht auf Datenträger geschriebene Seiten |
| `Slab` | Kernel-Datenstrukturen |

> Für die praktische Bewertung ist `MemAvailable` meist aussagekräftiger als `MemFree`, weil Linux freien RAM bewusst als Cache nutzt.

</details>

---

<details>
<summary><strong>17. Linux-Prozesse nach Speicherverbrauch untersuchen</strong></summary>

**Nach residentem Speicher sortieren:**

```bash
[RO] ps -eo pid,ppid,user,stat,%cpu,%mem,rss,vsz,etime,comm \
  --sort=-rss |
  head -n 16
```

**Bestimmten Prozess anzeigen:**

```bash
[RO][SENS] ps -p <PID> \
  -o user,pid,ppid,stat,%cpu,%mem,rss,vsz,etime,cmd
```

**Detaillierte Prozessspeicherwerte:**

```bash
[RO][FILE][SENS] cat "/proc/<PID>/status"
```

Relevant sind unter anderem:

```text
VmPeak
VmSize
VmHWM
VmRSS
RssAnon
RssFile
VmSwap
Threads
```

| Wert | Bedeutung |
|---|---|
| `VmSize` | Virtueller Adressraum |
| `VmRSS` | Residenter physischer Speicher |
| `VmHWM` | Bisheriger Höchstwert des residenten Speichers |
| `VmSwap` | Für den Prozess ausgelagerter Speicher |
| `Threads` | Threadanzahl |

</details>

---

<details>
<summary><strong>18. Swap und Paging unter Linux prüfen</strong></summary>

**Aktive Swap-Bereiche anzeigen:**

```bash
[RO] swapon --show
```

**Gesamtnutzung anzeigen:**

```bash
[RO] free -h
```

**Swap-Aktivität über mehrere Messpunkte:**

```bash
[RO] vmstat 2 5
```

Relevant:

| Spalte | Bedeutung |
|---|---|
| `si` | Von Swap eingelesene Daten |
| `so` | In Swap geschriebene Daten |

**Bewertung:**

- verwendeter Swap allein beweist keinen aktuellen Engpass,
- dauerhaft hohe Werte bei `si` und `so` weisen auf aktiven Speicherdruck hin,
- gleichzeitige hohe I/O-Wartezeit kann die Anwendung stark verlangsamen,
- einzelne Prozesse können einen großen Teil des Speichers belegen,
- ein Container kann sein eigenes Speicherlimit erreichen, obwohl der Host noch freien RAM besitzt.

</details>

---

<details>
<summary><strong>19. Linux-Datenträger-I/O prüfen</strong></summary>

**Grundlegende Datenträgerstatistik:**

```bash
[RO] iostat
```

**Falls sysstat installiert ist – erweiterte Messreihe:**

```bash
[RO] iostat -xz 2 5
```

Wichtige Felder können je nach Version enthalten:

| Feld | Bedeutung |
|---|---|
| `r/s` | Lesevorgänge pro Sekunde |
| `w/s` | Schreibvorgänge pro Sekunde |
| `rkB/s` | Gelesene KiB pro Sekunde |
| `wkB/s` | Geschriebene KiB pro Sekunde |
| `await` | Durchschnittliche Wartezeit |
| `aqu-sz` | Durchschnittliche Warteschlangenlänge |
| `%util` | Anteil der Zeit mit aktiven I/O-Anfragen |

**Prozessbezogene I/O-Aktivität mit pidstat:**

```bash
[RO] pidstat -d 2 5
```

> `%util` und Warteschlangenwerte müssen zur Datenträgerart und Speicherarchitektur passend bewertet werden. RAID, SSD, SAN und virtuelle Datenträger verhalten sich unterschiedlich.

</details>

---

<details>
<summary><strong>20. Linux Pressure Stall Information prüfen</strong></summary>

Auf unterstützten Linux-Kernels stehen Druckinformationen unter `/proc/pressure` bereit.

**CPU-Druck:**

```bash
[RO][FILE] cat /proc/pressure/cpu
```

**Speicherdruck:**

```bash
[RO][FILE] cat /proc/pressure/memory
```

**I/O-Druck:**

```bash
[RO][FILE] cat /proc/pressure/io
```

Mögliche Zeilen:

```text
some
full
```

| Wert | Bedeutung |
|---|---|
| `some` | Mindestens eine Aufgabe wurde durch Ressourcenmangel verzögert |
| `full` | Alle nicht im Leerlauf befindlichen Aufgaben waren gleichzeitig verzögert |
| `avg10` | Durchschnitt der letzten 10 Sekunden |
| `avg60` | Durchschnitt der letzten 60 Sekunden |
| `avg300` | Durchschnitt der letzten 300 Sekunden |
| `total` | Kumulierte Verzögerungszeit in Mikrosekunden |

> Fehlen die Dateien, unterstützt oder aktiviert das System diese Schnittstelle möglicherweise nicht.

</details>

---

<details>
<summary><strong>21. Linux-Dateideskriptor- und Prozessgrenzen prüfen</strong></summary>

**Grenzwerte eines laufenden Prozesses:**

```bash
[RO][FILE] cat "/proc/<PID>/limits"
```

Besonders relevant:

```text
Max open files
Max processes
Max locked memory
Max address space
Max core file size
```

**Anzahl geöffneter Dateideskriptoren:**

```bash
[RO][PRIV] sudo find "/proc/<PID>/fd" \
  -mindepth 1 \
  -maxdepth 1 \
  -printf '.' |
    wc -c
```

**systemd-Grenzwerte anzeigen:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=LimitNOFILE,LimitNPROC,TasksCurrent,TasksMax,MemoryCurrent,MemoryMax,CPUQuotaPerSecUSec
```

**Aktuelle Shell-Grenzen anzeigen:**

```bash
[RO] ulimit -a
```

> `ulimit -a` zeigt die Grenzen der aktuellen Shell und nicht automatisch die Grenzen eines bereits laufenden Dienstes.

</details>

---

<details>
<summary><strong>22. Linux-Protokolle nach Ressourcenfehlern durchsuchen</strong></summary>

**Warnungen und Fehler des aktuellen Systemstarts:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -b \
  -p warning \
  --no-pager
```

**Kernelmeldungen nach Speicherproblemen durchsuchen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -k \
  -b \
  --no-pager |
    grep -i -E -- "out of memory|oom|killed process|memory cgroup"
```

**Nach I/O- und Dateisystemproblemen suchen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -k \
  -b \
  --no-pager |
    grep -i -E -- "i/o error|filesystem|read-only|blocked for more than"
```

**Dienstprotokoll im Störungszeitraum:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  --since "2026-07-31 09:10:00" \
  --until "2026-07-31 09:20:00" \
  --no-pager
```

</details>

---

<details>
<summary><strong>23. CPU und Load Average unter macOS prüfen</strong></summary>

**Systemlaufzeit und Load Average:**

```bash
[RO] uptime
```

**Logische und physische CPUs:**

```bash
[RO] sysctl -n hw.logicalcpu
```

```bash
[RO] sysctl -n hw.physicalcpu
```

**Interaktive Übersicht nach CPU-Nutzung:**

```bash
[RO] top -o cpu
```

**Fünf Messungen im Abstand von zwei Sekunden:**

```bash
[RO] top \
  -l 5 \
  -s 2 \
  -o cpu \
  -stats pid,command,cpu,mem,threads,state,time
```

**Bestimmten Prozess beobachten:**

```bash
[RO] top \
  -l 5 \
  -s 2 \
  -pid <PID> \
  -stats pid,command,cpu,mem,threads,state,time
```

> Bei `top -l` kann die erste CPU-Messung ungeeignet sein, weil zur Prozentberechnung noch kein vollständiges vorheriges Intervall vorliegt.

</details>

---

<details>
<summary><strong>24. Speicher unter macOS prüfen</strong></summary>

**Speicherdruck anzeigen:**

```bash
[RO] memory_pressure
```

**Virtuelle Speicherstatistik:**

```bash
[RO] vm_stat
```

**Gesamten physischen Speicher anzeigen:**

```bash
[RO] sysctl -n hw.memsize
```

**Swap-Nutzung anzeigen:**

```bash
[RO] sysctl vm.swapusage
```

**Prozesse nach Speicherverbrauch sortieren:**

```bash
[RO] ps -Amcwwxo pid,ppid,user,state,%cpu,%mem,rss,vsz,etime,command
```

**Bestimmten Prozess anzeigen:**

```bash
[RO][SENS] ps -p <PID> \
  -o user,pid,ppid,state,%cpu,%mem,rss,vsz,etime,command
```

> macOS verwaltet Arbeitsspeicher unter anderem durch Cache, Kompression und Swap. „Freier Speicher“ allein ist deshalb weniger aussagekräftig als Speicherdruck, Swap-Aktivität und Anwendungsreaktion.

</details>

---

<details>
<summary><strong>25. vm_stat unter macOS interpretieren</strong></summary>

`vm_stat` zeigt Speicherwerte in Seiten an. Die Seitengröße wird in der ersten Ausgabezeile genannt.

Wichtige Werte können sein:

| Wert | Bedeutung |
|---|---|
| `Pages free` | Freie Seiten |
| `Pages active` | Aktiv verwendete Seiten |
| `Pages inactive` | Inaktive, möglicherweise wiederverwendbare Seiten |
| `Pages speculative` | Spekulativ geladene Seiten |
| `Pages wired down` | Nicht auslagerbarer Speicher |
| `Pages occupied by compressor` | Durch Speicherkompression belegte Seiten |
| `Pageins` | Vom Datenträger eingelesene Seiten |
| `Pageouts` | Auf Datenträger ausgelagerte Seiten |
| `Swapins` | Aus Swap eingelesene Seiten |
| `Swapouts` | In Swap geschriebene Seiten |

> Viele Werte sind kumuliert seit dem Systemstart. Für aktuelle Aktivität müssen Messungen über einen definierten Zeitraum verglichen werden.

</details>

---

<details>
<summary><strong>26. Datenträger-I/O unter macOS prüfen</strong></summary>

**Datenträgerübersicht:**

```bash
[RO] iostat
```

**Fünf Messungen im Abstand von zwei Sekunden:**

```bash
[RO] iostat -w 2 -c 5
```

**CPU- und Datenträgerstatistik ausführlicher anzeigen:**

```bash
[RO] iostat -d -c 5 -w 2
```

**Prozessbezogene Beobachtung mit top:**

```bash
[RO] top \
  -l 5 \
  -s 2 \
  -o cpu \
  -stats pid,command,cpu,mem,purg,cmprs,pageins,faults
```

Zu prüfen:

- steigt Datenträgeraktivität während der Störung?
- tritt gleichzeitig Speicherdruck auf?
- verursacht ein anderer Prozess hohe I/O-Last?
- ist das Ziel ein internes, externes oder Netzwerkvolume?
- gibt es Dateisystem- oder Hardwaremeldungen?
- wird gleichzeitig gesichert, indiziert oder aktualisiert?

</details>

---

<details>
<summary><strong>27. Prozess- und Dateigrenzen unter macOS prüfen</strong></summary>

**Grenzwerte von launchd anzeigen:**

```bash
[RO] launchctl limit
```

**Grenzwerte der aktuellen Shell anzeigen:**

```bash
[RO] ulimit -a
```

**Offene Ressourcen eines Prozesses anzeigen:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -p <PID>
```

**Anzahl der ausgegebenen offenen Ressourcen grob zählen:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -p <PID> |
    wc -l
```

Die Kopfzeile von `lsof` wird dabei mitgezählt.

**Threadanzahl anzeigen:**

```bash
[RO] ps -M -p <PID>
```

> Die Grenzwerte einer Shell sind nicht automatisch mit denen eines launchd-Dienstes identisch. Für den Dienst müssen launchd-Konfiguration, Prozesskontext und tatsächlicher Verbrauch berücksichtigt werden.

</details>

---

<details>
<summary><strong>28. macOS-Protokolle nach Ressourcenproblemen prüfen</strong></summary>

**Fehler und Faults der letzten Stunde:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'messageType == error OR messageType == fault' \
  --style compact \
  --no-pager
```

**Dienstprozess filtern:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'process == "<PROZESS>"' \
  --style compact \
  --no-pager
```

**Nach ressourcenbezogenen Meldungstexten suchen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'eventMessage CONTAINS[c] "memory" OR eventMessage CONTAINS[c] "resource" OR eventMessage CONTAINS[c] "disk"' \
  --style compact \
  --no-pager
```

> Textfilter sind nur eine Ergänzung. Prozess, Zeitfenster, Subsystem und konkrete Fehlermeldung müssen ebenfalls berücksichtigt werden.

</details>

---

<details>
<summary><strong>29. CPU-Engpass systematisch erkennen</strong></summary>

**Belastbare Hinweise:**

- CPU-Auslastung bleibt über längere Zeit hoch,
- ausführungsbereite Prozesse warten,
- Antwortzeiten steigen gleichzeitig,
- Anwendungswarteschlange wächst,
- Timeouts treten auf,
- ein bestimmter Prozess oder Thread verursacht den Großteil der Last,
- virtueller Host meldet hohe CPU-Steal- oder Ready-Zeit,
- CPU-Limit eines Containers wird erreicht.

**Mögliche Ursachen:**

- regulär hohe Benutzerlast,
- Endlosschleife,
- fehlerhafte Abfrage,
- Kompression oder Verschlüsselung,
- Virenscan,
- Sicherung,
- Softwareupdate,
- zu viele Prozesse oder Threads,
- zu niedriges Containerlimit,
- fehlende Hardwarebeschleunigung.

**Nicht ausreichend als Beweis:**

```text
Ein einzelner Messwert von 100 %
```

</details>

---

<details>
<summary><strong>30. Arbeitsspeicherengpass systematisch erkennen</strong></summary>

**Belastbare Hinweise:**

- verfügbarer Speicher bleibt dauerhaft niedrig,
- Paging oder Swapping ist kontinuierlich aktiv,
- Speicherdruck steigt,
- Antwortzeiten steigen parallel,
- Prozesse werden durch Speichermangel beendet,
- Anwendung meldet Allokationsfehler,
- Prozessspeicher wächst kontinuierlich,
- Container erreicht `MemoryMax` oder sein Plattformlimit,
- Cache kann nicht ausreichend zurückgewonnen werden.

**Mögliche Ursachen:**

- Speicherleck,
- zu großer Cache,
- unerwartet viele Sitzungen,
- zu große Datenmenge,
- mehrere speicherintensive Dienste,
- zu kleines VM- oder Containerlimit,
- fehlerhafte Heap-Konfiguration,
- fehlende Begrenzung von Workerprozessen.

> Ein Dienstneustart kann den Speicherverbrauch kurzfristig reduzieren, beweist aber nicht, dass die Ursache beseitigt wurde.

</details>

---

<details>
<summary><strong>31. I/O-Engpass systematisch erkennen</strong></summary>

**Belastbare Hinweise:**

- I/O-Wartezeiten steigen,
- Warteschlange bleibt gefüllt,
- Prozesse verbleiben im Wartezustand,
- Datenbankabfragen werden langsam,
- Schreibvorgänge blockieren,
- gleichzeitig erscheinen I/O- oder Dateisystemfehler,
- Netzwerkstorage zeigt hohe Latenz,
- Sicherung oder Indizierung erzeugt konkurrierende Last.

**Mögliche Ursachen:**

- langsamer oder fehlerhafter Datenträger,
- RAID-Rebuild,
- defekter Datenträger,
- überlastetes SAN oder NAS,
- hoher Speicherdruck und Paging,
- ungeeignete Datenbankabfrage,
- fehlender Cache,
- Sicherung oder Virenscan,
- zu viele parallele Schreibvorgänge,
- Volume- oder IOPS-Limit einer Cloudplattform.

> Hoher Datendurchsatz kann normal sein. Ein Engpass zeigt sich durch Wartezeit, Warteschlange und beeinträchtigte Anwendung.

</details>

---

<details>
<summary><strong>32. Ressourcenleck erkennen</strong></summary>

Ein Ressourcenleck wird durch eine Zeitreihe sichtbar.

Mögliche Lecks:

- Arbeitsspeicher,
- Handles,
- Dateideskriptoren,
- Threads,
- Netzwerkverbindungen,
- temporäre Dateien,
- Datenbankverbindungen,
- Warteschlangeneinträge.

**Typisches Muster:**

```text
Dienststart          niedriger Verbrauch
nach 1 Stunde        höherer Verbrauch
nach 6 Stunden       weiter gestiegen
nach 24 Stunden      Grenzwert erreicht
nach Dienstneustart  wieder niedriger Verbrauch
```

**Nachweisstrategie:**

1. gleiche Messgröße verwenden,
2. regelmäßige Zeitpunkte erfassen,
3. Last und Benutzerzahl mit dokumentieren,
4. Prozessneustarts berücksichtigen,
5. Grenzwert und Fehlereintritt bestimmen,
6. Herstellerdiagnose oder Profiler kontrolliert einsetzen.

> Wachstum kann durch einen vorgesehenen Cache entstehen. Ein Leck ist erst wahrscheinlich, wenn Ressourcen trotz abgeschlossener Arbeit nicht angemessen freigegeben werden und der Verbrauch problematisch weiter steigt.

</details>

---

<details>
<summary><strong>33. Virtualisierung und Containerlimits berücksichtigen</strong></summary>

Ein Gastbetriebssystem kann normale Hostwerte anzeigen, obwohl die Virtualisierungsplattform Ressourcen begrenzt.

Zu prüfen:

- zugewiesene virtuelle CPUs,
- CPU-Limit oder CPU-Anteile,
- CPU-Steal- beziehungsweise Ready-Zeit,
- zugesicherter und maximaler RAM,
- Memory Ballooning,
- Host-Swapping,
- IOPS- und Durchsatzlimits,
- Container-CPU-Quota,
- Container-Speicherlimit,
- Prozess- beziehungsweise PID-Limit,
- gemeinsam verwendete Hostressourcen,
- konkurrierende virtuelle Maschinen oder Container.

**Typische Fehlinterpretation:**

> „Der Host hat noch freien RAM, deshalb kann der Container keinen Speichermangel haben.“

Ein Container kann sein eigenes Limit erreichen, obwohl der Host noch freie Ressourcen besitzt.

</details>

---

<details>
<summary><strong>34. Engpass anhand einer Vergleichsmatrix eingrenzen</strong></summary>

| CPU | RAM | I/O-Wartezeit | Mögliche Richtung |
|---:|---:|---:|---|
| Hoch | Normal | Niedrig | CPU-intensive Verarbeitung |
| Niedrig | Knapp | Hoch | Paging oder Speicherdruck |
| Niedrig | Normal | Hoch | Datenträger- oder Netzwerkstorage |
| Hoch | Knapp | Hoch | Gesamtsystem überlastet |
| Niedrig | Normal | Niedrig | Externes Backend, Sperre oder Anwendung |
| Normal | Verbrauch steigt | Zunehmend | Mögliches Speicherleck |
| Normal | Normal | Normal | Anwendungs-, Netzwerk- oder Konfigurationsfehler |

Diese Matrix ist eine Eingrenzungshilfe und kein automatischer Ursachenbeweis.

</details>

---

<details>
<summary><strong>35. Typische Fehlinterpretationen</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „100 Prozent CPU bedeutet immer einen Fehler.“ | Kurze oder produktive Vollauslastung kann normal sein |
| „Freier RAM ist niedrig, also fehlt Speicher.“ | Cache und verfügbarer Speicher müssen berücksichtigt werden |
| „Swap wird verwendet, also ist das System überlastet.“ | Aktuelle Swap-Aktivität und Speicherdruck sind entscheidend |
| „Hoher Datendurchsatz bedeutet I/O-Engpass.“ | Wartezeit und Warteschlange sind entscheidender |
| „Load Average entspricht CPU-Prozent.“ | Load berücksichtigt unter Linux weitere Wartezustände |
| „Die erste vmstat-Zeile zeigt die aktuelle Last.“ | Sie kann Durchschnittswerte seit dem Start enthalten |
| „Get-Process CPU ist der aktuelle Prozentwert.“ | Es ist kumulierte CPU-Zeit |
| „Virtueller Speicher ist vollständig belegter RAM.“ | Virtueller Adressraum und residenter Speicher unterscheiden sich |
| „Ein Neustart behebt das Ressourcenproblem.“ | Er kann Zähler und Verbrauch nur vorübergehend zurücksetzen |
| „Der Host hat Ressourcen, also hat der Container sie ebenfalls.“ | Container und VM können eigene Limits besitzen |

</details>

---

<details>
<summary><strong>36. Dokumentationsvorlage für Ressourcenengpässe</strong></summary>

```text
Störung:
Server:
Dienst:
Prozess und PID:
Betriebssystem:
Virtualisiert beziehungsweise containerisiert:
Messzeitraum:
Abtastintervall:
CPU gesamt:
CPU des Prozesses:
Load Average:
Verfügbarer Arbeitsspeicher:
Speicher des Prozesses:
Swap- beziehungsweise Paging-Aktivität:
Datenträgerlatenz:
Datenträgerwarteschlange:
Dateideskriptor- beziehungsweise Handleanzahl:
Threadanzahl:
Konfigurierte Limits:
Anwendungsantwortzeit:
Fehlerrate:
Gleichzeitige Benutzer oder Aufgaben:
Relevante Protokollmeldung:
Vergleichswert:
Bewertung:
Nächster Prüfschritt:
```

</details>

---

<details>
<summary><strong>37. Checkliste zur Ressourcenanalyse</strong></summary>

```text
[ ] Störungszeitraum genau bestimmt
[ ] System- und Prozesswerte getrennt erfasst
[ ] Mehrere Messpunkte aufgenommen
[ ] Normalen Vergleichszeitraum bestimmt
[ ] Anzahl logischer CPUs berücksichtigt
[ ] CPU-Auslastung und Warteschlange geprüft
[ ] Load Average richtig eingeordnet
[ ] Verfügbaren Arbeitsspeicher geprüft
[ ] Prozessspeicher geprüft
[ ] Paging beziehungsweise Swapping geprüft
[ ] Speicherdruck berücksichtigt
[ ] Datenträgerdurchsatz geprüft
[ ] I/O-Wartezeit und Warteschlange geprüft
[ ] Speicherplatz und Dateisystem grob geprüft
[ ] Handle- beziehungsweise Dateideskriptoranzahl geprüft
[ ] Thread- und Prozessgrenzen geprüft
[ ] Ressourcenlecks über Zeitreihe geprüft
[ ] Betriebssystemprotokolle geprüft
[ ] Anwendungsprotokolle geprüft
[ ] VM- und Containerlimits berücksichtigt
[ ] Gleichzeitige Sicherungen und Updates berücksichtigt
[ ] Messwerte mit Antwortzeit und Fehlerrate korreliert
[ ] Noch keine ungeprüfte Limitänderung durchgeführt
[ ] Ursache und nächster Schritt dokumentiert
```

</details>

---

**Bewertung des Ergebnisses**

| Ergebnis | Nächster Schritt |
|---|---|
| CPU dauerhaft gesättigt | Verursachenden Prozess, Threads und Arbeitslast untersuchen |
| Hoher Load bei niedriger CPU | I/O-Wartezustände und blockierte Prozesse prüfen |
| Speicherdruck und aktives Swapping | Prozessspeicher, Limits und mögliches Leck untersuchen |
| Prozessverbrauch steigt kontinuierlich | Zeitreihe und Herstellerdiagnose erstellen |
| Datenträgerlatenz erhöht | Datenträger, Dateisystem, Storage und konkurrierende Last prüfen |
| Dateideskriptor- oder Handlegrenze erreicht | Leck, Grenzwert und benötigte Kapazität untersuchen |
| Containerlimit erreicht | Sollressourcen und Plattformkonfiguration prüfen |
| Host überlastet | Andere VMs, Container und Hostprozesse berücksichtigen |
| Ressourcenwerte normal | Abhängigkeiten, Sperren, Netzwerk und Anwendung untersuchen |
| Speicherplatz oder Dateisystem auffällig | Mit Seite 4.11 detailliert weiterprüfen |

---

**Merksatz**

> **Ein Ressourcenengpass wird nicht durch einen hohen Wert bewiesen, sondern durch dauerhaftes Warten, erreichte Grenzen und eine gleichzeitig beeinträchtigte Dienstfunktion.**

---

**Weiterführende Quellen**

- [Microsoft Learn – Get-Counter](https://learn.microsoft.com/powershell/module/microsoft.powershell.diagnostics/get-counter)
- [Microsoft Learn – Get-Process](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-process)
- [Microsoft Learn – Get-CimInstance](https://learn.microsoft.com/powershell/module/cimcmdlets/get-ciminstance)
- [Microsoft Learn – Win32_Process](https://learn.microsoft.com/windows/win32/cimwin32prov/win32-process)
- [Microsoft Learn – Windows-Leistungsüberwachung](https://learn.microsoft.com/windows-server/administration/windows-commands/typeperf)
- [Linux-Handbuch – proc_loadavg](https://man7.org/linux/man-pages/man5/proc_loadavg.5.html)
- [Linux-Handbuch – proc_meminfo](https://man7.org/linux/man-pages/man5/proc_meminfo.5.html)
- [Linux-Handbuch – proc_pid_limits](https://man7.org/linux/man-pages/man5/proc_pid_limits.5.html)
- [Linux-Handbuch – proc_pressure](https://man7.org/linux/man-pages/man5/proc_pressure.5.html)
- [systemd – systemd.resource-control](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html)
- [Apple – top-Handbuchseite](https://keith.github.io/xcode-man-pages/top.1.html)
- [Apple – vm_stat-Handbuchseite](https://keith.github.io/xcode-man-pages/vm_stat.1.html)
- [Apple – iostat-Handbuchseite](https://keith.github.io/xcode-man-pages/iostat.8.html)
- [Apple – launchctl-Handbuchseite](https://keith.github.io/xcode-man-pages/launchctl.1.html)

# 4.11 Speicherplatz- und Dateisystemfehler

Speicherplatzprobleme gehören zu den häufigsten Ursachen für Dienststörungen. Dabei muss ein Datenträger nicht vollständig belegt sein: Auch ausgeschöpfte Benutzerquoten, fehlende Inodes, schreibgeschützte Dateisysteme, Snapshots, nicht eingehängte Volumes oder Ein-/Ausgabefehler können Schreibvorgänge verhindern.

Typische Auswirkungen sind:

- Dienste starten nicht mehr.
- Datenbanken können keine Transaktionen schreiben.
- Protokoll-, temporäre oder PID-Dateien können nicht erstellt werden.
- Updates und Installationen schlagen fehl.
- Benutzerprofile werden nicht geladen oder gespeichert.
- Anwendungen melden irreführende Zugriffs- oder Datenbankfehler.
- Ein Dateisystem wird nach einem Fehler nur noch schreibgeschützt eingebunden.
- Dateien wurden gelöscht, belegen aber weiterhin Speicherplatz.
- Der Server besitzt freien Speicherplatz, aber eine Quote ist ausgeschöpft.

> **Wichtig:** Freier Speicherplatz allein reicht nicht als Prüfung. Untersucht werden müssen Kapazität, Inodes, Quoten, Einhängezustand, Schreibbarkeit, Dateisystemzustand und die zugrunde liegende Speicherhardware.

**Kennzeichnung der Befehle**

| Kennzeichnung | Bedeutung |
|---|---|
| `[RO]` | Nur lesender Befehl |
| `[TEST]` | Führt eine aktive Prüfung aus |
| `[PRIV]` | Erhöhte Berechtigungen erforderlich |
| `[FILE]` | Liest Dateien oder Verzeichnisse ein |
| `[SENS]` | Ausgabe kann sensible Informationen enthalten |
| `[CHANGE]` | Verändert Daten oder Systemzustand |
| `[DISRUPT]` | Kann den Betrieb unterbrechen |

---

<details>
<summary><strong>1. Fehlerbild und betroffenen Speicherpfad bestimmen</strong></summary>

Zuerst muss festgestellt werden, welcher konkrete Pfad nicht mehr funktioniert. Die Meldung „Datenträger voll“ sagt noch nicht, welches Volume, Dateisystem oder Speichersystem betroffen ist.

Zu klären sind:

- Welcher Dienst oder Benutzer ist betroffen?
- Welche Datei sollte gelesen oder geschrieben werden?
- Unter welchem Pfad liegt diese Datei?
- Welches Volume beziehungsweise Dateisystem enthält den Pfad?
- Handelt es sich um lokalen Speicher oder ein Netzlaufwerk?
- Ist der Pfad ein Mountpoint, symbolischer Link oder eine Freigabe?
- Ist nur ein Benutzer betroffen oder das gesamte System?
- Trat der Fehler nach einem Neustart, Update oder Speicherausbau auf?

**Typische Fehlermeldungen**

| Fehlermeldung | Mögliche Ursache |
|---|---|
| `No space left on device` | Speicherplatz oder Inodes ausgeschöpft |
| `Disk full` | Datenträger, Quote oder Speicherpool voll |
| `Read-only file system` | Dateisystem schreibgeschützt eingebunden |
| `Input/output error` | Dateisystem-, Datenträger- oder Controllerfehler |
| `Access denied` | Berechtigung, Quote oder schreibgeschützter Pfad |
| `File system is corrupt` | Inkonsistente Dateisystemstrukturen |
| `The volume is dirty` | Dateisystem wurde nicht sauber getrennt oder weist Fehler auf |
| Datei oder Verzeichnis fehlt | Volume möglicherweise nicht eingehängt |
| Schreiben funktioniert nur als Administrator | Quote, Berechtigung oder reservierter Speicherbereich |
| Freier Speicher wird nach dem Löschen nicht größer | Datei noch geöffnet, Snapshot oder Papierkorb |

**Prüffragen**

- Ist die Fehlermeldung im Original verfügbar?
- Welcher exakte Pfad wird in der Meldung genannt?
- Kann eine vorhandene Datei gelesen werden?
- Kann im Zielverzeichnis eine neue Datei erstellt werden?
- Funktioniert das Schreiben mit einem anderen Benutzer?
- Ist das erwartete Volume tatsächlich eingehängt?
- Stimmen Zeitpunkt und Umfang des Speicherverbrauchs mit einer Änderung überein?

> Ein Schreibtest darf nur in einem dafür vorgesehenen Verzeichnis durchgeführt werden. In Anwendungs-, Datenbank- oder Systemverzeichnissen dürfen nicht unkontrolliert Testdateien angelegt werden.

</details>

<details>
<summary><strong>2. Speicherschichten systematisch eingrenzen</strong></summary>

Zwischen einer Anwendung und dem physischen Datenträger können mehrere Speicherschichten liegen:

1. Anwendung oder Dienst
2. Datei und Verzeichnis
3. Dateisystem
4. Partition oder Volume
5. LVM-, Storage-Spaces- oder APFS-Container
6. Virtueller Datenträger
7. RAID, SAN, NAS oder Hypervisor-Datastore
8. Controller und physischer Datenträger

Ein Fehler kann auf jeder dieser Ebenen auftreten.

| Beobachtung | Wahrscheinliche Ebene |
|---|---|
| Nur eine Anwendung kann nicht schreiben | Anwendung, Pfad, Berechtigung oder Quote |
| Alle Anwendungen auf einem Volume sind betroffen | Dateisystem oder Volume |
| Volume fehlt nach einem Neustart | Mount-, Geräte- oder Konfigurationsfehler |
| Mehrere virtuelle Maschinen sind betroffen | Hypervisor, Datastore, SAN oder NAS |
| Betriebssystem meldet Ein-/Ausgabefehler | Datenträger, Controller oder Speicherverbindung |
| Gastbetriebssystem zeigt freien Platz, Datastore ist voll | Virtualisierungs- oder Thin-Provisioning-Ebene |
| Netzfreigabe ist betroffen, lokaler Speicher funktioniert | Netzwerkdateisystem oder Speicherserver |

**Besonderheit bei Thin Provisioning**

Bei dynamisch bereitgestelltem Speicher können unterschiedliche Ansichten entstehen:

- Das Gastbetriebssystem sieht freien Platz.
- Der zugrunde liegende Datastore oder Speicherpool ist jedoch voll.
- Eine virtuelle Festplatte besitzt eine große logische Größe, belegt physisch aber weniger.
- Snapshots können den realen Verbrauch stark erhöhen.

Deshalb müssen bei virtuellen Servern sowohl das Betriebssystem als auch Hypervisor und Speicherplattform kontrolliert werden.

</details>

<details>
<summary><strong>3. Speicherbelegung unter Windows prüfen</strong></summary>

**Volumes und freien Speicher anzeigen**

```powershell
[RO] Get-Volume |
    Select-Object DriveLetter, FileSystemLabel, FileSystem,
        HealthStatus, OperationalStatus, SizeRemaining, Size
```

**Belegung in Prozent berechnen**

```powershell
[RO] Get-Volume |
    Where-Object { $_.Size -gt 0 } |
    Select-Object DriveLetter, FileSystemLabel,
        @{Name='Belegt_GB';Expression={[math]::Round(($_.Size-$_.SizeRemaining)/1GB,2)}},
        @{Name='Frei_GB';Expression={[math]::Round($_.SizeRemaining/1GB,2)}},
        @{Name='Belegt_Prozent';Expression={[math]::Round((($_.Size-$_.SizeRemaining)/$_.Size)*100,1)}}
```

**Datenträger anzeigen**

```powershell
[RO] Get-Disk |
    Select-Object Number, FriendlyName, PartitionStyle,
        OperationalStatus, HealthStatus, Size
```

**Partitionen anzeigen**

```powershell
[RO] Get-Partition |
    Select-Object DiskNumber, PartitionNumber, DriveLetter,
        Type, Size, OperationalStatus
```

**Informationen zu einem bestimmten Volume**

```powershell
[RO] Get-Volume -DriveLetter <BUCHSTABE>
```

Beispiel:

```powershell
[RO] Get-Volume -DriveLetter C
```

**NTFS-Dirty-Bit abfragen**

```cmd
[RO][PRIV] fsutil dirty query <LAUFWERK>:
```

Beispiel:

```cmd
[RO][PRIV] fsutil dirty query C:
```

**NTFS-Quoten abfragen**

```cmd
[RO][PRIV][SENS] fsutil quota query <LAUFWERK>:
```

Beispiel:

```cmd
[RO][PRIV][SENS] fsutil quota query D:
```

**Große Dateien in einem bekannten Verzeichnis suchen**

```powershell
[TEST][FILE][SENS] Get-ChildItem -LiteralPath "<PFAD>" -File -Recurse -ErrorAction SilentlyContinue |
    Sort-Object Length -Descending |
    Select-Object -First 20 FullName,
        @{Name='Groesse_GB';Expression={[math]::Round($_.Length/1GB,2)}}
```

> Eine rekursive Suche kann auf großen Verzeichnissen, Dateiservern oder langsamen Datenträgern erhebliche Last und lange Laufzeiten verursachen. Die Suche sollte auf den betroffenen Pfad begrenzt werden.

**Typische Windows-Ursachen**

- Windows-Update-Dateien
- Speicherabbilder und Dump-Dateien
- Stark wachsende Anwendungsprotokolle
- Datenbank- und Transaktionsprotokolle
- Benutzerprofile und Benutzerverzeichnisse
- Papierkorb
- Schattenkopien
- Temporäre Dateien
- Nicht mehr verwendete virtuelle Festplatten
- Sicherungsdateien auf dem Produktivvolume
- Ausgeschöpfte NTFS-Quoten

</details>

<details>
<summary><strong>4. Speicherbelegung unter Linux prüfen</strong></summary>

**Kapazität und Dateisystemtyp anzeigen**

```bash
[RO] df -hT
```

**Belegung für einen bestimmten Pfad anzeigen**

```bash
[RO] df -hT "<PFAD>"
```

**Inode-Belegung anzeigen**

```bash
[RO] df -i
```

**Blockgeräte und Dateisysteme anzeigen**

```bash
[RO] lsblk -f
```

**Eingehängte Dateisysteme übersichtlich anzeigen**

```bash
[RO] findmnt
```

**Zugehöriges Dateisystem eines Pfades ermitteln**

```bash
[RO] findmnt --target "<PFAD>"
```

**Mount-Optionen eines Pfades anzeigen**

```bash
[RO] findmnt -no TARGET,SOURCE,FSTYPE,OPTIONS --target "<PFAD>"
```

**Größe eines bestimmten Verzeichnisses ermitteln**

```bash
[TEST][FILE] du -sh "<PFAD>"
```

**Direkte Unterverzeichnisse nach Größe sortieren**

```bash
[TEST][FILE][PRIV][SENS] sudo du -xhd1 "<PFAD>" | sort -h
```

Bedeutung von `-x`:

- Die Auswertung bleibt innerhalb desselben Dateisystems.
- Andere eingehängte Dateisysteme werden nicht mitgezählt.
- Dadurch wird vermieden, versehentlich Netzlaufwerke oder weitere Volumes zu durchsuchen.

**Benutzerquote anzeigen, sofern Quoten eingerichtet sind**

```bash
[RO][SENS] quota -s
```

**Quota-Bericht für Dateisysteme anzeigen**

```bash
[RO][PRIV][SENS] sudo repquota -a
```

> Die Programme `quota` und `repquota` sind nicht auf jedem Linux-System standardmäßig installiert. Zudem müssen Quoten auf dem betreffenden Dateisystem eingerichtet sein.

**Typische Linux-Ursachen**

- Stark wachsende Dateien unter `/var/log`
- Container-Images und Container-Logs
- Paket- und Update-Caches
- Temporäre Dateien
- Datenbankdateien
- Core-Dumps
- Alte Kernel oder Pakete
- Nicht rotierte Protokolldateien
- Gelöschte, aber weiterhin geöffnete Dateien
- Ausgeschöpfte Inodes
- Snapshots von LVM, Btrfs oder ZFS
- Ein unerwartet nicht eingehängtes Datenvolume

> `du` liest Verzeichnisstrukturen ein und kann auf großen Dateisystemen viel Ein-/Ausgabelast erzeugen. Auf Produktivsystemen sollte die Untersuchung auf kleine und verdächtige Pfade begrenzt werden.

</details>

<details>
<summary><strong>5. Speicherbelegung unter macOS prüfen</strong></summary>

**Belegung der Dateisysteme anzeigen**

```bash
[RO] df -h
```

**Belegung für einen bestimmten Pfad anzeigen**

```bash
[RO] df -h "<PFAD>"
```

**Datenträger und Volumes anzeigen**

```bash
[RO] diskutil list
```

**Informationen über ein Volume oder Gerät anzeigen**

```bash
[RO] diskutil info "<VOLUME-ODER-GERÄT>"
```

Beispiele:

```bash
[RO] diskutil info /
```

```bash
[RO] diskutil info disk3
```

**APFS-Container und Volumes anzeigen**

```bash
[RO] diskutil apfs list
```

**Lokale Time-Machine-Snapshots anzeigen**

```bash
[RO] tmutil listlocalsnapshots /
```

**Größe eines Verzeichnisses ermitteln**

```bash
[TEST][FILE] du -sh "<PFAD>"
```

**Direkte Unterverzeichnisse nach Größe sortieren**

```bash
[TEST][FILE][PRIV][SENS] sudo du -xhd 1 "<PFAD>" | sort -h
```

**Besonderheit bei APFS**

Mehrere APFS-Volumes können sich den freien Speicherplatz eines gemeinsamen Containers teilen. Deshalb darf die Belegung einzelner APFS-Volumes nicht wie bei vollständig getrennten Partitionen addiert werden.

Zusätzlich können für APFS-Volumes eingerichtet sein:

- Eine reservierte Mindestgröße
- Eine maximale Quote
- Gemeinsam verwendbarer Containerspeicher
- Snapshots
- Verschlüsselte und gegebenenfalls gesperrte Volumes

**Typische macOS-Ursachen**

- Lokale Time-Machine-Snapshots
- Große Benutzerbibliotheken
- Caches und Protokolldateien
- iPhone- oder iPad-Sicherungen
- Virtuelle Maschinen
- Entwicklerwerkzeuge und Simulatoren
- APFS-Container ohne ausreichend freien Gesamtspeicher
- Volume-Quoten
- Nicht eingehängte oder gesperrte verschlüsselte Volumes

</details>

<details>
<summary><strong>6. Inode-Erschöpfung unter Linux erkennen</strong></summary>

Linux-Dateisysteme verwenden Inodes zur Verwaltung von Dateien und Verzeichnissen. Ein Dateisystem kann noch freien Speicherplatz besitzen und trotzdem keine neuen Dateien mehr anlegen, wenn keine freien Inodes verfügbar sind.

**Inode-Belegung prüfen**

```bash
[RO] df -i
```

Beispielhafte Interpretation:

| Speicherplatz | Inodes | Bedeutung |
|---|---|---|
| 100 % belegt | Frei | Kapazitätsproblem |
| Frei | 100 % belegt | Zu viele Dateien beziehungsweise Inode-Problem |
| 100 % belegt | 100 % belegt | Kapazität und Inodes ausgeschöpft |
| Frei | Frei | Andere Ursache untersuchen |

**Typische Verursacher einer Inode-Erschöpfung**

- Millionen kleiner Sitzungsdateien
- Mail-Warteschlangen
- Cache-Verzeichnisse
- Temporäre Dateien
- Fehlkonfigurierte Anwendungen
- Container-Layer
- Sehr viele kleine Protokolldateien
- Nicht bereinigte Upload- oder Spool-Verzeichnisse

**Anzahl der Einträge unter einem begrenzten Pfad ermitteln**

```bash
[TEST][FILE][SENS] find "<PFAD>" -xdev -printf '.' | wc -c
```

> Das Durchsuchen sehr großer Verzeichnisbäume kann erhebliche Last verursachen. Der Befehl sollte nicht unkontrolliert auf dem gesamten Root-Dateisystem ausgeführt werden.

Auf Windows mit NTFS und macOS mit APFS wird eine klassische Inode-Erschöpfung normalerweise nicht auf dieselbe Weise diagnostiziert. Dort stehen Kapazität, Quoten, Dateisystemmetadaten und Containergrenzen im Vordergrund.

</details>

<details>
<summary><strong>7. Gelöschte, aber noch geöffnete Dateien untersuchen</strong></summary>

Unter Linux und macOS kann ein Prozess eine Datei weiterhin geöffnet halten, nachdem sie aus dem Verzeichnis gelöscht wurde. Der Dateiname ist dann nicht mehr sichtbar, die Datenblöcke bleiben aber belegt, bis der Prozess die Datei schließt.

Das kommt häufig bei Protokolldateien vor:

1. Eine große Protokolldatei wird gelöscht.
2. Der Dienst schreibt weiterhin in den offenen Dateideskriptor.
3. `du` findet die Datei nicht mehr.
4. `df` zeigt weiterhin den belegten Speicher.
5. Erst nach dem Schließen der Datei wird der Platz freigegeben.

**Linux und macOS**

```bash
[RO][PRIV][SENS] sudo lsof +L1
```

Wichtige Spalten:

| Spalte | Bedeutung |
|---|---|
| `COMMAND` | Prozessname |
| `PID` | Prozess-ID |
| `USER` | Prozessbenutzer |
| `FD` | Dateideskriptor |
| `SIZE/OFF` | Größe beziehungsweise Dateiposition |
| `NAME` | Dateiname, häufig mit Hinweis auf Löschung |

**Sinnvolle Reaktion**

- Zugehörigen Dienst identifizieren.
- Prüfen, ob eine reguläre Protokollrotation vorgesehen ist.
- Dienst nicht unkontrolliert beenden.
- Einen möglichen Neustart im Wartungsfenster planen.
- Ursache der fehlerhaften Rotation korrigieren.

> Einen Prozess nur zum Freigeben von Speicher zu beenden, kann einen Dienstausfall oder Datenverlust verursachen. Zuerst müssen Dienst, Kritikalität und Abhängigkeiten geprüft werden.

Unter Windows werden geöffnete Dateien anders behandelt. Eine regulär geöffnete Datei kann dort häufig nicht ohne Weiteres gelöscht werden. Zur Analyse können beispielsweise Ressourcenmonitor, Process Explorer oder anwendungsspezifische Werkzeuge verwendet werden.

</details>

<details>
<summary><strong>8. Schreibgeschützte und falsch eingehängte Dateisysteme erkennen</strong></summary>

Ein Dateisystem kann vorhanden und lesbar sein, Schreibzugriffe aber verweigern. Linux kann ein fehlerhaftes Dateisystem abhängig von Konfiguration und Fehlertyp schreibgeschützt erneut einhängen.

**Linux: Mount-Optionen eines Pfades prüfen**

```bash
[RO] findmnt -no TARGET,SOURCE,FSTYPE,OPTIONS --target "<PFAD>"
```

In der Ausgabe bedeuten:

| Option | Bedeutung |
|---|---|
| `rw` | Lesen und Schreiben |
| `ro` | Nur Lesen |
| `noexec` | Ausführung von Programmen nicht erlaubt |
| `nosuid` | SUID- und SGID-Bits werden nicht berücksichtigt |
| `nodev` | Gerätedateien werden nicht interpretiert |

**Linux: Kernelmeldungen prüfen**

```bash
[RO][PRIV][SENS] sudo journalctl -k -b -p warning --no-pager
```

Gezielt nach speicherbezogenen Meldungen suchen:

```bash
[RO][PRIV][SENS] sudo journalctl -k -b --no-pager |
    grep -Ei 'I/O error|filesystem|read-only|corrupt|ext4|xfs|btrfs|nvme|ata|scsi'
```

**macOS: Eingehängte Dateisysteme anzeigen**

```bash
[RO] mount
```

**macOS: Volume-Informationen anzeigen**

```bash
[RO] diskutil info "<VOLUME-ODER-GERÄT>"
```

**Windows: Volumezustand anzeigen**

```powershell
[RO] Get-Volume |
    Select-Object DriveLetter, FileSystemLabel,
        HealthStatus, OperationalStatus
```

**Wichtige Unterscheidung**

Ein Schreibfehler kann verursacht werden durch:

- Fehlende Dateiberechtigung
- Ausgeschöpfte Quote
- Volles Dateisystem
- Schreibgeschütztes Dateisystem
- Schreibgeschütztes Speichermedium
- Gesperrtes oder verschlüsseltes Volume
- Fehlendes Netzlaufwerk
- Dateisystem- oder Hardwarefehler

Ein Berechtigungsfehler sollte deshalb nicht automatisch durch das Erteilen weitreichender Rechte „behoben“ werden.

</details>

<details>
<summary><strong>9. Snapshots, Schattenkopien und gemeinsam genutzten Speicher prüfen</strong></summary>

Snapshots können Speicherplatz belegen, obwohl die sichtbaren Dateien wenig Platz benötigen. Beim Ändern oder Löschen von Dateien müssen ältere Datenblöcke möglicherweise für den Snapshot erhalten bleiben.

**Windows: Schattenkopien anzeigen**

```cmd
[RO][PRIV] vssadmin list shadows
```

**Windows: Schattenkopiespeicher anzeigen**

```cmd
[RO][PRIV] vssadmin list shadowstorage
```

**macOS: lokale Time-Machine-Snapshots anzeigen**

```bash
[RO] tmutil listlocalsnapshots /
```

**macOS: APFS-Struktur anzeigen**

```bash
[RO] diskutil apfs list
```

**Linux**

Abhängig von der Speichertechnik kommen unterschiedliche Werkzeuge zum Einsatz:

| Technik | Typische Prüfung |
|---|---|
| LVM | `[RO][PRIV] sudo lvs` |
| Btrfs | `[RO][PRIV] sudo btrfs filesystem usage "<PFAD>"` |
| ZFS | `[RO] zfs list` |
| ZFS-Snapshots | `[RO] zfs list -t snapshot` |

> Diese Werkzeuge stehen nur zur Verfügung, wenn die jeweilige Speichertechnik installiert und verwendet wird.

Snapshots dürfen nicht allein aufgrund ihres Alters gelöscht werden. Vorher ist zu prüfen:

- Wer oder welches System hat den Snapshot erstellt?
- Wird er von einer Sicherungslösung benötigt?
- Gibt es gesetzliche oder betriebliche Aufbewahrungsfristen?
- Kann eine Replikation oder Wiederherstellung davon abhängen?
- Welcher Speicherplatz würde tatsächlich freigegeben?
- Existiert eine funktionierende Sicherung?

</details>

<details>
<summary><strong>10. Dateisystemzustand unter Windows prüfen</strong></summary>

**Onlineprüfung mit CHKDSK**

```cmd
[TEST][PRIV] chkdsk <LAUFWERK>: /scan
```

Beispiel:

```cmd
[TEST][PRIV] chkdsk C: /scan
```

**Onlineprüfung mit PowerShell**

```powershell
[TEST][PRIV] Repair-Volume -DriveLetter <BUCHSTABE> -Scan
```

Beispiel:

```powershell
[TEST][PRIV] Repair-Volume -DriveLetter D -Scan
```

**NTFS-Selbstreparaturstatus abfragen**

```cmd
[RO][PRIV] fsutil repair query <LAUFWERK>:
```

**Systemprotokoll nach Speichermeldungen durchsuchen**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = 'System'
    StartTime = (Get-Date).AddHours(-24)
} |
Where-Object {
    $_.ProviderName -match 'Disk|Ntfs|volmgr|volsnap|storport'
} |
Select-Object TimeCreated, LevelDisplayName, ProviderName, Id, Message
```

Die tatsächlich verwendeten Anbieter können je nach Windows-Version, Treiber und Speicherhardware abweichen.

**Reparaturbefehle nur geplant einsetzen**

```cmd
[CHANGE][DISRUPT][PRIV] chkdsk <LAUFWERK>: /f
```

```powershell
[CHANGE][DISRUPT][PRIV] Repair-Volume -DriveLetter <BUCHSTABE> -OfflineScanAndFix
```

Diese Befehle können:

- Ein Volume sperren oder aushängen
- Einen Neustart erforderlich machen
- Dienste unterbrechen
- Beschädigte Dateisystemstrukturen verändern
- Bei schwerwiegenden Schäden Dateien oder Dateifragmente verlieren

Vor einer Reparatur müssen Sicherung, Wartungsfenster, betroffene Dienste und Wiederherstellungsweg geklärt sein.

</details>

<details>
<summary><strong>11. Dateisystemzustand unter Linux prüfen</strong></summary>

Zuerst muss der Dateisystemtyp bestimmt werden:

```bash
[RO] findmnt -no SOURCE,FSTYPE,TARGET --target "<PFAD>"
```

oder:

```bash
[RO] lsblk -f
```

**Kernelmeldungen untersuchen**

```bash
[RO][PRIV][SENS] sudo journalctl -k -b -p warning --no-pager
```

**Anzeigen, welchen Prüfbefehl fsck verwenden würde**

```bash
[RO][PRIV] sudo fsck -N "<GERÄT>"
```

Beispiel:

```bash
[RO][PRIV] sudo fsck -N /dev/sdb1
```

`-N` zeigt an, welche Aktion vorgesehen wäre, ohne die Dateisystemprüfung auszuführen.

**Wichtige Sicherheitsregel**

Eine tatsächliche Dateisystemreparatur darf nicht unkontrolliert auf einem eingehängten Produktivdateisystem durchgeführt werden.

```bash
[CHANGE][DISRUPT][PRIV] sudo fsck "<GERÄT>"
```

Vorher müssen mindestens geklärt sein:

- Welcher Dateisystemtyp wird verwendet?
- Ist das Dateisystem ausgehängt?
- Existiert eine aktuelle Sicherung?
- Ist ein Wartungsfenster vorhanden?
- Handelt es sich um das Root-Dateisystem?
- Muss ein Rettungs- oder Wiederherstellungssystem verwendet werden?
- Gibt es herstellerspezifische Werkzeuge?

> Bei XFS, Btrfs, ZFS und anderen Dateisystemen gelten eigene Prüf- und Reparaturverfahren. Ein generisches `fsck` ist nicht für jedes Dateisystem die richtige Reparaturmethode.

</details>

<details>
<summary><strong>12. Dateisystemzustand unter macOS prüfen</strong></summary>

**Volume überprüfen**

```bash
[TEST][PRIV] sudo diskutil verifyVolume "<VOLUME>"
```

Beispiel:

```bash
[TEST][PRIV] sudo diskutil verifyVolume /
```

**Physisches Gerät und Volume-Struktur anzeigen**

```bash
[RO] diskutil list
```

```bash
[RO] diskutil info "<VOLUME-ODER-GERÄT>"
```

**Reparatur eines Volumes**

```bash
[CHANGE][DISRUPT][PRIV] sudo diskutil repairVolume "<VOLUME>"
```

Eine Reparatur des Startvolumes sollte nicht unkontrolliert im laufenden Produktivbetrieb erfolgen. Apple empfiehlt für die Prüfung und Reparatur des Startdatenträgers die macOS-Wiederherstellung und das Festplattendienstprogramm.

Vorher sind erforderlich:

- Aktuelle Sicherung
- Prüfung des betroffenen Volumes
- Geplantes Wartungsfenster
- Möglichkeit zum Start in die macOS-Wiederherstellung
- Wiederherstellungs- oder Austauschplan für den Datenträger

Das Festplattendienstprogramm kann nicht alle Hardware- oder Dateisystemprobleme erkennen beziehungsweise reparieren. Wiederkehrende Fehler können auf einen ausfallenden Datenträger hinweisen.

</details>

<details>
<summary><strong>13. Datenträger- und Ein-/Ausgabefehler erkennen</strong></summary>

Ein volles Dateisystem und ein defekter Datenträger sind unterschiedliche Fehlerklassen. Meldungen wie `I/O error`, Zeitüberschreitungen, Zurücksetzungen eines Controllers oder wiederholte Dateisystembeschädigungen weisen auf eine tiefere Speicherstörung hin.

**Windows**

```powershell
[RO] Get-Disk |
    Select-Object Number, FriendlyName, OperationalStatus,
        HealthStatus, Size
```

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = 'System'
    StartTime = (Get-Date).AddHours(-24)
} |
Where-Object {
    $_.ProviderName -match 'Disk|Ntfs|storport|stornvme|volmgr'
} |
Select-Object TimeCreated, LevelDisplayName, ProviderName, Id, Message
```

**Linux**

```bash
[RO][PRIV][SENS] sudo journalctl -k -b --no-pager |
    grep -Ei 'I/O error|timeout|reset|corrupt|nvme|ata|scsi|blk_update'
```

Falls `smartmontools` installiert ist und das Gerät SMART-Daten bereitstellt:

```bash
[RO][PRIV][SENS] sudo smartctl -a "<GERÄT>"
```

**macOS**

```bash
[RO] diskutil info "<GERÄT>"
```

Je nach Datenträger und Anschluss kann ein SMART-Status angezeigt werden. Externe USB-Gehäuse und Speicheradapter geben SMART-Daten nicht immer an das Betriebssystem weiter.

**Hinweise auf einen möglichen Hardwarefehler**

- Wiederkehrende Ein-/Ausgabefehler
- Zunehmende Lesefehler
- Controller- oder Bus-Zeitüberschreitungen
- Datenträger verschwindet zeitweise
- Dateisystem wird wiederholt schreibgeschützt
- Reparaturen werden nach kurzer Zeit erneut erforderlich
- RAID meldet einen herabgesetzten Zustand
- Herstellerdiagnose meldet Warnungen
- Ungewöhnlich hohe Latenzen bei geringer Last

> Bei Verdacht auf einen ausfallenden Datenträger hat die Sicherung beziehungsweise kontrollierte Datenrettung Vorrang vor wiederholten Reparaturversuchen.

</details>

<details>
<summary><strong>14. Abweichung zwischen df, du und sichtbaren Dateien erklären</strong></summary>

Unter Linux und macOS können verschiedene Werkzeuge unterschiedliche Werte anzeigen.

| Werkzeug | Misst hauptsächlich |
|---|---|
| `df` | Belegte und freie Blöcke des Dateisystems |
| `du` | Über Verzeichniseinträge erreichbare Dateien |
| `lsof +L1` | Gelöschte, aber weiterhin geöffnete Dateien |
| Snapshot-Werkzeug | Durch Snapshots erhaltene Daten |
| Quota-Werkzeug | Benutzer- oder Gruppenverbrauch |
| Storage-Plattform | Physische oder bereitgestellte Speicherkapazität |

**Mögliche Ursachen für unterschiedliche Werte**

- Gelöschte, aber geöffnete Dateien
- Snapshots
- Reservierte Dateisystemblöcke
- Sparse-Dateien
- Mountpoints, unter denen Dateien verborgen liegen
- Berechtigungsfehler bei `du`
- Netzlaufwerke oder weitere Dateisysteme
- Kompression oder Deduplizierung
- Thin Provisioning
- Dateisystemmetadaten

**Verdeckte Dateien unter einem Mountpoint**

Wenn Dateien in einem Verzeichnis liegen und anschließend ein anderes Dateisystem auf dieses Verzeichnis eingehängt wird, sind die ursprünglichen Dateien weiterhin vorhanden, aber im normalen Verzeichnisbaum nicht sichtbar.

Zur Untersuchung muss der Mountpoint kontrolliert und das darunterliegende Dateisystem in einem geplanten Wartungsfenster separat betrachtet werden. Ein Produktivvolume darf nicht allein zu Diagnosezwecken unkontrolliert ausgehängt werden.

</details>

<details>
<summary><strong>15. Typische Fehlinterpretationen vermeiden</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „Es sind noch 5 GB frei, also ist alles in Ordnung.“ | Freier Platz muss relativ zu Wachstum, Anwendung und Dateisystemgröße bewertet werden. |
| „Die Datei wurde gelöscht, also ist der Platz frei.“ | Ein Prozess oder Snapshot kann die Daten weiterhin festhalten. |
| „Das Volume ist erreichbar, also ist es beschreibbar.“ | Mount-Optionen, Quoten und Berechtigungen prüfen. |
| „No space left bedeutet immer, dass die Festplatte voll ist.“ | Unter Linux können auch Inodes erschöpft sein. |
| „CHKDSK oder fsck kann gefahrlos ausgeführt werden.“ | Reparaturen verändern Strukturen und können den Betrieb unterbrechen. |
| „SMART ist unauffällig, also ist der Datenträger fehlerfrei.“ | Nicht alle Fehler werden erkannt oder weitergereicht. |
| „Der Gastserver zeigt freien Platz, also ist der Speicher verfügbar.“ | Datastore oder Storage-Pool kann trotzdem voll sein. |
| „Alle großen Dateien können gelöscht werden.“ | Eigentümer, Zweck, Sicherung und Aufbewahrung müssen geklärt werden. |
| „Mehr Rechte lösen den Schreibfehler.“ | Ursache kann Quote, Read-only-Zustand oder Dateisystemfehler sein. |
| „Eine Reparatur ersetzt die Datensicherung.“ | Reparatur und Sicherung verfolgen unterschiedliche Ziele. |

</details>

<details>
<summary><strong>16. Sichere Reihenfolge der Fehleranalyse</strong></summary>

1. Originale Fehlermeldung und betroffenen Pfad dokumentieren.
2. Zugehöriges Volume beziehungsweise Dateisystem bestimmen.
3. Freien Speicherplatz und prozentuale Belegung prüfen.
4. Unter Linux zusätzlich die Inode-Belegung prüfen.
5. Benutzer- und Dateisystemquoten kontrollieren.
6. Mount-, Volume- und Schreibzustand untersuchen.
7. Wachstum nach Verzeichnis, Anwendung und Zeitpunkt eingrenzen.
8. Snapshots und Schattenkopien berücksichtigen.
9. Nach gelöschten, aber geöffneten Dateien suchen.
10. System- und Kernelprotokolle auf Ein-/Ausgabefehler prüfen.
11. Speicherhardware, RAID, Hypervisor oder SAN/NAS einbeziehen.
12. Erst danach über Bereinigung, Erweiterung oder Reparatur entscheiden.
13. Änderungen nur nach Sicherung, Freigabe und dokumentiertem Rückweg durchführen.
14. Nach der Maßnahme Dienstfunktion und freien Speicher erneut prüfen.

**Grundsatz für Bereinigungen**

Vor dem Löschen einer Datei müssen folgende Fragen beantwortet sein:

- Wem gehört die Datei?
- Welche Anwendung verwendet sie?
- Gibt es eine Aufbewahrungsfrist?
- Existiert eine Sicherung?
- Wird sie von einem Snapshot oder einer Replikation benötigt?
- Kann die Anwendung sie selbst bereinigen?
- Muss stattdessen die Protokollrotation korrigiert werden?
- Welche Auswirkung hat das Löschen auf Wiederherstellung und Nachvollziehbarkeit?

</details>

<details>
<summary><strong>17. Schnelle Befehlsübersicht</strong></summary>

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Volume-Belegung | `[RO] Get-Volume` | `[RO] df -hT` | `[RO] df -h` |
| Datenträger anzeigen | `[RO] Get-Disk` | `[RO] lsblk -f` | `[RO] diskutil list` |
| Partitionen anzeigen | `[RO] Get-Partition` | `[RO] lsblk` | `[RO] diskutil list` |
| Dateisystem eines Pfades | Volume anhand Laufwerksbuchstaben prüfen | `[RO] findmnt --target "<PFAD>"` | `[RO] df -h "<PFAD>"` |
| Mount-Optionen | Nicht direkt vergleichbar | `[RO] findmnt -no TARGET,SOURCE,FSTYPE,OPTIONS --target "<PFAD>"` | `[RO] mount` |
| Verzeichnisgröße | `[TEST][FILE] Get-ChildItem ...` | `[TEST][FILE] du -sh "<PFAD>"` | `[TEST][FILE] du -sh "<PFAD>"` |
| Inode-Belegung | Nicht vergleichbar | `[RO] df -i` | Nicht üblicherweise erforderlich |
| Benutzerquote | `[RO][PRIV] fsutil quota query <LAUFWERK>:` | `[RO] quota -s` | APFS-Quote mit `diskutil apfs list` prüfen |
| Dirty-Bit | `[RO][PRIV] fsutil dirty query <LAUFWERK>:` | Nicht direkt vergleichbar | Nicht direkt vergleichbar |
| Gelöschte offene Dateien | Spezielle Prozesswerkzeuge | `[RO][PRIV] sudo lsof +L1` | `[RO][PRIV] sudo lsof +L1` |
| Snapshots | `[RO][PRIV] vssadmin list shadows` | Abhängig von LVM, Btrfs oder ZFS | `[RO] tmutil listlocalsnapshots /` |
| Dateisystemprüfung | `[TEST][PRIV] chkdsk <LAUFWERK>: /scan` | Dateisystemspezifisch; nicht auf gemountetem Produktivsystem | `[TEST][PRIV] sudo diskutil verifyVolume "<VOLUME>"` |
| Systemmeldungen | `[RO] Get-WinEvent` | `[RO][PRIV] sudo journalctl -k` | Systemprotokoll und `diskutil` |
| Hardwarezustand | `[RO] Get-Disk` | `[RO][PRIV] sudo smartctl -a "<GERÄT>"` | `[RO] diskutil info "<GERÄT>"` |

</details>

<details>
<summary><strong>18. Entscheidungsmatrix</strong></summary>

| Befund | Wahrscheinliche Ursache | Nächster Schritt |
|---|---|---|
| Volume nahezu 100 % belegt | Kapazitätsproblem | Größte Verbraucher und Wachstum ermitteln |
| Speicher frei, Inodes 100 % | Zu viele Dateien | Verursachendes Verzeichnis und Anwendung ermitteln |
| Speicher frei, Benutzer kann nicht schreiben | Quote oder Berechtigung | Quote, Besitz und ACL prüfen |
| `df` hoch, `du` deutlich niedriger | Offene gelöschte Datei oder Snapshot | `lsof +L1` und Snapshots prüfen |
| Volume nur lesbar | Dateisystem- oder Hardwarefehler | Protokolle sichern und Wartung planen |
| Volume nach Neustart nicht vorhanden | Mount-, Geräte- oder Konfigurationsfehler | Geräteerkennung und Mount-Konfiguration prüfen |
| Wiederkehrende I/O-Fehler | Hardware, Controller oder Speicherpfad | Sicherung und Storage-Eskalation |
| Gast hat Platz, Datastore ist voll | Thin Provisioning oder Snapshot-Wachstum | Hypervisor und Speicherplattform prüfen |
| Speicher wird schnell erneut voll | Ursache nicht behoben | Wachstum messen und Rotation beziehungsweise Retention korrigieren |
| Reparatur findet wiederholt Fehler | Datenträger- oder tiefer Dateisystemschaden | Daten sichern und Austausch bewerten |

</details>

<details>
<summary><strong>19. Dokumentationsvorlage</strong></summary>

```text
Ticket:
Datum und Uhrzeit:
Bearbeiter:

Betroffenes System:
Betroffener Dienst:
Betroffener Benutzer:
Betroffener Pfad:
Volume beziehungsweise Dateisystem:
Dateisystemtyp:
Lokaler, virtueller oder externer Speicher:

Originale Fehlermeldung:

Gesamtkapazität:
Freier Speicher:
Belegung in Prozent:
Inode-Belegung:
Quota-Status:
Mount- beziehungsweise Volume-Status:
Schreibgeschützt:
Snapshots vorhanden:
Gelöschte offene Dateien:
Auffällige große Verzeichnisse oder Dateien:

Betriebssystemmeldungen:
Dateisystemmeldungen:
Hardware- oder Controllerfehler:
RAID-, SAN-, NAS- oder Datastore-Status:

Vermutete Ursache:
Durchgeführte Tests:
Durchgeführte Änderungen:
Sicherung geprüft:
Wartungsfenster:
Rückfallplan:

Ergebnis:
Funktionsprüfung:
Verbleibender freier Speicher:
Weiterführende Maßnahmen:
```

</details>

---

**Merksatz**

> „Datenträger voll“ ist keine vollständige Diagnose. Ein Systemintegrator prüft Kapazität, Inodes, Quoten, Mountzustand, Snapshots, offene Dateien, Dateisystem und Speicherhardware getrennt – und repariert erst nach Sicherung und klarer Ursachenanalyse.

**Quellen und weiterführende Dokumentation**

- [Microsoft Learn – Get-Volume](https://learn.microsoft.com/powershell/module/storage/get-volume)
- [Microsoft Learn – Get-Partition](https://learn.microsoft.com/powershell/module/storage/get-partition)
- [Microsoft Learn – Repair-Volume](https://learn.microsoft.com/powershell/module/storage/repair-volume)
- [Microsoft Learn – chkdsk](https://learn.microsoft.com/windows-server/administration/windows-commands/chkdsk)
- [Microsoft Learn – fsutil quota](https://learn.microsoft.com/windows-server/administration/windows-commands/fsutil-quota)
- [Microsoft Learn – fsutil repair](https://learn.microsoft.com/windows-server/administration/windows-commands/fsutil-repair)
- [Linux-Handbuch – df](https://man7.org/linux/man-pages/man1/df.1.html)
- [Linux-Handbuch – findmnt](https://man7.org/linux/man-pages/man8/findmnt.8.html)
- [Linux-Handbuch – lsblk](https://man7.org/linux/man-pages/man8/lsblk.8.html)
- [Linux-Handbuch – mount](https://man7.org/linux/man-pages/man8/mount.8.html)
- [Linux-Handbuch – fsck](https://man7.org/linux/man-pages/man8/fsck.8.html)
- [Linux-Handbuch – lsof](https://man7.org/linux/man-pages/man8/lsof.8.html)
- [Apple – Speichermedium mit dem Festplattendienstprogramm reparieren](https://support.apple.com/de-de/guide/disk-utility/-dskutl1040/mac)
- [Apple – APFS-Volumes hinzufügen, löschen oder vergrößern](https://support.apple.com/en-asia/guide/disk-utility/dskua9e6a110/mac)
- [Apple-Handbuch – diskutil](https://keith.github.io/xcode-man-pages/diskutil.8.html)

# 4.12 Zeit-, Zeitzonen- und Synchronisationsfehler

Eine falsche Systemzeit kann Fehler verursachen, die zunächst wie Netzwerk-, Zertifikats-, Anmelde- oder Anwendungsprobleme wirken. Besonders in Active-Directory-Umgebungen, verteilten Systemen, Datenbanken, Clustern und virtualisierten Umgebungen ist eine zuverlässige Zeitsynchronisation entscheidend.

Typische Auswirkungen sind:

- Domänenanmeldungen schlagen fehl.
- Kerberos-Tickets werden abgelehnt.
- Zertifikate erscheinen noch nicht oder nicht mehr gültig.
- HTTPS- und TLS-Verbindungen schlagen fehl.
- Protokolle verschiedener Systeme lassen sich nicht zeitlich zuordnen.
- Datenbanken speichern Ereignisse in falscher Reihenfolge.
- Geplante Aufgaben starten zu früh, zu spät oder gar nicht.
- Sicherungen und Synchronisationsaufgaben verhalten sich unerwartet.
- Einmalpasswörter und zeitbasierte Mehrfaktor-Authentifizierung schlagen fehl.
- Cluster, Replikationen oder verteilte Anwendungen melden Inkonsistenzen.
- Dateien besitzen scheinbar zukünftige oder unlogische Zeitstempel.
- Nach einem Neustart springt die Uhrzeit erneut auf einen falschen Wert.

> **Wichtig:** Datum, Uhrzeit, Zeitzone und Zeitsynchronisation sind unterschiedliche Prüfbereiche. Eine korrekt aussehende Uhrzeit bedeutet nicht automatisch, dass das System korrekt synchronisiert ist.

**Kennzeichnung der Befehle**

| Kennzeichnung | Bedeutung |
|---|---|
| `[RO]` | Nur lesender Befehl |
| `[TEST]` | Führt eine aktive Prüfung aus |
| `[PRIV]` | Erhöhte Berechtigungen erforderlich |
| `[SENS]` | Ausgabe kann sensible Informationen enthalten |
| `[CHANGE]` | Verändert Konfiguration oder Systemzustand |
| `[DISRUPT]` | Kann laufende Dienste oder Anwendungen beeinflussen |

---

<details>
<summary><strong>1. Warum eine korrekte Systemzeit wichtig ist</strong></summary>

Viele IT-Systeme verwenden Zeitstempel nicht nur zur Anzeige, sondern als Bestandteil ihrer Sicherheits- und Ablaufsteuerung.

| System oder Funktion | Bedeutung der Systemzeit |
|---|---|
| Active Directory | Kerberos verwendet Zeitstempel zum Schutz vor wiederholten Anmeldeversuchen |
| TLS und Zertifikate | Gültigkeitsbeginn und Gültigkeitsende werden gegen die Systemzeit geprüft |
| Protokollierung | Ereignisse verschiedener Systeme müssen zeitlich vergleichbar sein |
| Datenbanken | Transaktionen, Replikation und Datensätze besitzen Zeitstempel |
| Sicherungen | Zeitpläne und inkrementelle Sicherungen hängen von Zeitinformationen ab |
| MFA und TOTP | Einmalpasswörter werden aus Zeitintervallen berechnet |
| E-Mail | Nachrichten und Signaturen enthalten Zeitstempel |
| Monitoring | Messwerte müssen in der richtigen Reihenfolge gespeichert werden |
| Cluster | Knoten müssen Ereignisse zeitlich konsistent bewerten |
| Dateisynchronisation | Änderungszeiten beeinflussen die Entscheidung, welche Datei neuer ist |
| Lizenzsysteme | Lizenzen können an Zeiträume gebunden sein |
| Aufgabenplanung | Startzeitpunkte hängen von lokaler Zeit und Zeitzone ab |

Eine Zeitabweichung kann daher gleichzeitig mehrere scheinbar unabhängige Dienste beeinträchtigen.

</details>

<details>
<summary><strong>2. Fehlerbild strukturiert aufnehmen</strong></summary>

Zuerst muss festgestellt werden, welche Zeitinformation tatsächlich falsch ist.

**Zu prüfende Fragen**

- Sind Datum und Uhrzeit falsch?
- Ist nur die Zeitzone falsch?
- Beträgt die Abweichung genau eine oder mehrere volle Stunden?
- Wächst die Abweichung kontinuierlich?
- Springt die Zeit nach einem Neustart zurück?
- Ist nur eine virtuelle Maschine betroffen?
- Sind mehrere Geräte am gleichen Standort betroffen?
- Ist die UTC-Zeit korrekt, aber die lokale Anzeige falsch?
- Ist der eingetragene Zeitserver erreichbar?
- Wird die erwartete Zeitquelle tatsächlich verwendet?
- Trat das Problem nach einem Snapshot, einer Migration oder einem Standby auf?
- Ist das System Mitglied einer Active-Directory-Domäne?
- Verwaltet eine Gruppenrichtlinie oder Geräteverwaltung die Zeiteinstellungen?
- Wurde die Zeit manuell verändert?

**Abweichungsmuster und erste Hinweise**

| Beobachtung | Mögliche Ursache |
|---|---|
| Abweichung um genau eine Stunde | Falsche Zeitzone oder Sommerzeitregel |
| Abweichung um mehrere volle Stunden | Falsche Zeitzone |
| Abweichung wächst langsam | Ungenaue lokale Uhr oder fehlende Synchronisation |
| Zeit springt nach einem Neustart zurück | Hardwareuhr, Firmware, Host oder leere CMOS-Batterie |
| Nur virtuelle Maschinen betroffen | Hypervisor-Zeitquelle oder Snapshot |
| Alle Domänenmitglieder betroffen | Fehler in der AD-Zeithierarchie |
| Nur ein Domänenmitglied betroffen | Lokaler Zeitdienst, Netzwerk oder Richtlinie |
| Uhrzeit stimmt, TLS schlägt trotzdem fehl | UTC, Datum und Zertifikatszeitraum kontrollieren |
| Protokolle wirken zeitversetzt | UTC- und Lokalzeitdarstellung vergleichen |
| Zeitserver ist per Ping erreichbar, Synchronisation scheitert | NTP, Firewall oder Serverantwort prüfen |

> Eine Abweichung um eine volle Stunde deutet meistens eher auf die Zeitzone als auf eine fehlerhafte NTP-Synchronisation hin.

</details>

<details>
<summary><strong>3. Datum, Uhrzeit und Zeitzone vergleichen</strong></summary>

Die Werte sollten möglichst gleichzeitig auf dem betroffenen System und einem vertrauenswürdigen Vergleichssystem erfasst werden.

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Lokale Zeit | `[RO] Get-Date -Format o` | `[RO] date --iso-8601=seconds` | `[RO] date "+%Y-%m-%dT%H:%M:%S%z"` |
| UTC-Zeit | `[RO] (Get-Date).ToUniversalTime().ToString("o")` | `[RO] date -u "+%Y-%m-%dT%H:%M:%SZ"` | `[RO] date -u "+%Y-%m-%dT%H:%M:%SZ"` |
| Zeitzone | `[RO] Get-TimeZone` | `[RO] timedatectl status` | `[RO][PRIV] sudo systemsetup -gettimezone` |
| Zeitzonendatei | Nicht zutreffend | `[RO] readlink -f /etc/localtime` | Nicht zutreffend |
| Hardwareuhr | Nicht direkt erforderlich | `[RO][PRIV] sudo hwclock --show` | Nicht regulär erforderlich |

**Warum UTC und lokale Zeit getrennt geprüft werden**

- UTC ist die gemeinsame Zeitbasis.
- Die lokale Zeit entsteht aus UTC, Zeitzone und Sommerzeitregel.
- Zwei Systeme können dieselbe UTC-Zeit, aber unterschiedliche lokale Zeiten anzeigen.
- Protokolle können entweder UTC oder lokale Zeit verwenden.
- Server werden häufig in UTC betrieben, während Benutzeroberflächen lokale Zeit anzeigen.

**Beispiel**

Wenn UTC korrekt ist, die lokale Zeit aber um eine Stunde abweicht, liegt die Ursache wahrscheinlich in der Zeitzone oder Sommerzeitregel und nicht in der eigentlichen Zeitsynchronisation.

</details>

<details>
<summary><strong>4. Windows-Zeitdienst untersuchen</strong></summary>

Windows verwendet den Dienst `W32Time` zur Zeitsynchronisation.

**Status des Zeitdienstes prüfen**

```powershell
[RO] Get-Service -Name W32Time
```

Ausführlicher:

```powershell
[RO] Get-CimInstance Win32_Service -Filter "Name='W32Time'" |
    Select-Object Name, State, StartMode, StartName, ExitCode
```

**Aktuelle Zeitquelle anzeigen**

```cmd
[RO] w32tm /query /source
```

**Synchronisationsstatus anzeigen**

```cmd
[RO] w32tm /query /status
```

**Ausführlichen Status anzeigen**

```cmd
[RO] w32tm /query /status /verbose
```

**Konfiguration anzeigen**

```cmd
[RO][SENS] w32tm /query /configuration
```

**Konfigurierte Zeitpartner anzeigen**

```cmd
[RO][SENS] w32tm /query /peers
```

**Zeitzone anzeigen**

```powershell
[RO] Get-TimeZone
```

oder:

```cmd
[RO] tzutil /g
```

**Mögliche Ausgaben bei der Zeitquelle**

| Ausgabe | Bedeutung |
|---|---|
| Name eines Domänencontrollers | Synchronisation über die AD-Zeithierarchie |
| Name eines NTP-Servers | Direkte Synchronisation mit diesem Server |
| `Local CMOS Clock` | Lokale Hardwareuhr wird verwendet |
| `VM IC Time Synchronization Provider` | Zeit wird über den Hypervisor bereitgestellt |
| `Free-running System Clock` | Keine geeignete externe Synchronisation |

> `Local CMOS Clock` oder `Free-running System Clock` ist bei einem normalen Domänenmitglied meist ein Hinweis darauf, dass die erwartete Domänenzeitquelle nicht verwendet wird. Bei isolierten Systemen kann die Bewertung anders ausfallen.

</details>

<details>
<summary><strong>5. Windows-Zeitabweichung aktiv messen</strong></summary>

Mit `w32tm /stripchart` kann die Abweichung zu einem Zeitserver gemessen werden, ohne die lokale Uhr zu verändern.

```cmd
[TEST] w32tm /stripchart /computer:<ZEITSERVER> /samples:5 /dataonly
```

Beispiel:

```cmd
[TEST] w32tm /stripchart /computer:dc01.example.local /samples:5 /dataonly
```

Fortlaufende Messung:

```cmd
[TEST] w32tm /stripchart /computer:<ZEITSERVER> /dataonly
```

Die fortlaufende Ausgabe wird mit `Strg` + `C` beendet.

**Wichtige Interpretation**

| Ergebnis | Bedeutung |
|---|---|
| Kleine, stabile Abweichung | Synchronisation wahrscheinlich funktionsfähig |
| Große, stabile Abweichung | Falsche Quelle oder noch nicht korrigierte Uhr |
| Abweichung wächst | Lokale Uhr driftet oder wird nicht nachgeregelt |
| Keine Antwort | Name, Netzwerk, Firewall oder NTP-Dienst prüfen |
| Zeitüberschreitung | NTP-Antwort erreicht den Client nicht |

> Der Test bestätigt nicht automatisch, dass Windows diese Gegenstelle als aktive Zeitquelle verwendet. Die aktive Quelle muss zusätzlich mit `w32tm /query /source` geprüft werden.

</details>

<details>
<summary><strong>6. Active-Directory-Zeithierarchie verstehen</strong></summary>

Domänenmitglieder sollten grundsätzlich der Active-Directory-Zeithierarchie folgen.

Vereinfachter Aufbau:

```text
Externe zuverlässige Zeitquelle
              │
              ▼
PDC-Emulator der Gesamtstruktur-Stammdomäne
              │
              ▼
Weitere Domänencontroller
              │
              ▼
Mitgliedsserver und Clients
```

**PDC-Emulator ermitteln**

```cmd
[RO][SENS] netdom query fsmo
```

Alternativ mit PowerShell:

```powershell
[RO][SENS] Get-ADDomain |
    Select-Object DNSRoot, PDCEmulator
```

Dafür muss das ActiveDirectory-PowerShell-Modul verfügbar sein.

**Domänencontroller anzeigen**

```cmd
[RO][SENS] nltest /dclist:<DOMÄNE>
```

**Verwendeten Domänencontroller anzeigen**

```cmd
[RO][SENS] nltest /dsgetdc:<DOMÄNE>
```

**Zeitstatus eines entfernten Windows-Systems abfragen**

```cmd
[RO][SENS] w32tm /query /computer:<COMPUTER> /status
```

Dafür sind ausreichende Berechtigungen und eine erreichbare Remoteverwaltung erforderlich.

**Wichtige Regeln**

- Normale Domänenmitglieder sollten nicht unabhängig auf beliebige öffentliche NTP-Server zeigen.
- Der PDC-Emulator der Stammdomäne benötigt eine zuverlässige übergeordnete Zeitquelle.
- Gruppenrichtlinien können lokale Einstellungen überschreiben.
- Auf virtuellen Domänencontrollern dürfen Hypervisor- und Domänenzeitsynchronisation nicht unkontrolliert gegeneinander arbeiten.
- Eine manuelle Uhrzeitkorrektur behebt keine fehlerhafte Zeithierarchie.

</details>

<details>
<summary><strong>7. Windows-Ereignisprotokolle auswerten</strong></summary>

**Zeitdienst-Ereignisse im Systemprotokoll anzeigen**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName      = 'System'
    ProviderName = 'Microsoft-Windows-Time-Service'
    StartTime    = (Get-Date).AddHours(-24)
} |
Select-Object TimeCreated, LevelDisplayName, Id, Message
```

**Operational-Protokoll des Zeitdienstes prüfen**

```powershell
[RO][SENS] Get-WinEvent -LogName `
    'Microsoft-Windows-Time-Service/Operational' `
    -ErrorAction SilentlyContinue |
Select-Object -First 100 TimeCreated, LevelDisplayName, Id, Message
```

**Dienststatus und letzte Meldungen gemeinsam bewerten**

```powershell
[RO] Get-Service W32Time
```

```cmd
[RO] w32tm /query /source
```

```cmd
[RO] w32tm /query /status
```

**Typische Hinweise in Ereignissen**

- Keine Zeitdaten verfügbar
- Zeitquelle nicht erreichbar
- Zeitquelle wurde gewechselt
- Synchronisation wurde beendet
- Uhrzeitabweichung ist zu groß
- Zeitdienst wurde gestartet oder beendet
- NTP-Anbieter konnte keine gültigen Daten abrufen

> Einzelne ältere Warnungen beweisen keine aktuelle Störung. Zeitstempel, Wiederholungsrate und aktueller Synchronisationsstatus müssen gemeinsam bewertet werden.

</details>

<details>
<summary><strong>8. Linux mit systemd-timesyncd untersuchen</strong></summary>

Viele Linux-Distributionen verwenden `systemd-timesyncd`. Andere Systeme verwenden stattdessen chrony, ntpd oder eine herstellerspezifische Lösung.

**Gesamtstatus anzeigen**

```bash
[RO] timedatectl status
```

Wichtige Felder:

| Feld | Bedeutung |
|---|---|
| `Local time` | Lokale Uhrzeit |
| `Universal time` | UTC-Zeit |
| `RTC time` | Hardwareuhr |
| `Time zone` | Aktive Zeitzone |
| `System clock synchronized` | Synchronisationszustand |
| `NTP service` | Status eines erkannten NTP-Dienstes |
| `RTC in local TZ` | Gibt an, ob die Hardwareuhr Lokalzeit verwendet |

**Status der Zeitsynchronisation anzeigen**

```bash
[RO] timedatectl timesync-status
```

**Alle verfügbaren Synchronisationsinformationen anzeigen**

```bash
[RO] timedatectl show-timesync --all
```

**Dienststatus prüfen**

```bash
[RO] systemctl status systemd-timesyncd --no-pager
```

**Protokolle anzeigen**

```bash
[RO][PRIV][SENS] sudo journalctl -u systemd-timesyncd \
    --since "-24 hours" --no-pager
```

**Konfiguration anzeigen**

```bash
[RO][FILE] systemd-analyze cat-config systemd/timesyncd.conf
```

> `timedatectl timesync-status` und `show-timesync` funktionieren nur, wenn `systemd-timesyncd` verwendet und von der eingesetzten systemd-Version unterstützt wird. Bei chrony oder ntpd müssen deren eigene Werkzeuge verwendet werden.

</details>

<details>
<summary><strong>9. Linux mit chrony untersuchen</strong></summary>

Chrony wird häufig auf Linux-Servern, virtuellen Maschinen und Systemen mit unregelmäßiger Netzwerkverbindung verwendet.

**Synchronisationsstatus anzeigen**

```bash
[RO] chronyc tracking
```

Wichtige Werte:

| Wert | Bedeutung |
|---|---|
| `Reference ID` | Aktuell verwendete Referenz |
| `Stratum` | Entfernung zur ursprünglichen Referenzuhr |
| `Ref time` | Zeitpunkt der letzten verwendeten Messung |
| `System time` | Abweichung der Systemuhr |
| `Last offset` | Zuletzt gemessene Abweichung |
| `RMS offset` | Langfristige Abweichung |
| `Leap status` | Synchronisations- beziehungsweise Schaltsekundenstatus |

**Zeitquellen anzeigen**

```bash
[RO] chronyc sources -v
```

**Messwerte der Quellen anzeigen**

```bash
[RO] chronyc sourcestats -v
```

**Chrony-Aktivität prüfen**

```bash
[RO] chronyc activity
```

**Dienststatus anzeigen**

```bash
[RO] systemctl status chronyd --no-pager
```

Je nach Distribution kann der Dienst auch `chrony` heißen:

```bash
[RO] systemctl status chrony --no-pager
```

**Protokolle anzeigen**

```bash
[RO][PRIV][SENS] sudo journalctl -u chronyd \
    --since "-24 hours" --no-pager
```

oder:

```bash
[RO][PRIV][SENS] sudo journalctl -u chrony \
    --since "-24 hours" --no-pager
```

**Kennzeichen in `chronyc sources -v`**

| Zeichen | Bedeutung |
|---|---|
| `^*` | Aktuell ausgewählte NTP-Quelle |
| `^+` | Geeignete zusätzliche Quelle |
| `^-` | Geeignete, aber nicht verwendete Quelle |
| `^?` | Quelle nicht erreichbar oder noch nicht ausreichend bewertet |
| `^x` | Quelle wird als fehlerhaft bewertet |
| `^~` | Quelle weist zu große Schwankungen auf |

> Ein erreichbarer Server ist nicht automatisch eine geeignete Zeitquelle. Chrony bewertet unter anderem Abweichung, Stabilität und Messqualität.

</details>

<details>
<summary><strong>10. Linux mit klassischem ntpd untersuchen</strong></summary>

Auf älteren oder speziell konfigurierten Systemen kann weiterhin `ntpd` verwendet werden.

**Dienststatus prüfen**

```bash
[RO] systemctl status ntp --no-pager
```

oder abhängig von der Distribution:

```bash
[RO] systemctl status ntpd --no-pager
```

**Zeitpartner anzeigen**

```bash
[RO] ntpq -pn
```

Typische Markierungen:

| Zeichen | Bedeutung |
|---|---|
| `*` | Aktuell ausgewählte Zeitquelle |
| `+` | Geeignete zusätzliche Quelle |
| `-` | Von der Auswahl verworfene Quelle |
| `x` | Als falsch bewertete Quelle |
| Leerzeichen | Quelle wurde noch nicht ausgewählt |

**Protokolle anzeigen**

```bash
[RO][PRIV][SENS] sudo journalctl -u ntp \
    --since "-24 hours" --no-pager
```

oder:

```bash
[RO][PRIV][SENS] sudo journalctl -u ntpd \
    --since "-24 hours" --no-pager
```

> Es sollte zuerst ermittelt werden, welcher Zeitdienst tatsächlich aktiv ist. Mehrere parallel aktive Zeitdienste können sich gegenseitig beeinflussen.

</details>

<details>
<summary><strong>11. Aktiven Zeitdienst unter Linux bestimmen</strong></summary>

**Erkannten NTP-Dienst anzeigen**

```bash
[RO] timedatectl status
```

**Typische Dienste prüfen**

```bash
[RO] systemctl is-active systemd-timesyncd
```

```bash
[RO] systemctl is-active chronyd
```

```bash
[RO] systemctl is-active chrony
```

```bash
[RO] systemctl is-active ntpd
```

```bash
[RO] systemctl is-active ntp
```

**Laufende Prozesse suchen**

```bash
[RO] ps -ef |
    grep -E '[c]hronyd|[n]tpd|[s]ystemd-timesyncd'
```

**Typische Problemkonstellationen**

- Mehrere Zeitdienste sind gleichzeitig aktiv.
- Ein alter Zeitdienst wurde nach einer Migration nicht entfernt.
- Der Dienst läuft, besitzt aber keine verwendbare Quelle.
- Die Distribution verwaltet die Konfiguration über ein anderes Werkzeug.
- Eine virtuelle Maschine erhält zusätzlich Zeit vom Hypervisor.
- Eine Konfigurationsmanagement-Lösung überschreibt lokale Änderungen.

</details>

<details>
<summary><strong>12. Zeitstatus unter macOS untersuchen</strong></summary>

**Lokale Zeit anzeigen**

```bash
[RO] date "+%Y-%m-%dT%H:%M:%S%z"
```

**UTC-Zeit anzeigen**

```bash
[RO] date -u "+%Y-%m-%dT%H:%M:%SZ"
```

**Zeitzone anzeigen**

```bash
[RO][PRIV] sudo systemsetup -gettimezone
```

**Prüfen, ob Netzwerkzeit aktiviert ist**

```bash
[RO][PRIV] sudo systemsetup -getusingnetworktime
```

**Eingetragenen Netzwerkzeitserver anzeigen**

```bash
[RO][PRIV][SENS] sudo systemsetup -getnetworktimeserver
```

**Aktive Systemeinstellungen anzeigen**

```bash
[RO] systemsetup -help
```

`systemsetup` benötigt für viele Abfragen Administratorrechte.

**NTP-Server aktiv abfragen**

```bash
[TEST] sntp -d <ZEITSERVER>
```

Beispiel:

```bash
[TEST] sntp -d time.apple.com
```

Dieser Test fragt eine Zeitquelle ab, ändert aber nicht automatisch die lokale Systemzeit.

**Zeitbezogene Protokolle der letzten Stunde durchsuchen**

```bash
[RO][PRIV][SENS] sudo log show --last 1h \
    --predicate 'process == "timed" OR process == "sntp"' \
    --style compact
```

Die vorhandenen Prozessnamen und Protokolle können sich zwischen macOS-Versionen unterscheiden.

**Grafische Kontrolle**

```text
Apple-Menü
→ Systemeinstellungen
→ Allgemein
→ Datum & Uhrzeit
```

Dort werden unter anderem geprüft:

- Datum und Uhrzeit automatisch einstellen
- Eingetragener Netzwerkzeitserver
- Zeitzone automatisch anhand des Standorts einstellen
- Aktive Zeitzone
- Standortdienste für die automatische Zeitzone

</details>

<details>
<summary><strong>13. Erreichbarkeit des Zeitservers prüfen</strong></summary>

NTP verwendet normalerweise UDP-Port 123. Ein erfolgreicher Ping beweist nicht, dass NTP funktioniert.

**Namensauflösung prüfen**

Windows:

```powershell
[RO] Resolve-DnsName "<ZEITSERVER>"
```

Linux:

```bash
[RO] getent ahosts "<ZEITSERVER>"
```

macOS:

```bash
[RO] dscacheutil -q host -a name "<ZEITSERVER>"
```

**Windows: NTP-Antwort und Zeitabweichung testen**

```cmd
[TEST] w32tm /stripchart /computer:<ZEITSERVER> /samples:5 /dataonly
```

**Linux mit chrony**

```bash
[RO] chronyc sources -v
```

**macOS**

```bash
[TEST] sntp -d <ZEITSERVER>
```

**Netzwerkaufzeichnung unter Linux**

```bash
[TEST][PRIV][SENS] sudo tcpdump -ni any udp port 123
```

**Netzwerkaufzeichnung unter macOS**

```bash
[TEST][PRIV][SENS] sudo tcpdump -ni any udp port 123
```

Dabei ist zu prüfen:

1. Verlässt eine Anfrage das System?
2. Wird sie an die erwartete IP-Adresse gesendet?
3. Kommt eine Antwort zurück?
4. Verwendet das System tatsächlich diese Gegenstelle?
5. Blockiert eine lokale oder zentrale Firewall UDP 123?
6. Überschreibt ein VPN die Route oder DNS-Auflösung?

> Ein einfacher TCP-Porttest ist für NTP ungeeignet, weil NTP normalerweise UDP und nicht TCP verwendet.

</details>

<details>
<summary><strong>14. Zeitzone und Sommerzeit untersuchen</strong></summary>

Eine korrekte Synchronisation liefert eine gemeinsame Zeitbasis. Die lokale Darstellung hängt zusätzlich von der Zeitzone ab.

**Windows**

```powershell
[RO] Get-TimeZone
```

```cmd
[RO] tzutil /g
```

Verfügbare Zeitzonen anzeigen:

```powershell
[RO] Get-TimeZone -ListAvailable
```

**Linux**

```bash
[RO] timedatectl status
```

```bash
[RO] readlink -f /etc/localtime
```

Verfügbare Zeitzonen anzeigen:

```bash
[RO] timedatectl list-timezones
```

**macOS**

```bash
[RO][PRIV] sudo systemsetup -gettimezone
```

**Typische Zeitzonenfehler**

- Ein System verwendet UTC statt `Europe/Berlin`.
- Ein Standortwechsel wurde nicht berücksichtigt.
- Veraltete Zeitzonendaten enthalten falsche Sommerzeitregeln.
- Ein Container besitzt eine andere Zeitzone als der Host.
- Eine Anwendung verwendet eine eigene Zeitzonenkonfiguration.
- Die Datenbank speichert UTC, die Anwendung interpretiert sie als Lokalzeit.
- Ein Protokoll zeigt UTC ohne deutliche Kennzeichnung.
- Die Hardwareuhr wird unter Linux als lokale Zeit interpretiert.

**Wichtige Unterscheidung**

| Situation | Bewertung |
|---|---|
| UTC falsch | Synchronisations- oder Uhrenproblem |
| UTC richtig, Lokalzeit falsch | Zeitzonenproblem |
| Betriebssystemzeit richtig, Anwendung falsch | Anwendungskonfiguration prüfen |
| Anzeige richtig, Logzeit abweichend | Prüfen, ob das Protokoll UTC verwendet |

</details>

<details>
<summary><strong>15. Virtuelle Maschinen und Hypervisor berücksichtigen</strong></summary>

Virtuelle Maschinen können ihre Zeit aus mehreren Quellen erhalten:

- Virtuelle Hardwareuhr
- Hypervisor oder Gasterweiterungen
- Betriebssystem-Zeitdienst
- Active-Directory-Zeithierarchie
- Externer NTP-Server

Wenn mehrere Quellen gleichzeitig eingreifen, kann die Uhr springen oder ständig korrigiert werden.

**Typische Ursachen**

- Host besitzt selbst eine falsche Uhrzeit.
- VM wird nach längerer Pause fortgesetzt.
- Snapshot stellt einen älteren Zustand wieder her.
- Live-Migration verändert die Zeitbasis.
- Hypervisor-Zeitsynchronisation und NTP arbeiten gegeneinander.
- Ein virtueller Domänencontroller verwendet die falsche Quelle.
- Gasterweiterungen sind veraltet oder falsch konfiguriert.
- Die VM war längere Zeit ohne CPU-Zeit oder Netzwerkverbindung.

**Prüfreihenfolge**

1. Zeitquelle innerhalb der VM ermitteln.
2. Zeitstatus des Hypervisors prüfen.
3. Gasterweiterungen und Integrationsdienste kontrollieren.
4. Domänenrolle der VM berücksichtigen.
5. Snapshot- oder Migrationsereignisse zeitlich vergleichen.
6. Prüfen, ob mehrere Zeitquellen gleichzeitig aktiv sind.
7. Herstellerempfehlung des verwendeten Hypervisors beachten.

**Windows-VM**

```cmd
[RO] w32tm /query /source
```

Die Ausgabe:

```text
VM IC Time Synchronization Provider
```

weist bei Hyper-V auf eine Zeitbereitstellung über die Integrationskomponenten hin.

> Bei Domänencontrollern muss besonders sorgfältig geplant werden, welche Zeitquelle maßgeblich ist. Eine unkontrollierte Änderung kann die gesamte Domänenzeithierarchie beeinflussen.

</details>

<details>
<summary><strong>16. Container und Zeitzonenfehler untersuchen</strong></summary>

Container verwenden normalerweise die Kernel-Uhr des Hosts. Die angezeigte lokale Zeit kann dennoch durch Zeitzonendateien, Umgebungsvariablen oder das Container-Image abweichen.

**Zeit auf dem Host prüfen**

```bash
[RO] date --iso-8601=seconds
```

**Zeit in einem Docker-Container prüfen**

```bash
[RO] docker exec "<CONTAINER>" date --iso-8601=seconds
```

**UTC-Zeit im Container prüfen**

```bash
[RO] docker exec "<CONTAINER>" date -u "+%Y-%m-%dT%H:%M:%SZ"
```

**Zeitzonenumgebung prüfen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format '{{range .Config.Env}}{{println .}}{{end}}'
```

In der Ausgabe kann nach einer Variable wie `TZ` gesucht werden.

**Typische Ursachen**

- Hostzeit ist falsch.
- Im Container fehlt die Zeitzonendatenbank.
- Die Variable `TZ` ist falsch gesetzt.
- `/etc/localtime` enthält eine andere Zeitzone.
- Anwendung verwendet unabhängig vom Betriebssystem UTC.
- Host und Container zeigen dieselbe UTC-Zeit, aber unterschiedliche Lokalzeit.
- Protokolltreiber fügt Zeitstempel in UTC hinzu.

> Die Systemzeit eines Containers sollte nicht durch zusätzliche Berechtigungen oder manuelle Änderungen korrigiert werden. Zuerst müssen Hostzeit, Zeitzone und Anwendungskonfiguration geprüft werden.

</details>

<details>
<summary><strong>17. Hardwareuhr und Firmware berücksichtigen</strong></summary>

Die Hardwareuhr, auch RTC genannt, hält die Zeit während des ausgeschalteten Zustands. Beim Start übernimmt das Betriebssystem einen Ausgangswert und synchronisiert ihn anschließend.

**Linux**

```bash
[RO][PRIV] sudo hwclock --show
```

Vergleich mit der Systemzeit:

```bash
[RO] date --iso-8601=seconds
```

**Mögliche Ursachen für eine falsche Startzeit**

- Leere oder schwache CMOS-Batterie
- Falsche Uhrzeit im BIOS oder UEFI
- Hardwareuhr wird unterschiedlich als UTC oder Lokalzeit interpretiert
- Dual-Boot-Systeme verwenden verschiedene RTC-Konventionen
- Virtuelle Hardwareuhr liefert einen falschen Wert
- NTP-Synchronisation erfolgt nach dem Start nicht
- System besitzt beim Start keine Netzwerkverbindung

**Typisches Fehlerbild einer schwachen CMOS-Batterie**

- Uhrzeit ist nach vollständigem Ausschalten wieder falsch.
- Firmware-Einstellungen gehen verloren.
- Datum springt auf einen älteren Standardwert.
- Nach erfolgreicher Netzwerksynchronisation stimmt die Uhr bis zum nächsten Ausschalten.

Bei virtuellen Maschinen existiert keine normale austauschbare CMOS-Batterie. Dort müssen Hypervisor, virtuelle Hardwareuhr und Hostzeit geprüft werden.

</details>

<details>
<summary><strong>18. Zeitabhängige Sicherheitsfehler erkennen</strong></summary>

**Kerberos**

Kerberos verwendet Zeitstempel, um wiederholte Verwendung abgefangener Authentifizierungsdaten zu erschweren. Eine zu große Abweichung zwischen Client, Domänencontroller und Server kann Anmeldungen verhindern.

Typische Meldungen:

- Zeitunterschied zwischen Client und Server
- Kerberos-Ticket noch nicht gültig
- Kerberos-Ticket abgelaufen
- Domänenanmeldung nicht möglich

**TLS und Zertifikate**

Zertifikate besitzen unter anderem:

- Gültigkeitsbeginn
- Gültigkeitsende

Bei falscher Systemzeit kann ein gültiges Zertifikat erscheinen als:

- Noch nicht gültig
- Abgelaufen
- Außerhalb des Gültigkeitszeitraums

**Zeitbasierte Einmalpasswörter**

TOTP-Verfahren berechnen Codes aus:

- Gemeinsamen Geheimnis
- Aktuellem Zeitintervall

Wenn Smartphone, Server oder Authentifizierungsdienst zeitlich abweichen, werden korrekte Codes abgelehnt.

**Prüfregel**

Bei gleichzeitigen Fehlern in Anmeldung, Zertifikaten und MFA sollte die Systemzeit sehr früh in der Diagnose geprüft werden.

</details>

<details>
<summary><strong>19. Sichere Korrekturmaßnahmen</strong></summary>

Vor jeder Änderung muss die Ursache bestimmt werden. Ein manuelles Stellen der Uhr kann Protokolle, Datenbanken, Cluster und laufende Anwendungen beeinflussen.

**Windows: erneute Synchronisation anfordern**

```cmd
[CHANGE][PRIV] w32tm /resync
```

Mit erneuter Erkennung der Zeitquelle:

```cmd
[CHANGE][PRIV] w32tm /resync /rediscover
```

**Linux mit systemd-timesyncd**

Zeitdienst nur nach bestätigter Ursache neu starten:

```bash
[CHANGE][PRIV] sudo systemctl restart systemd-timesyncd
```

**Linux mit chrony**

Dienst nur nach bestätigter Ursache neu starten:

```bash
[CHANGE][PRIV] sudo systemctl restart chronyd
```

Abhängig von der Distribution:

```bash
[CHANGE][PRIV] sudo systemctl restart chrony
```

**Große Zeitkorrekturen**

Große Zeitsprünge können:

- Datenbanktransaktionen beeinflussen
- Protokolle unbrauchbar machen
- Sitzungen und Tickets ungültig machen
- Cluster irritieren
- Aufgaben doppelt oder gar nicht ausführen
- Monitoringdaten in die falsche Reihenfolge bringen
- Anwendungen mit zeitabhängigen Sperren beeinträchtigen

Vor einer großen Korrektur sind deshalb zu prüfen:

- Größe und Richtung der Abweichung
- Rolle des Systems
- Laufende Datenbanken und Cluster
- Domänenfunktion
- Virtualisierung
- Wartungsfenster
- Sicherung und Rückfallplan
- Herstellerdokumentation der betroffenen Anwendung

> Die Zeit niemals absichtlich zurückstellen, ohne die Auswirkungen auf Datenbanken, Protokolle und verteilte Systeme zu bewerten.

</details>

<details>
<summary><strong>20. Typische Fehlinterpretationen vermeiden</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „Die Uhr in der Taskleiste stimmt.“ | Quelle, Synchronisationsstatus, UTC und Zeitzone zusätzlich prüfen. |
| „Ping zum Zeitserver funktioniert.“ | Ping prüft nicht die NTP-Kommunikation über UDP 123. |
| „Der Zeitdienst läuft, also synchronisiert er.“ | Ein aktiver Dienst kann ohne brauchbare Quelle laufen. |
| „Eine Stunde Abweichung ist ein NTP-Fehler.“ | Häufig ist die Zeitzone oder Sommerzeitregel falsch. |
| „Alle Systeme müssen dieselbe lokale Uhrzeit anzeigen.“ | Systeme in verschiedenen Zeitzonen können dieselbe UTC-Zeit verwenden. |
| „Die Uhr kann gefahrlos manuell gestellt werden.“ | Zeitsprünge können Anwendungen und Protokolle beeinflussen. |
| „Jeder Domänenclient sollte einen öffentlichen NTP-Server verwenden.“ | Domänenmitglieder sollten normalerweise der AD-Zeithierarchie folgen. |
| „Der Hypervisor regelt die Zeit vollständig.“ | Gastzeitdienst und Hypervisor können gleichzeitig eingreifen. |
| „Container besitzen eine vollständig eigene Uhr.“ | Container verwenden normalerweise die Kernel-Uhr des Hosts. |
| „Ein Neustart behebt die Zeit dauerhaft.“ | Eine fehlerhafte Quelle oder Konfiguration bleibt bestehen. |

</details>

<details>
<summary><strong>21. Sichere Reihenfolge der Fehleranalyse</strong></summary>

1. Fehlerzeitpunkt und originale Fehlermeldung dokumentieren.
2. Lokale Zeit und UTC-Zeit erfassen.
3. Zeitzone kontrollieren.
4. Abweichung mit einem vertrauenswürdigen Vergleichssystem bestimmen.
5. Aktiven Zeitdienst identifizieren.
6. Tatsächlich verwendete Zeitquelle ermitteln.
7. Synchronisationsstatus und letzte erfolgreiche Messung prüfen.
8. Namensauflösung der Zeitquelle testen.
9. NTP-Antwort beziehungsweise Zeitabweichung aktiv prüfen.
10. Firewall, Routing und UDP 123 untersuchen.
11. Ereignis- beziehungsweise Systemprotokolle auswerten.
12. Domänen-, Virtualisierungs- oder Containerstruktur berücksichtigen.
13. Erst danach eine erneute Synchronisation oder Konfigurationsänderung durchführen.
14. Nach der Maßnahme Quelle, Status und Abweichung erneut kontrollieren.
15. Ursache und Korrektur dokumentieren.

</details>

<details>
<summary><strong>22. Schnelle Befehlsübersicht</strong></summary>

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Lokale Zeit | `[RO] Get-Date -Format o` | `[RO] date --iso-8601=seconds` | `[RO] date "+%Y-%m-%dT%H:%M:%S%z"` |
| UTC-Zeit | `[RO] (Get-Date).ToUniversalTime().ToString("o")` | `[RO] date -u "+%Y-%m-%dT%H:%M:%SZ"` | `[RO] date -u "+%Y-%m-%dT%H:%M:%SZ"` |
| Zeitzone | `[RO] Get-TimeZone` | `[RO] timedatectl status` | `[RO][PRIV] sudo systemsetup -gettimezone` |
| Zeitdienst | `[RO] Get-Service W32Time` | `[RO] systemctl status <DIENST>` | Systemdienst wird durch macOS verwaltet |
| Zeitquelle | `[RO] w32tm /query /source` | `[RO] timedatectl timesync-status` oder `[RO] chronyc tracking` | `[RO][PRIV] sudo systemsetup -getnetworktimeserver` |
| Synchronisationsstatus | `[RO] w32tm /query /status` | `[RO] timedatectl status` oder `[RO] chronyc tracking` | `[RO][PRIV] sudo systemsetup -getusingnetworktime` |
| Zeitpartner | `[RO] w32tm /query /peers` | `[RO] chronyc sources -v` oder `[RO] ntpq -pn` | Eingetragener Netzwerkzeitserver |
| Abweichung testen | `[TEST] w32tm /stripchart ...` | Quellenstatus des verwendeten Dienstes | `[TEST] sntp -d <ZEITSERVER>` |
| Protokolle | `[RO] Get-WinEvent ...` | `[RO][PRIV] sudo journalctl -u <DIENST>` | `[RO][PRIV] sudo log show ...` |
| Hardwareuhr | Nicht üblicherweise separat | `[RO][PRIV] sudo hwclock --show` | Nicht regulär erforderlich |
| Synchronisation anfordern | `[CHANGE][PRIV] w32tm /resync` | Abhängig vom eingesetzten Dienst | Durch macOS beziehungsweise Systemeinstellungen |
| NTP-Verkehr erfassen | Paketaufzeichnung erforderlich | `[TEST][PRIV] sudo tcpdump -ni any udp port 123` | `[TEST][PRIV] sudo tcpdump -ni any udp port 123` |

</details>

<details>
<summary><strong>23. Entscheidungsmatrix</strong></summary>

| Befund | Wahrscheinliche Ursache | Nächster Schritt |
|---|---|---|
| UTC korrekt, Lokalzeit falsch | Zeitzone oder Sommerzeit | Zeitzonenkonfiguration prüfen |
| UTC und Lokalzeit falsch | Zeitquelle oder Synchronisation | Dienst und Quelle untersuchen |
| Zeitdienst läuft, keine Quelle | Netzwerk, DNS, Firewall oder Konfiguration | Erreichbarkeit und Zeitpartner prüfen |
| Quelle ist lokale Hardwareuhr | Keine externe Synchronisation | Erwartete Zeitarchitektur prüfen |
| Nur Domänenanmeldungen betroffen | Kerberos-Zeitabweichung möglich | Client, Server und DC vergleichen |
| TLS und MFA gleichzeitig fehlerhaft | Systemzeit wahrscheinlich falsch | Datum, UTC und Quelle sofort prüfen |
| Zeit springt nach Neustart zurück | RTC, Firmware, Host oder CMOS-Batterie | Startzeit und Hardware prüfen |
| Nur eine VM betroffen | Hypervisor- oder Gastkonfiguration | Beide Zeitquellen vergleichen |
| Alle Domänensysteme betroffen | Fehler in der AD-Zeithierarchie | PDC-Emulator und übergeordnete Quelle prüfen |
| Abweichung wächst kontinuierlich | Uhrdrift oder keine Nachregelung | Messwerte und Dienstprotokolle untersuchen |
| Exakt eine Stunde Abweichung | Zeitzone oder Sommerzeit | Zeitzone statt NTP-Konfiguration prüfen |
| Host korrekt, Container falsch | Container-Zeitzone oder Anwendung | `TZ`, Zeitzonendateien und Anwendung prüfen |

</details>

<details>
<summary><strong>24. Dokumentationsvorlage</strong></summary>

```text
Ticket:
Datum und Uhrzeit der Analyse:
Bearbeiter:

Betroffenes System:
Betriebssystem:
Systemrolle:
Physisch, virtuell oder Container:
Domänenmitglied:
Betroffene Anwendung oder Funktion:

Originale Fehlermeldung:
Lokale Zeit:
UTC-Zeit:
Zeitzone:
Vergleichssystem:
Gemessene Abweichung:

Aktiver Zeitdienst:
Dienststatus:
Aktive Zeitquelle:
Konfigurierte Zeitpartner:
Letzte erfolgreiche Synchronisation:
Stratum beziehungsweise Hierarchie:
NTP-Antwort erhalten:
UDP 123 erreichbar:
DNS-Auflösung:

Zeitbezogene Protokollmeldungen:
Hypervisor-Zeitquelle:
Snapshot oder Migration:
Hardwareuhr:
Gruppenrichtlinie oder Geräteverwaltung:

Vermutete Ursache:
Durchgeführte Tests:
Durchgeführte Änderung:
Auswirkung der Änderung:
Rückfallplan:

Zeitquelle nach der Maßnahme:
Abweichung nach der Maßnahme:
Synchronisationsstatus nach der Maßnahme:
Funktionsprüfung:
Weiterführende Maßnahmen:
```

</details>

---

**Merksatz**

> Bei Zeitfehlern werden immer vier Dinge getrennt geprüft: aktuelle UTC-Zeit, lokale Zeitzone, verwendete Zeitquelle und tatsächlicher Synchronisationsstatus. Die Uhr wird erst verändert, wenn Ursache und Auswirkungen geklärt sind.

**Quellen und weiterführende Dokumentation**

- [Microsoft Learn – Windows Time Service Tools and Settings](https://learn.microsoft.com/windows-server/networking/windows-time-service/windows-time-service-tools-and-settings)
- [Microsoft Learn – Funktionsweise des Windows-Zeitdiensts](https://learn.microsoft.com/windows-server/networking/windows-time-service/how-the-windows-time-service-works)
- [Microsoft Learn – Windows Server Time Accuracy Improvements](https://learn.microsoft.com/windows-server/networking/windows-time-service/windows-server-2016-improvements)
- [Microsoft Learn – Windows Time Service Technical Reference](https://learn.microsoft.com/windows-server/networking/windows-time-service/windows-time-service-tech-ref)
- [systemd – timedatectl](https://www.freedesktop.org/software/systemd/man/latest/timedatectl.html)
- [systemd – systemd-timesyncd](https://www.freedesktop.org/software/systemd/man/latest/systemd-timesyncd.service.html)
- [chrony – Dokumentation](https://chrony-project.org/documentation.html)
- [chrony – chronyc](https://chrony-project.org/doc/4.8/chronyc.html)
- [Linux-Handbuch – hwclock](https://man7.org/linux/man-pages/man8/hwclock.8.html)
- [Apple – Datum und Uhrzeit auf dem Mac automatisch einstellen](https://support.apple.com/de-de/guide/mac-help/mchlp2996/mac)
- [Apple – Einstellungen für Datum und Uhrzeit](https://support.apple.com/de-de/guide/mac-help/mchlp1124/mac)
- [Apple – Fehlerhafte Uhrzeit oder Zeitzone korrigieren](https://support.apple.com/en-us/101619)

# 4.13 Update-, Patch- und Paketverwaltungsfehler

Updates können in verschiedenen Phasen scheitern: bei der Erkennung, beim Herunterladen, bei der Signaturprüfung, während der Installation, beim Neustart oder erst nach der Aktivierung der neuen Komponenten.

Dabei muss zwischen Betriebssystemupdates, Sicherheitsupdates, Treibern, Firmware, Anwendungspaketen und verwalteten Unternehmensupdates unterschieden werden.

Typische Auswirkungen sind:

- Updates werden nicht gefunden oder angeboten.
- Der Download bleibt bei einem bestimmten Prozentwert stehen.
- Pakete können wegen Abhängigkeitsfehlern nicht installiert werden.
- Signaturen oder Zertifikate werden abgelehnt.
- Ein Neustart wird wiederholt angefordert.
- Ein Update wird nach dem Neustart zurückgerollt.
- Dienste starten nach dem Update nicht mehr.
- Paketdatenbanken oder Updatekomponenten sind beschädigt.
- Ein WSUS-, Repository-, Proxy- oder MDM-Server ist nicht erreichbar.
- Der Datenträger besitzt nicht genügend freien Speicherplatz.
- Ein anderes Installationsprogramm blockiert die Paketverwaltung.
- Das System verwendet eine nicht mehr unterstützte Version.
- Ein Update ist für die verwendete Architektur oder Version ungeeignet.

> **Wichtig:** Die Meldung „Update fehlgeschlagen“ bezeichnet nur das Ergebnis. Für die Diagnose müssen Updatequelle, Fehlerphase, Fehlercode, Systemzustand und Protokolle getrennt untersucht werden.

**Kennzeichnung der Befehle**

| Kennzeichnung | Bedeutung |
|---|---|
| `[RO]` | Nur lesender Befehl |
| `[TEST]` | Führt eine aktive Prüfung aus |
| `[PRIV]` | Erhöhte Berechtigungen erforderlich |
| `[FILE]` | Liest Dateien oder Verzeichnisse |
| `[SENS]` | Ausgabe kann sensible Informationen enthalten |
| `[CHANGE]` | Verändert Cache, Konfiguration oder Systemzustand |
| `[DISRUPT]` | Kann Dienste unterbrechen oder einen Neustart erfordern |

---

<details>
<summary><strong>1. Updatefehler strukturiert aufnehmen</strong></summary>

Vor einer Reparatur müssen die genaue Updateart und die Fehlerphase bestimmt werden.

**Zu erfassende Informationen**

- Welches Betriebssystem und welche Version werden verwendet?
- Welches konkrete Update oder Paket schlägt fehl?
- Welche Paket-, KB-, Build- oder Versionsnummer ist betroffen?
- Wird das Update direkt vom Hersteller oder intern bereitgestellt?
- Tritt der Fehler bei Erkennung, Download, Prüfung, Installation oder Neustart auf?
- Wird ein numerischer oder hexadezimaler Fehlercode angezeigt?
- Sind alle Systeme oder nur einzelne Geräte betroffen?
- Wurde das System kürzlich geklont, wiederhergestellt oder migriert?
- Ist ein Neustart ausstehend?
- Besteht ausreichend freier Speicherplatz?
- Stimmen Datum und Uhrzeit?
- Wird ein Proxy, VPN, WSUS, MDM oder internes Repository verwendet?
- Wurden Sicherheitssoftware oder Firewallregeln verändert?
- Ist die Betriebssystemversion noch unterstützt?
- Funktionierte die Aktualisierung zuvor?
- Welche Änderungen erfolgten unmittelbar vor dem Fehler?

**Fehlerphasen**

| Phase | Typische Ursachen |
|---|---|
| Erkennung | Updatequelle, Richtlinie, MDM, Repository oder nicht unterstützte Version |
| Download | Netzwerk, DNS, Proxy, Firewall, CDN oder Speicherplatz |
| Signaturprüfung | Falsche Zeit, Zertifikat, Schlüsselbund oder beschädigter Download |
| Vorbereitung | Speicherplatz, Abhängigkeiten, Paketdatenbank oder Systemdateien |
| Installation | Gesperrte Dateien, laufende Dienste, Abhängigkeiten oder Berechtigungen |
| Neustart | Pending-Reboot-Zustand, Bootfehler, Treiber oder Firmware |
| Aktivierung | Dienststart, Konfigurationsmigration oder inkompatible Anwendung |
| Rollback | Installationsfehler, Bootproblem oder nicht erfüllte Voraussetzung |

**Dokumentationsregel**

Der originale Fehlercode muss vollständig übernommen werden. Beschreibungen wie „irgendein Updatefehler“ reichen für eine gezielte Analyse nicht aus.

</details>

<details>
<summary><strong>2. Vorbedingungen auf allen Betriebssystemen prüfen</strong></summary>

Viele Updatefehler entstehen nicht in der Paketverwaltung selbst.

| Prüfbereich | Warum er wichtig ist |
|---|---|
| Freier Speicherplatz | Updates benötigen Platz für Download, Entpacken, Installation und Rückfall |
| Datum und Uhrzeit | Signaturen, Zertifikate und TLS-Verbindungen sind zeitabhängig |
| DNS | Update- und Repositoryserver müssen aufgelöst werden |
| Internet beziehungsweise internes Netzwerk | Updatequelle muss erreichbar sein |
| Proxy | Systemdienste verwenden möglicherweise andere Proxyeinstellungen als Benutzer |
| Neustartstatus | Eine ältere Installation kann noch nicht abgeschlossen sein |
| Systemversion | Nicht mehr unterstützte Versionen erhalten möglicherweise keine Updates |
| Architektur | Paket muss zu x64, ARM64 oder einer anderen Architektur passen |
| Paketquelle | Repository, WSUS oder MDM muss gültige Metadaten bereitstellen |
| Signaturen | Paket und Metadaten müssen vertrauenswürdig sein |
| Berechtigungen | Installation benötigt normalerweise administrative Rechte |
| Sicherung | Fehlerhafte Updates können einen Rollback erforderlich machen |

**Schnellprüfung des Speicherplatzes**

Windows:

```powershell
[RO] Get-Volume |
    Select-Object DriveLetter, FileSystemLabel,
        HealthStatus, SizeRemaining, Size
```

Linux:

```bash
[RO] df -hT
```

macOS:

```bash
[RO] df -h
```

**Zeit prüfen**

Windows:

```powershell
[RO] Get-Date -Format o
```

Linux:

```bash
[RO] timedatectl status
```

macOS:

```bash
[RO] date "+%Y-%m-%dT%H:%M:%S%z"
```

</details>

<details>
<summary><strong>3. Betriebssystemversion und Architektur ermitteln</strong></summary>

Ein Update kann nur installiert werden, wenn Version, Build, Edition und Architektur unterstützt werden.

**Windows**

```powershell
[RO] Get-ComputerInfo |
    Select-Object WindowsProductName, WindowsEditionId,
        WindowsVersion, OsBuildNumber, OsArchitecture
```

Kompakter:

```powershell
[RO] Get-CimInstance Win32_OperatingSystem |
    Select-Object Caption, Version, BuildNumber, OSArchitecture
```

**Linux**

```bash
[RO][FILE] cat /etc/os-release
```

```bash
[RO] uname -r
```

```bash
[RO] uname -m
```

**macOS**

```bash
[RO] sw_vers
```

```bash
[RO] uname -m
```

**Typische Architekturbezeichnungen**

| Bezeichnung | Bedeutung |
|---|---|
| `x86_64` beziehungsweise `AMD64` | 64-Bit-x86 |
| `aarch64` beziehungsweise `ARM64` | 64-Bit-ARM |
| `i386` oder `i686` | 32-Bit-x86 |
| `arm64` unter macOS | Apple Silicon |
| `x86_64` unter macOS | Intel-Mac oder gegebenenfalls übersetzter Prozess |

> Die Prozessorarchitektur des Hosts, die Architektur des Betriebssystems und die Architektur eines einzelnen Programms können unterschiedlich sein.

</details>

<details>
<summary><strong>4. Windows-Updatequelle und Richtlinien prüfen</strong></summary>

Windows-Geräte können Updates aus unterschiedlichen Quellen beziehen:

- Windows Update
- Microsoft Update
- Windows Server Update Services, kurz WSUS
- Microsoft Intune oder andere Geräteverwaltung
- Windows Update for Business
- Lokale oder zentrale Richtlinien
- Manuell bereitgestellte Updatepakete

**Windows-Update-Richtlinien anzeigen**

```powershell
[RO][SENS] Get-ItemProperty `
    -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' `
    -ErrorAction SilentlyContinue
```

**Richtlinien für automatische Updates anzeigen**

```powershell
[RO][SENS] Get-ItemProperty `
    -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU' `
    -ErrorAction SilentlyContinue
```

**Angewendete Gruppenrichtlinien dokumentieren**

```cmd
[RO][SENS] gpresult /scope computer /r
```

Ausführlichen HTML-Bericht erstellen:

```cmd
[RO][FILE][SENS] gpresult /scope computer /h "<ZIELPFAD>\gpresult-computer.html"
```

**Relevante Hinweise**

| Beobachtung | Mögliche Bedeutung |
|---|---|
| Interner Update-Server eingetragen | Gerät verwendet wahrscheinlich WSUS |
| WSUS-Server nicht erreichbar | Erkennung und Download können scheitern |
| Keine sichtbare lokale Richtlinie | Einstellung kann über MDM oder andere Verwaltung kommen |
| Einstellung springt zurück | Zentrale Richtlinie überschreibt lokale Änderung |
| Update wird anderen Geräten angeboten | Zielgruppen-, Freigabe- oder Kompatibilitätsunterschied möglich |
| Gerät erhält nur bestimmte Updatearten | Richtlinie oder Updatekanal begrenzt das Angebot |

> Registrywerte dürfen nicht allein aufgrund einer Internetanleitung gelöscht oder verändert werden. Zuerst muss festgestellt werden, ob sie zentral verwaltet werden.

</details>

<details>
<summary><strong>5. Windows-Update-Dienste untersuchen</strong></summary>

**Relevante Dienste anzeigen**

```powershell
[RO] Get-Service -Name wuauserv, bits, cryptsvc, trustedinstaller |
    Select-Object Name, DisplayName, Status, StartType
```

Bedeutung:

| Dienst | Aufgabe |
|---|---|
| `wuauserv` | Windows Update |
| `BITS` | Hintergrundübertragung von Dateien |
| `CryptSvc` | Kryptografische Dienste und Signaturprüfungen |
| `TrustedInstaller` | Windows Modules Installer |

**Ausführliche Dienstinformationen**

```powershell
[RO] Get-CimInstance Win32_Service |
    Where-Object {
        $_.Name -in 'wuauserv','BITS','CryptSvc','TrustedInstaller'
    } |
    Select-Object Name, State, StartMode, StartName, ExitCode
```

**Abhängigkeiten eines Dienstes anzeigen**

```powershell
[RO] Get-Service -Name wuauserv -RequiredServices
```

**Wichtige Bewertung**

- Ein beendeter Dienst ist nicht automatisch fehlerhaft.
- Einige Dienste werden bedarfsgesteuert gestartet.
- Der Starttyp `Manual` kann vorgesehen sein.
- Zentral verwaltete Systeme können abweichende Konfigurationen verwenden.
- Ein Dienstneustart behebt nicht die Ursache einer defekten Richtlinie oder Updatequelle.

</details>

<details>
<summary><strong>6. Installierte Windows-Updates und Verlauf prüfen</strong></summary>

**Ausgewählte installierte Updates anzeigen**

```powershell
[RO] Get-HotFix |
    Sort-Object InstalledOn -Descending |
    Select-Object HotFixID, Description, InstalledOn, InstalledBy
```

> `Get-HotFix` zeigt nicht jede denkbare Update-, Treiber-, App- oder Servicing-Komponente an. Die Ausgabe darf deshalb nicht als vollständiges Inventar aller installierten Aktualisierungen interpretiert werden.

**Installierte Windows-Pakete mit DISM anzeigen**

```cmd
[RO][PRIV] DISM.exe /Online /Get-Packages /Format:Table
```

**Nach einem bestimmten KB-Paket suchen**

```powershell
[RO] Get-HotFix -Id <KB-NUMMER> -ErrorAction SilentlyContinue
```

Beispiel:

```powershell
[RO] Get-HotFix -Id KB5030000 -ErrorAction SilentlyContinue
```

Die KB-Nummer im Beispiel ist durch die tatsächlich zu prüfende Nummer zu ersetzen.

**Installationszeit und Paketstatus mit DISM prüfen**

```cmd
[RO][PRIV] DISM.exe /Online /Get-PackageInfo /PackageName:<PAKETNAME>
```

Den exakten Paketnamen erhält man zuvor über:

```cmd
[RO][PRIV] DISM.exe /Online /Get-Packages /Format:Table
```

</details>

<details>
<summary><strong>7. Windows-Updateprotokolle auswerten</strong></summary>

Moderne Windows-Versionen speichern Windows-Update-Ereignisse überwiegend als ETL-Daten. `Get-WindowsUpdateLog` erzeugt daraus eine lesbare Protokolldatei.

**Lesbares WindowsUpdate-Protokoll erzeugen**

```powershell
[RO][FILE][SENS] Get-WindowsUpdateLog -LogPath "<ZIELPFAD>\WindowsUpdate.log"
```

> Der Befehl sammelt und konvertiert vorhandene Protokolldaten. Die erzeugte Datei kann Servernamen, URLs, Geräteinformationen und Fehlerdetails enthalten.

**Windows-Update-Ereignisse anzeigen**

```powershell
[RO][SENS] Get-WinEvent -LogName `
    'Microsoft-Windows-WindowsUpdateClient/Operational' |
Select-Object -First 100 TimeCreated, LevelDisplayName, Id, Message
```

**Nur Warnungen und Fehler der letzten 24 Stunden**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = 'Microsoft-Windows-WindowsUpdateClient/Operational'
    StartTime = (Get-Date).AddHours(-24)
} |
Where-Object {
    $_.LevelDisplayName -in 'Warning','Error','Warnung','Fehler'
} |
Select-Object TimeCreated, LevelDisplayName, Id, Message
```

**Servicing-Protokolle**

```text
[RO][FILE][SENS] %WINDIR%\Logs\CBS\CBS.log
```

```text
[RO][FILE][SENS] %WINDIR%\Logs\DISM\dism.log
```

**Setup- und Upgradeprotokolle können unter anderem hier liegen**

```text
[RO][FILE][SENS] %WINDIR%\Panther
```

```text
[RO][FILE][SENS] %WINDIR%\Logs\MoSetup
```

Die tatsächlich vorhandenen Dateien hängen von Updateart, Betriebssystemversion und Fehlerphase ab.

**Bei der Protokollanalyse suchen nach**

- Fehlercode
- KB-Nummer
- Paketname
- Zeitpunkt des Installationsversuchs
- Downloadfehler
- Signaturfehler
- Paketabhängigkeit
- ausstehendem Neustart
- beschädigten Komponenten
- Rollback-Ursache

</details>

<details>
<summary><strong>8. Ausstehenden Windows-Neustart erkennen</strong></summary>

Ein ausstehender Neustart kann weitere Updates, Rolleninstallationen oder Paketänderungen blockieren.

**Component-Based-Servicing prüfen**

```powershell
[RO] Test-Path `
    'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending'
```

**Windows-Update-Neustartstatus prüfen**

```powershell
[RO] Test-Path `
    'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired'
```

**Ausstehende Dateiumbenennungen prüfen**

```powershell
[RO][SENS] Get-ItemProperty `
    -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' `
    -Name PendingFileRenameOperations `
    -ErrorAction SilentlyContinue
```

**Bewertung**

- Nicht jeder vorhandene Indikator bedeutet denselben Neustartgrund.
- Ein Neustart muss mit den Protokollen und dem Änderungsverlauf abgeglichen werden.
- Produktivserver dürfen nicht unkontrolliert neu gestartet werden.
- Vor dem Neustart müssen Dienste, Benutzer, Clusterstatus und Wartungsfenster geprüft werden.

</details>

<details>
<summary><strong>9. Windows-Komponentenspeicher prüfen</strong></summary>

Beschädigungen im Windows-Komponentenspeicher können Updates und Rolleninstallationen verhindern.

**Schnelle Prüfung**

```cmd
[TEST][PRIV] DISM.exe /Online /Cleanup-Image /CheckHealth
```

`/CheckHealth` prüft, ob bereits eine Beschädigung markiert wurde. Es führt keinen vollständigen Scan aus.

**Ausführlichere Prüfung**

```cmd
[TEST][PRIV] DISM.exe /Online /Cleanup-Image /ScanHealth
```

**Systemdateien prüfen**

```cmd
[TEST][PRIV] sfc /verifyonly
```

**Reparatur des Komponentenspeichers**

```cmd
[CHANGE][PRIV] DISM.exe /Online /Cleanup-Image /RestoreHealth
```

**Systemdateien prüfen und reparieren**

```cmd
[CHANGE][PRIV] sfc /scannow
```

**Wichtige Hinweise**

- `RestoreHealth` kann Dateien von Windows Update beziehen.
- In abgeschotteten Umgebungen kann eine passende Reparaturquelle erforderlich sein.
- Eine Reparaturquelle muss zur Betriebssystemversion und zum Wartungsstand passen.
- DISM und SFC können längere Zeit benötigen.
- Ein Abbruch sollte nicht allein wegen eines länger unveränderten Prozentwerts erfolgen.
- Protokolle befinden sich unter anderem in `CBS.log` und `dism.log`.

> DISM und SFC sind keine pauschalen ersten Schritte für jeden Updatefehler. Zuerst müssen Fehlercode, Quelle, Speicherplatz und Updatephase geprüft werden.

</details>

<details>
<summary><strong>10. Windows-Proxy und Netzwerkpfad prüfen</strong></summary>

Windows-Systemdienste können andere Proxyeinstellungen verwenden als ein angemeldeter Benutzer.

**WinHTTP-Proxy anzeigen**

```cmd
[RO] netsh winhttp show proxy
```

**DNS-Auflösung prüfen**

```powershell
[RO] Resolve-DnsName "<UPDATE-ODER-WSUS-SERVER>"
```

**HTTPS-Erreichbarkeit eines konkret bekannten Servers prüfen**

```powershell
[TEST] Test-NetConnection `
    -ComputerName "<SERVERNAME>" `
    -Port 443
```

Bei einem internen WSUS-Server muss der tatsächlich konfigurierte Port verwendet werden.

**Route anzeigen**

```powershell
[RO] Test-NetConnection `
    -ComputerName "<SERVERNAME>" `
    -TraceRoute
```

**Typische Ursachen**

- Proxy verlangt eine interaktive Anmeldung.
- WinHTTP-Proxy ist veraltet.
- PAC-Datei funktioniert nur im Benutzerkontext.
- Firewall blockiert Updateendpunkte.
- TLS-Inspection verändert Zertifikate.
- DNS liefert eine falsche oder interne Adresse.
- VPN verändert Route oder Namensauflösung.
- WSUS ist erreichbar, aber dessen Datenbank oder Anwendungspool ist gestört.

> Öffentliche Updateplattformen verwenden mehrere dynamische Endpunkte. Es sollten keine unbestätigten Einzeladressen dauerhaft freigeschaltet werden; maßgeblich ist die aktuelle Herstellerdokumentation.

</details>

<details>
<summary><strong>11. Debian- und Ubuntu-Paketverwaltung prüfen</strong></summary>

Debian und Ubuntu verwenden üblicherweise APT und dpkg.

**Betriebssystemversion prüfen**

```bash
[RO][FILE] cat /etc/os-release
```

**Konfigurierte Paketquellen anzeigen**

```bash
[RO][FILE][SENS] grep -RhsE '^[[:space:]]*deb ' \
    /etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null
```

Neuere APT-Quellen können zusätzlich im Deb822-Format mit der Endung `.sources` gespeichert sein:

```bash
[RO][FILE][SENS] grep -RhsE \
    '^[[:space:]]*(Types|URIs|Suites|Components|Signed-By):' \
    /etc/apt/sources.list.d 2>/dev/null
```

**Paketstatus auf Inkonsistenzen prüfen**

```bash
[RO][PRIV] sudo dpkg --audit
```

Alternativ:

```bash
[RO][PRIV] sudo dpkg -C
```

**Paketabhängigkeiten prüfen**

```bash
[TEST][PRIV] sudo apt-get check
```

**Installierte und verfügbare Version eines Pakets anzeigen**

```bash
[RO] apt-cache policy "<PAKETNAME>"
```

**Zurückgehaltene Pakete anzeigen**

```bash
[RO] apt-mark showhold
```

**Paketarchitektur anzeigen**

```bash
[RO] dpkg --print-architecture
```

Zusätzlich konfigurierte Architekturen:

```bash
[RO] dpkg --print-foreign-architectures
```

**Letzte dpkg-Aktionen anzeigen**

```bash
[RO][FILE][SENS] tail -n 100 /var/log/dpkg.log
```

**APT-Verlauf anzeigen, sofern vorhanden**

```bash
[RO][FILE][SENS] ls -l /var/log/apt
```

```bash
[RO][FILE][SENS] tail -n 100 /var/log/apt/history.log
```

</details>

<details>
<summary><strong>12. APT-Aktualisierung und Fehlerausgabe kontrolliert prüfen</strong></summary>

Das Aktualisieren der Paketlisten ist bereits eine Veränderung des lokalen Paketcache.

```bash
[CHANGE][PRIV] sudo apt update
```

Dabei sind besonders folgende Meldungen zu beachten:

| Meldung | Mögliche Ursache |
|---|---|
| `Temporary failure resolving` | DNS-Problem |
| `Connection timed out` | Netzwerk, Proxy, Firewall oder Repository |
| `404 Not Found` | Falscher Distributionsname oder veraltete Quelle |
| `NO_PUBKEY` | Fehlender oder falsch eingebundener Signaturschlüssel |
| `Release file is not valid yet` | Systemzeit möglicherweise falsch |
| `does not have a Release file` | Quelle unterstützt die Distribution nicht |
| `Hash Sum mismatch` | Spiegelserver, Proxycache oder inkonsistente Metadaten |
| `Could not get lock` | Andere Paketverwaltung ist aktiv |
| `Unmet dependencies` | Abhängigkeitskonflikt |
| `held broken packages` | Zurückgehaltene oder nicht auflösbare Pakete |
| `No space left on device` | Speicherplatz oder Inodes ausgeschöpft |

**Simulation einer Installation**

```bash
[TEST] apt-get --simulate install "<PAKETNAME>"
```

Die Simulation verändert keine Pakete, bildet aber nicht jede Nebenwirkung eines tatsächlichen Installationsskripts ab.

**Paketinformationen anzeigen**

```bash
[RO] apt-cache show "<PAKETNAME>"
```

**Abhängigkeiten anzeigen**

```bash
[RO] apt-cache depends "<PAKETNAME>"
```

**Reverse-Abhängigkeiten anzeigen**

```bash
[RO] apt-cache rdepends "<PAKETNAME>"
```

</details>

<details>
<summary><strong>13. Paketmanager-Sperren unter Linux untersuchen</strong></summary>

Eine Sperrdatei darf nicht allein aufgrund ihrer Existenz gelöscht werden. Zuerst muss geprüft werden, ob ein Paketmanager tatsächlich arbeitet.

**APT- und dpkg-Prozesse anzeigen**

```bash
[RO][SENS] ps -ef |
    grep -E '[a]pt|[d]pkg|[u]nattended-upgrade'
```

**Prozesse mit geöffneten APT- oder dpkg-Sperren anzeigen**

```bash
[RO][PRIV][SENS] sudo lsof \
    /var/lib/dpkg/lock \
    /var/lib/dpkg/lock-frontend \
    /var/lib/apt/lists/lock \
    /var/cache/apt/archives/lock 2>/dev/null
```

**Automatische Updates prüfen**

```bash
[RO] systemctl status apt-daily.service --no-pager
```

```bash
[RO] systemctl status apt-daily-upgrade.service --no-pager
```

**Protokolle automatischer Updates**

```bash
[RO][PRIV][SENS] sudo journalctl \
    -u apt-daily.service \
    -u apt-daily-upgrade.service \
    --since "-24 hours" --no-pager
```

> Das Löschen einer Sperrdatei oder Beenden eines Paketmanagers während einer Installation kann die Paketdatenbank beschädigen. Erst muss geklärt werden, ob der Prozess noch arbeitet, wartet oder abgestürzt ist.

</details>

<details>
<summary><strong>14. Unvollständige dpkg-Transaktionen behandeln</strong></summary>

Ein abgebrochener Installationsprozess kann Pakete in einem nicht fertig konfigurierten Zustand hinterlassen.

**Zustand zunächst prüfen**

```bash
[RO][PRIV] sudo dpkg --audit
```

**Paketstatus eines bestimmten Pakets anzeigen**

```bash
[RO] dpkg-query -W \
    -f='${Package}\t${Status}\t${Version}\n' "<PAKETNAME>"
```

**Noch nicht konfigurierte Pakete konfigurieren**

```bash
[CHANGE][PRIV] sudo dpkg --configure -a
```

**Abhängigkeiten reparieren**

```bash
[CHANGE][PRIV] sudo apt-get --fix-broken install
```

Diese Befehle können:

- Paketkonfigurationen ausführen
- Dienste starten oder neu starten
- Konfigurationsdateien verändern
- zusätzliche Pakete installieren
- Pakete entfernen
- Administratorfragen anzeigen

Vorher sollten geprüft werden:

- Sicherung oder Snapshot
- freier Speicherplatz
- aktueller Paketstatus
- betroffene Produktivdienste
- vorgeschlagene Paketänderungen
- Wartungsfenster

> Bei `apt-get --fix-broken install` muss die vorgeschlagene Paketliste vor der Bestätigung vollständig gelesen werden.

</details>

<details>
<summary><strong>15. DNF- und RPM-Systeme untersuchen</strong></summary>

Fedora, Red Hat Enterprise Linux und verwandte Distributionen verwenden häufig DNF und RPM.

**Betriebssystemversion**

```bash
[RO][FILE] cat /etc/os-release
```

**Aktive Repositories anzeigen**

```bash
[RO][SENS] dnf repolist
```

**Alle bekannten Repositories anzeigen**

```bash
[RO][SENS] dnf repolist --all
```

**Paketdatenbank und Abhängigkeiten prüfen**

```bash
[TEST][PRIV] sudo dnf check
```

**Verfügbare Aktualisierungen prüfen**

```bash
[TEST][PRIV] sudo dnf check-update
```

> `dnf check-update` kann mit Rückgabecode `100` enden, wenn Updates verfügbar sind. Dieser Rückgabecode bedeutet dann nicht automatisch einen Fehler.

**Paketinformationen anzeigen**

```bash
[RO] dnf info "<PAKETNAME>"
```

**Installierte Paketversion anzeigen**

```bash
[RO] rpm -q "<PAKETNAME>"
```

**Paketarchitektur anzeigen**

```bash
[RO] rpm -q --queryformat \
    '%{NAME}\t%{VERSION}-%{RELEASE}\t%{ARCH}\n' "<PAKETNAME>"
```

**Transaktionsverlauf anzeigen**

```bash
[RO][SENS] dnf history
```

**Details einer Transaktion**

```bash
[RO][SENS] dnf history info <TRANSAKTIONS-ID>
```

**Installierte Dateien gegen RPM-Metadaten prüfen**

```bash
[TEST][PRIV][FILE][SENS] sudo rpm -Va
```

`rpm -Va` kann lange laufen und meldet auch absichtlich veränderte Konfigurationsdateien. Abweichungen sind nicht automatisch Beschädigungen.

</details>

<details>
<summary><strong>16. Zypper- und RPM-Systeme untersuchen</strong></summary>

SUSE Linux Enterprise und openSUSE verwenden typischerweise Zypper.

**Repositories anzeigen**

```bash
[RO][SENS] zypper repos
```

Ausführlicher:

```bash
[RO][SENS] zypper repos --details
```

**Verfügbare Patches anzeigen**

```bash
[TEST][PRIV] sudo zypper list-patches
```

**Abhängigkeiten prüfen**

```bash
[TEST][PRIV] sudo zypper verify
```

**Paketinformationen anzeigen**

```bash
[RO] zypper info "<PAKETNAME>"
```

**Installierte Version prüfen**

```bash
[RO] rpm -q "<PAKETNAME>"
```

**Zypper-Protokoll lesen**

```bash
[RO][FILE][SENS] tail -n 100 /var/log/zypper.log
```

</details>

<details>
<summary><strong>17. macOS-Softwareupdates untersuchen</strong></summary>

**macOS-Version und Build anzeigen**

```bash
[RO] sw_vers
```

**Verfügbare Apple-Softwareupdates suchen**

```bash
[TEST] softwareupdate --list
```

Der Befehl kontaktiert die konfigurierte Updateinfrastruktur und kann einige Zeit benötigen.

**Verlauf installierter Apple-Updates anzeigen**

```bash
[RO] softwareupdate --history
```

Ausführlicher Verlauf:

```bash
[RO] softwareupdate --history --all
```

**Hilfe der installierten softwareupdate-Version anzeigen**

```bash
[RO] softwareupdate --help
```

> Die verfügbaren Optionen von `softwareupdate` können sich zwischen macOS-Versionen unterscheiden. Deshalb sollte die lokale Hilfe geprüft werden, bevor Installationsoptionen verwendet werden.

**Freien Speicherplatz prüfen**

```bash
[RO] df -h /
```

**Datum und Uhrzeit prüfen**

```bash
[RO] date "+%Y-%m-%dT%H:%M:%S%z"
```

**Netzwerkzeitstatus prüfen**

```bash
[RO][PRIV] sudo systemsetup -getusingnetworktime
```

**Eingetragenen Zeitserver anzeigen**

```bash
[RO][PRIV][SENS] sudo systemsetup -getnetworktimeserver
```

**MDM-Registrierungsstatus anzeigen**

```bash
[RO][PRIV][SENS] sudo profiles status -type enrollment
```

Ein verwalteter Mac kann Updates aufgrund von MDM-Vorgaben:

- verzögert angeboten bekommen
- zu einem Termin erzwungen installieren
- nur über bestimmte Updatekanäle erhalten
- mit anderen Neustartbedingungen installieren
- nicht manuell verändern dürfen

</details>

<details>
<summary><strong>18. macOS-Updateprotokolle auswerten</strong></summary>

**Softwareupdate-Protokolle der letzten Stunde**

```bash
[RO][PRIV][SENS] sudo log show --last 1h \
    --predicate 'process == "softwareupdated"' \
    --style compact
```

**Mehrere typische Updateprozesse berücksichtigen**

```bash
[RO][PRIV][SENS] sudo log show --last 2h \
    --predicate 'process == "softwareupdated" OR process == "softwareupdate"' \
    --style compact
```

**Nur Fehler und schwerwiegende Meldungen**

```bash
[RO][PRIV][SENS] sudo log show --last 2h \
    --predicate '(process == "softwareupdated" OR process == "softwareupdate") AND messageType >= error' \
    --style compact
```

Die von macOS verwendeten Prozesse und Protokollfelder können sich zwischen Versionen unterscheiden. Wenn die Abfrage keine Ergebnisse liefert, bedeutet dies nicht automatisch, dass kein Updateversuch stattgefunden hat.

**Typische Ursachen**

- Zu wenig Speicherplatz
- Nicht unterstütztes Mac-Modell
- Falsche Systemzeit
- Netzwerk- oder CDN-Problem
- MDM-Aufschub
- Fehlende Benutzerbestätigung
- FileVault- oder Bootstrap-Token-Anforderung in verwalteten Umgebungen
- Beschädigter Download
- Nicht abgeschlossener vorheriger Updateversuch
- Firmware- oder Wiederherstellungsfehler
- Update wird für den verwendeten Kanal noch nicht angeboten

</details>

<details>
<summary><strong>19. Repository-, Signatur- und Zertifikatsfehler unterscheiden</strong></summary>

Softwarepakete und Repositorymetadaten werden normalerweise kryptografisch geprüft.

**Typische Fehlerursachen**

| Ursache | Wirkung |
|---|---|
| Falsche Systemzeit | Zertifikat oder signierte Metadaten erscheinen ungültig |
| Abgelaufener Signaturschlüssel | Repository wird nicht akzeptiert |
| Falscher Schlüssel | Signatur kann nicht verifiziert werden |
| Manipulierender Proxy | TLS- oder Zertifikatsprüfung schlägt fehl |
| Unvollständiger Download | Prüfsumme stimmt nicht |
| Veraltete Repositorydefinition | Release-Datei oder Paketpfad fehlt |
| Nicht unterstützte Distribution | Repository stellt keine passenden Metadaten bereit |
| Falsche Architektur | Paket kann nicht installiert werden |
| Internes Zertifikat fehlt | Unternehmensrepository wird nicht vertraut |
| Spiegelserver nicht synchron | Metadaten und Paketdateien passen vorübergehend nicht zusammen |

**Sicherheitsregel**

Signatur- und Zertifikatsprüfungen dürfen nicht dauerhaft deaktiviert werden, um eine Installation „zum Laufen zu bringen“.

Stattdessen müssen geprüft werden:

1. Systemzeit
2. Repositoryadresse
3. Distributionsversion
4. Paketarchitektur
5. erwarteter Signaturschlüssel
6. Zertifikatskette
7. Proxy- oder TLS-Inspection
8. Integrität des Downloads
9. offizielle Installationsanleitung des Herstellers

</details>

<details>
<summary><strong>20. Abhängigkeiten und Versionskonflikte analysieren</strong></summary>

Paketmanager installieren selten nur eine einzelne Datei. Pakete besitzen Abhängigkeiten, Konflikte und Versionsanforderungen.

**Typische Beziehungen**

| Beziehung | Bedeutung |
|---|---|
| Abhängigkeit | Zusätzlich benötigtes Paket |
| Versionsabhängigkeit | Nur bestimmte Versionen sind zulässig |
| Konflikt | Pakete dürfen nicht gleichzeitig installiert sein |
| Ersatz | Ein Paket ersetzt ein anderes |
| Empfehlung | Zusätzliches Paket wird empfohlen |
| Architekturabhängigkeit | Paket benötigt eine bestimmte Plattform |
| Modulschnittstelle | Anwendung benötigt eine kompatible Bibliotheksversion |

**APT-Abhängigkeiten anzeigen**

```bash
[RO] apt-cache depends "<PAKETNAME>"
```

**APT-Reverse-Abhängigkeiten**

```bash
[RO] apt-cache rdepends "<PAKETNAME>"
```

**RPM-Abhängigkeiten anzeigen**

```bash
[RO] rpm -qR "<PAKETNAME>"
```

**Paket ermitteln, das eine Fähigkeit bereitstellt**

DNF:

```bash
[RO] dnf provides "<DATEI-ODER-FÄHIGKEIT>"
```

APT:

```bash
[RO] apt-file search "<DATEINAME>"
```

`apt-file` ist nicht standardmäßig auf jedem System installiert und benötigt einen eigenen Suchindex.

**Diagnosefragen**

- Ist das benötigte Repository aktiviert?
- Ist ein Paket bewusst festgehalten worden?
- Wurden Fremdquellen gemischt?
- Wird ein Paket aus einer anderen Distributionsversion verwendet?
- Verlangt die Anwendung eine ältere Bibliothek?
- Wurde ein Teilupdate durchgeführt?
- Passt die Architektur?
- Ist ein Herstellerrepository noch unterstützt?

</details>

<details>
<summary><strong>21. Paketcache und heruntergeladene Dateien richtig bewerten</strong></summary>

Beschädigte oder unvollständige Downloads können wiederholte Fehler verursachen. Das pauschale Löschen aller Updatecaches ist dennoch kein sinnvoller erster Diagnoseschritt.

**Vor einer Cachebereinigung prüfen**

- Ist der Fehler reproduzierbar?
- Ist die Prüfsumme falsch?
- Betrifft der Fehler immer dieselbe Datei?
- Liegt ein Proxycache zwischen Client und Repository?
- Ist genügend Speicherplatz vorhanden?
- Gibt es noch einen aktiven Paketmanager?
- Werden Dateien für einen Rollback benötigt?
- Kann der Download aus einer vertrauenswürdigen Quelle erneut erfolgen?

**APT-Downloadcache anzeigen**

```bash
[RO][FILE] du -sh /var/cache/apt/archives
```

**DNF-Cachebelegung anzeigen**

```bash
[RO][FILE][PRIV] sudo du -sh /var/cache/dnf
```

**Windows-Update-Downloadbereich**

```text
[RO][FILE][PRIV] %WINDIR%\SoftwareDistribution\Download
```

> Der Ordner `SoftwareDistribution` darf nicht unkontrolliert umbenannt oder gelöscht werden. Ein Reset der Windows-Updatekomponenten verändert den Updatezustand und erschwert möglicherweise die ursprüngliche Ursachenanalyse.

</details>

<details>
<summary><strong>22. Automatische Updates und Wartungsfenster prüfen</strong></summary>

Automatische Aktualisierungen können parallel zu manuellen Arbeiten laufen oder durch Wartungsregeln eingeschränkt sein.

**Windows**

Zu prüfen sind:

- Gruppenrichtlinien
- Windows Update for Business
- WSUS-Zielgruppen
- aktive Nutzungszeit
- Neustartrichtlinien
- Intune-Update-Ringe
- geplante Wartungsfenster

**Debian und Ubuntu**

```bash
[RO] systemctl status apt-daily.timer --no-pager
```

```bash
[RO] systemctl status apt-daily-upgrade.timer --no-pager
```

```bash
[RO][FILE] systemctl list-timers --all |
    grep -E 'apt|upgrade'
```

**DNF-Systeme**

```bash
[RO] systemctl list-timers --all |
    grep -E 'dnf|upgrade'
```

Je nach Distribution und Konfiguration kann beispielsweise `dnf-automatic` verwendet werden.

**macOS**

Zu prüfen sind:

- Einstellungen für automatische Updates
- MDM-Aufschübe
- erzwungene Installationstermine
- erforderliche Benutzeraktion
- Neustartbedingungen
- verfügbare Bootstrap- oder Secure Tokens

> Automatische Updateprozesse dürfen nicht beendet werden, ohne ihren aktuellen Transaktionszustand zu prüfen.

</details>

<details>
<summary><strong>23. Updatefehler nach dem Neustart analysieren</strong></summary>

Ein Update kann zunächst erfolgreich erscheinen und erst beim Neustart scheitern.

**Typische Symptome**

- Endlose Neustartschleife
- „Änderungen werden rückgängig gemacht“
- Dienst startet nicht
- Treiber wird nicht geladen
- Netzwerkverbindung fehlt
- Anwendung ist inkompatibel
- Kernel startet nicht
- Dateisystem muss geprüft werden
- Firmwareaktualisierung schlägt fehl
- Verschlüsseltes Systemvolume wird nicht entsperrt

**Prüfreihenfolge**

1. Exakte Meldung und Zeitpunkt dokumentieren.
2. Prüfen, ob ein automatischer Rollback erfolgt ist.
3. Update- und Bootprotokolle sichern.
4. Zuletzt installierte Pakete ermitteln.
5. Dienst- und Treiberstatus kontrollieren.
6. Freien Speicherplatz prüfen.
7. Abhängige Systeme und Clusterstatus berücksichtigen.
8. Herstellerhinweise zum konkreten Update prüfen.
9. Rücknahme nur nach Bewertung der Sicherheitsauswirkung durchführen.
10. Vor erneuter Installation die ursprüngliche Ursache beheben.

**Linux: vorherigen Boot untersuchen**

```bash
[RO][PRIV][SENS] sudo journalctl -b -1 -p warning --no-pager
```

**Windows: letzte Systemfehler**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = 'System'
    StartTime = (Get-Date).AddHours(-24)
} |
Where-Object {
    $_.LevelDisplayName -in 'Warning','Error','Warnung','Fehler'
} |
Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message
```

</details>

<details>
<summary><strong>24. Updates in Clustern und hochverfügbaren Systemen</strong></summary>

Bei Clustern, Replikationssystemen und redundanten Diensten reicht die Betrachtung eines einzelnen Servers nicht aus.

**Vor einem Update prüfen**

- Ist der Cluster gesund?
- Funktioniert die Replikation?
- Ist ausreichend Redundanz vorhanden?
- Welcher Knoten besitzt aktuell die produktiven Rollen?
- Können Rollen kontrolliert verschoben werden?
- Ist Quorum beziehungsweise Witness erreichbar?
- Sind alle Knoten kompatibel?
- Unterstützt der Hersteller gemischte Patchstände?
- Existiert ein getesteter Rückfallplan?
- Ist das Monitoring aktiv?
- Wurde eine Sicherung geprüft?

**Gefahren**

- Mehrere Knoten werden gleichzeitig neu gestartet.
- Ein bereits gestörter Knoten wird als Ausweichknoten eingeplant.
- Datenbankschema und Anwendungsversion passen nicht zusammen.
- Quorum geht verloren.
- Load Balancer leitet weiterhin auf einen gewarteten Knoten.
- Replikation wird durch Versionsunterschiede unterbrochen.
- Ein automatisches Update umgeht das Wartungsfenster.

> Ein Snapshot eines einzelnen Clusterknotens ist kein vollständiger Rückfallplan für einen verteilten Dienst.

</details>

<details>
<summary><strong>25. Sichere Reihenfolge der Updatefehleranalyse</strong></summary>

1. Betroffenes Update, Paket oder KB eindeutig bestimmen.
2. Originalen Fehlercode und Fehlerzeitpunkt dokumentieren.
3. Betriebssystemversion, Build und Architektur prüfen.
4. Updatephase bestimmen.
5. Freien Speicherplatz und Inodes kontrollieren.
6. Datum, Uhrzeit und Zeitzone prüfen.
7. Ausstehenden Neustart berücksichtigen.
8. Updatequelle, Repository, WSUS oder MDM ermitteln.
9. DNS, Proxy, Firewall und Erreichbarkeit prüfen.
10. Paketmanager- beziehungsweise Updatedienste untersuchen.
11. Protokolle zum Fehlerzeitpunkt auswerten.
12. Paketabhängigkeiten und Signaturen prüfen.
13. Aktive Installations- oder Sperrprozesse identifizieren.
14. Systemdateien beziehungsweise Paketdatenbank kontrollieren.
15. Erst danach Cachebereinigung oder Reparaturmaßnahmen planen.
16. Änderung im Wartungsfenster durchführen.
17. Neustartbedarf kontrolliert umsetzen.
18. Update-, Dienst- und Anwendungsfunktion verifizieren.
19. Ergebnis und verbleibende Risiken dokumentieren.

</details>

<details>
<summary><strong>26. Typische Fehlinterpretationen vermeiden</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „Der Download hängt bei 0 Prozent.“ | Verbindung, Metadatenprüfung oder Vorbereitung kann bereits laufen. |
| „Der Update-Dienst ist beendet.“ | Bedarfsgesteuerter Dienst kann regulär beendet sein. |
| „Ping funktioniert, also ist Windows Update erreichbar.“ | DNS, HTTPS, Proxy, CDN und Authentifizierung sind zusätzlich relevant. |
| „Ein Neustart ist immer harmlos.“ | Produktivdienste, Cluster und Benutzer müssen berücksichtigt werden. |
| „Cache löschen behebt jeden Updatefehler.“ | Es entfernt Symptome und erschwert möglicherweise die Diagnose. |
| „Signaturprüfung kann vorübergehend deaktiviert werden.“ | Dadurch wird eine wichtige Sicherheitskontrolle umgangen. |
| „Get-HotFix zeigt alle installierten Updates.“ | Es erfasst nicht jede Update- und Paketart. |
| „Rückgabecode 100 von dnf ist ein Fehler.“ | Bei `dnf check-update` kann er verfügbare Updates anzeigen. |
| „Eine Sperrdatei kann einfach gelöscht werden.“ | Eine aktive Pakettransaktion könnte beschädigt werden. |
| „Update fehlgeschlagen bedeutet fehlerhaftes Update.“ | Ursache kann lokal in Speicher, Netzwerk, Zeit oder Paketstatus liegen. |
| „Snapshot entspricht einer Sicherung.“ | Snapshot und unabhängige Sicherung erfüllen unterschiedliche Aufgaben. |
| „Update erfolgreich bedeutet Dienst funktionsfähig.“ | Nachkontrolle von Diensten und Anwendungen bleibt erforderlich. |

</details>

<details>
<summary><strong>27. Schnelle Befehlsübersicht</strong></summary>

| Aufgabe | Windows | Debian/Ubuntu | RHEL/Fedora | macOS |
|---|---|---|---|---|
| Betriebssystemversion | `[RO] Get-ComputerInfo` | `[RO] cat /etc/os-release` | `[RO] cat /etc/os-release` | `[RO] sw_vers` |
| Architektur | `[RO] Get-CimInstance Win32_OperatingSystem` | `[RO] dpkg --print-architecture` | `[RO] uname -m` | `[RO] uname -m` |
| Freier Speicher | `[RO] Get-Volume` | `[RO] df -hT` | `[RO] df -hT` | `[RO] df -h` |
| Updatequelle | Richtlinien und WSUS prüfen | APT-Quelldateien prüfen | `[RO] dnf repolist` | MDM und Updateeinstellungen |
| Updatedienste | `[RO] Get-Service wuauserv,bits,cryptsvc,trustedinstaller` | APT-Timer und Prozesse | DNF-Timer und Prozesse | macOS-Systemdienst |
| Updatehistorie | `Get-HotFix` und DISM | APT- und dpkg-Protokolle | `[RO] dnf history` | `[RO] softwareupdate --history` |
| Verfügbare Updates | Windows-Updateverwaltung | `[CHANGE][PRIV] sudo apt update` | `[TEST][PRIV] sudo dnf check-update` | `[TEST] softwareupdate --list` |
| Paketstatus prüfen | DISM | `[RO][PRIV] sudo dpkg --audit` | `[TEST][PRIV] sudo dnf check` | Updateprotokoll prüfen |
| Abhängigkeiten prüfen | CBS- und DISM-Protokoll | `[TEST][PRIV] sudo apt-get check` | `[TEST][PRIV] sudo dnf check` | Nicht direkt vergleichbar |
| Paketversion | DISM oder `Get-HotFix` | `[RO] apt-cache policy "<PAKET>"` | `[RO] rpm -q "<PAKET>"` | Anwendungsspezifisch |
| Ausstehender Neustart | Registryindikatoren prüfen | `/var/run/reboot-required` kann distributionsabhängig existieren | Paket- und Kernelstatus prüfen | Update- und MDM-Status prüfen |
| Protokolle | `Get-WindowsUpdateLog`, CBS, Ereignisanzeige | `/var/log/apt`, `/var/log/dpkg.log`, Journal | `dnf history`, Journal | `[RO][PRIV] log show ...` |
| Systemintegrität | `[TEST][PRIV] DISM /ScanHealth` | Paketdatenbank prüfen | `[TEST][PRIV] rpm -Va` | Festplatten- und Updateprotokolle |
| Proxy | `[RO] netsh winhttp show proxy` | APT- und Umgebungsvariablen prüfen | DNF- und Umgebungsvariablen prüfen | Netzwerk- und MDM-Konfiguration |

</details>

<details>
<summary><strong>28. Entscheidungsmatrix</strong></summary>

| Befund | Wahrscheinliche Ursache | Nächster Schritt |
|---|---|---|
| Update wird nicht angeboten | Richtlinie, Kanal, Kompatibilität oder Supportstatus | Quelle und Voraussetzungen prüfen |
| Download startet nicht | DNS, Proxy, Firewall oder Repository | Netzwerkpfad untersuchen |
| Download wiederholt beschädigt | Proxycache, Spiegelserver oder Datenträger | Prüfsumme, Quelle und Speicher prüfen |
| Signatur ungültig | Zeit, Schlüssel oder Zertifikatskette | Zeit und Vertrauenskette prüfen |
| Nicht genügend Speicher | System- oder temporäres Volume voll | Speicherverbrauch analysieren |
| Paketmanager ist gesperrt | Andere Transaktion aktiv | Prozess und Protokolle prüfen |
| Paketabhängigkeit nicht erfüllbar | Fehlendes Repository oder Versionskonflikt | Abhängigkeitsbaum untersuchen |
| Neustart wird wiederholt verlangt | Ausstehende Operation nicht abgeschlossen | Pending-Reboot-Status und Protokolle prüfen |
| Update rollt zurück | Installations-, Treiber- oder Bootfehler | Setup- und Systemprotokolle auswerten |
| Mehrere Geräte betroffen | Zentrale Quelle, Richtlinie oder Herstellerproblem | Gemeinsamen Nenner ermitteln |
| Nur ein Gerät betroffen | Lokaler Cache, Zustand oder Konfiguration | Mit funktionierendem Vergleichssystem abgleichen |
| Update erfolgreich, Dienst ausgefallen | Inkompatibilität oder Konfigurationsmigration | Dienstprotokolle und Herstellerhinweise prüfen |
| Betriebssystem nicht mehr unterstützt | Keine reguläre Updateversorgung | Geplantes Upgrade beziehungsweise Migration |
| DNF endet mit Code 100 | Updates verfügbar | Nicht als Paketmanagerfehler behandeln |

</details>

<details>
<summary><strong>29. Dokumentationsvorlage</strong></summary>

```text
Ticket:
Datum und Uhrzeit:
Bearbeiter:

Betroffenes System:
Betriebssystem:
Version und Build:
Architektur:
Systemrolle:
Physisch oder virtuell:
Cluster- oder Domänenmitglied:

Updateart:
KB-, Paket- oder Versionsnummer:
Updatequelle:
WSUS, Repository oder MDM:
Fehlerphase:
Originaler Fehlercode:
Originale Fehlermeldung:
Zeitpunkt des Fehlers:

Freier Speicher:
Inode-Belegung:
Datum und Uhrzeit:
Ausstehender Neustart:
Updatedienst:
Paketmanager:
Aktive Installationsprozesse:
Sperrstatus:

DNS-Auflösung:
Proxy:
Erreichbarkeit der Updatequelle:
Signatur- oder Zertifikatsfehler:
Repositorystatus:
Abhängigkeitsfehler:

Relevante Protokolle:
Letzte erfolgreiche Aktualisierung:
Letzte Änderungen:
Vergleich mit funktionierendem System:

Vermutete Ursache:
Durchgeführte Tests:
Sicherung geprüft:
Wartungsfenster:
Durchgeführte Änderung:
Neustart durchgeführt:
Rückfallplan:

Installationsstatus nach der Maßnahme:
Dienststatus:
Anwendungsprüfung:
Monitoring unauffällig:
Weiterführende Maßnahmen:
```

</details>

---

**Merksatz**

> Bei Updatefehlern wird nicht sofort der Cache gelöscht oder das Paket erneut installiert. Zuerst werden Updatequelle, Fehlerphase, Fehlercode, Speicherplatz, Zeit, Netzwerk, Paketstatus und Protokolle geprüft.

**Quellen und weiterführende Dokumentation**

- [Microsoft Learn – Windows-Updateprobleme behandeln](https://learn.microsoft.com/troubleshoot/windows-client/deployment/troubleshoot-windows-update-issues)
- [Microsoft Learn – Windows-Update-Beschädigungen und Installationsfehler beheben](https://learn.microsoft.com/de-de/troubleshoot/windows-server/installing-updates-features-roles/fix-windows-update-errors)
- [Microsoft Learn – Get-WindowsUpdateLog](https://learn.microsoft.com/powershell/module/windowsupdate/get-windowsupdatelog)
- [Microsoft Learn – DISM-Befehlszeilenoptionen](https://learn.microsoft.com/windows-hardware/manufacture/desktop/dism-reference--deployment-image-servicing-and-management)
- [Microsoft Learn – Windows Update for Business](https://learn.microsoft.com/windows/deployment/update/waas-manage-updates-wufb)
- [Debian-Handbuch – APT](https://www.debian.org/doc/manuals/debian-handbook/apt.en.html)
- [Ubuntu Server – Paketverwaltung](https://documentation.ubuntu.com/server/how-to/software/package-management/)
- [Ubuntu Manpages – apt-get](https://manpages.ubuntu.com/manpages/noble/en/man8/apt-get.8.html)
- [DNF-Dokumentation – Command Reference](https://dnf.readthedocs.io/en/latest/command_ref.html)
- [Red Hat – DNF-Paketverwaltung](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/managing_software_with_the_dnf_tool/)
- [openSUSE – Zypper-Dokumentation](https://doc.opensuse.org/documentation/leap/reference/html/book-opensuse-reference/cha-sw-cl.html)
- [Apple – Softwareupdate-Prozess überprüfen](https://support.apple.com/de-de/guide/deployment/dep02c211f3e/web)
- [Apple – Softwareupdates mit der Geräteverwaltung anwenden](https://support.apple.com/de-de/guide/deployment/depafd2fad80/web)
- [Apple-Handbuch – softwareupdate](https://keith.github.io/xcode-man-pages/softwareupdate.8.html)

# 4.14 Virtualisierungs- und Containerfehler

Bei virtualisierten Systemen befindet sich die Ursache einer Störung nicht zwangsläufig innerhalb des betroffenen Servers oder Containers. Der Fehler kann im Gastbetriebssystem, Hypervisor, Hostbetriebssystem, virtuellen Netzwerk, Storage, Managementsystem oder in einer Abhängigkeit außerhalb der Virtualisierungsplattform liegen.

Typische Auswirkungen sind:

- Eine virtuelle Maschine startet nicht.
- Eine VM läuft, ist aber nicht erreichbar.
- Ein Container beendet sich unmittelbar nach dem Start.
- Ein Container befindet sich in einer Neustartschleife.
- Die Anwendung ist nicht über den veröffentlichten Port erreichbar.
- Ein virtueller Datenträger ist voll oder nicht verfügbar.
- Snapshots wachsen unkontrolliert.
- Der Host besitzt zu wenig RAM, CPU oder Speicherplatz.
- Eine VM ist nach einer Migration oder Snapshot-Wiederherstellung inkonsistent.
- Virtuelle Netzwerkkarten sind mit dem falschen Netzwerk verbunden.
- Container können DNS-Namen oder andere Container nicht erreichen.
- Volume-Daten fehlen nach der Neuerstellung eines Containers.
- Das verwendete Image passt nicht zur Prozessorarchitektur.
- Integrationsdienste oder Gasterweiterungen sind fehlerhaft.
- Host und Gast verwenden konkurrierende Zeitquellen.

> **Wichtig:** Eine laufende VM, ein laufender Container oder ein Status `Up` beweist nur, dass der jeweilige Prozess gestartet wurde. Damit ist noch nicht bestätigt, dass Betriebssystem, Anwendung, Netzwerk, Storage und Abhängigkeiten funktionieren.

**Kennzeichnung der Befehle**

| Kennzeichnung | Bedeutung |
|---|---|
| `[RO]` | Nur lesender Befehl |
| `[TEST]` | Führt eine aktive Prüfung aus |
| `[PRIV]` | Erhöhte Berechtigungen erforderlich |
| `[FILE]` | Liest Dateien, Images, Volumes oder Verzeichnisse |
| `[SENS]` | Ausgabe kann sensible Informationen enthalten |
| `[CHANGE]` | Verändert Konfiguration oder Systemzustand |
| `[DISRUPT]` | Kann den Betrieb unterbrechen |

---

<details>
<summary><strong>1. Fehlerbereich zuerst eindeutig bestimmen</strong></summary>

Virtualisierungsfehler müssen schichtweise eingegrenzt werden.

```text
Anwendung
    │
Gastbetriebssystem oder Container
    │
Virtuelle Netzwerkkarte und virtueller Datenträger
    │
Hypervisor beziehungsweise Container-Engine
    │
Hostbetriebssystem
    │
Physisches Netzwerk und Storage
    │
Hardware
```

**Erste Prüffragen**

- Ist nur eine Anwendung betroffen?
- Ist das gesamte Gastbetriebssystem betroffen?
- Sind mehrere VMs oder Container betroffen?
- Befinden sich die betroffenen Systeme auf demselben Host?
- Nutzen sie denselben virtuellen Switch?
- Nutzen sie dasselbe Storage-System?
- Trat der Fehler nach Migration, Neustart, Snapshot oder Update auf?
- Ist die Managementoberfläche erreichbar?
- Wird die VM beziehungsweise der Container als laufend angezeigt?
- Ist ein Konsolenzugriff möglich?
- Funktioniert die Kommunikation innerhalb des Gasts?
- Sind Hostressourcen ausgeschöpft?
- Wurde eine Konfiguration, ein Image oder ein Compose-Projekt verändert?

**Erste Einordnung**

| Beobachtung | Wahrscheinlicher Fehlerbereich |
|---|---|
| Nur ein Dienst in einer VM gestört | Anwendung oder Gastbetriebssystem |
| Gesamte VM nicht erreichbar, Konsole funktioniert | Gastnetzwerk oder virtueller Switch |
| Gesamte VM reagiert auch über Konsole nicht | Gast, Ressourcen oder virtueller Datenträger |
| Mehrere VMs auf einem Host betroffen | Host, Hypervisor, Netzwerk oder Storage |
| VMs auf mehreren Hosts betroffen | Gemeinsames Netzwerk, Cluster oder Storage |
| Nur ein Container beendet sich | Anwendung, Image oder Containerkonfiguration |
| Alle Container reagieren nicht | Container-Engine, Host oder gemeinsame Ressource |
| Container läuft, veröffentlichter Port fehlt | Portfreigabe oder Netzwerkkonfiguration |
| Daten fehlen nach Neuerstellung | Volume oder Bind-Mount nicht korrekt eingebunden |

</details>

<details>
<summary><strong>2. VM, Container, Image und Host unterscheiden</strong></summary>

| Begriff | Bedeutung |
|---|---|
| Host | Physisches oder virtuelles System, das VMs oder Container ausführt |
| Hypervisor | Virtualisierungsschicht für virtuelle Maschinen |
| Virtuelle Maschine | Virtuelles Computersystem mit eigenem Betriebssystemkernel |
| Gastbetriebssystem | Betriebssystem innerhalb einer VM |
| Container-Engine | Verwaltet Images, Container, Netzwerke und Volumes |
| Image | Unveränderliche Vorlage für einen Container |
| Container | Laufende oder beendete Instanz eines Images |
| Volume | Von der Containerlebensdauer getrennter persistenter Speicher |
| Bind-Mount | Verzeichnis oder Datei des Hosts wird in den Container eingebunden |
| Snapshot beziehungsweise Checkpoint | Zustandsaufnahme einer VM oder eines Datenträgers |
| Virtueller Switch | Softwarebasierte Netzwerkverbindung für VMs |
| Portveröffentlichung | Zuordnung eines Hostports zu einem Containerport |

**Wichtige Unterschiede**

- Ein VM-Snapshot ist keine unabhängige Datensicherung.
- Ein Container-Image enthält normalerweise keine später erzeugten Nutzdaten.
- Das Löschen eines Containers muss ein korrekt eingebundenes Volume nicht löschen.
- Daten im beschreibbaren Container-Layer können beim Entfernen des Containers verloren gehen.
- Ein `EXPOSE`-Eintrag im Image veröffentlicht keinen Hostport.
- Ein laufender Container ist nicht automatisch eine funktionsfähige Anwendung.
- Container teilen den Kernel des Hosts; VMs besitzen einen eigenen Gastkernel.

</details>

<details>
<summary><strong>3. Hostzustand vor der Gastanalyse prüfen</strong></summary>

Bevor eine VM oder ein Container verändert wird, muss der Hostzustand kontrolliert werden.

| Prüfbereich | Typische Auswirkung |
|---|---|
| CPU-Auslastung | VMs und Container reagieren langsam |
| RAM-Auslastung | OOM-Ereignisse, Swapping oder VM-Startfehler |
| Speicherplatz | Images, Snapshots und virtuelle Datenträger können nicht wachsen |
| Inodes unter Linux | Containerdateien können nicht erstellt werden |
| Storage-Latenz | VMs frieren ein oder Datenbanken werden langsam |
| Netzwerk | Mehrere Gäste verlieren gleichzeitig die Verbindung |
| Zeit | Authentifizierung, Zertifikate und Cluster können fehlschlagen |
| Hypervisordienst | VMs können nicht verwaltet oder gestartet werden |
| Container-Engine | Containerstatus und Netzwerke sind nicht verfügbar |

**Windows-Host**

```powershell
[RO] Get-CimInstance Win32_OperatingSystem |
    Select-Object Caption, Version, BuildNumber,
        FreePhysicalMemory, TotalVisibleMemorySize
```

```powershell
[RO] Get-Volume |
    Select-Object DriveLetter, FileSystemLabel,
        HealthStatus, SizeRemaining, Size
```

```powershell
[RO] Get-Counter `
    '\Processor(_Total)\% Processor Time',
    '\Memory\Available MBytes'
```

**Linux-Host**

```bash
[RO] uptime
```

```bash
[RO] free -h
```

```bash
[RO] df -hT
```

```bash
[RO] df -i
```

```bash
[RO] lsblk -f
```

```bash
[RO] vmstat 1 5
```

**macOS-Host**

```bash
[RO] uptime
```

```bash
[RO] vm_stat
```

```bash
[RO] df -h
```

```bash
[RO] diskutil list
```

</details>

<details>
<summary><strong>4. Hyper-V-Host und virtuelle Maschinen prüfen</strong></summary>

Die Hyper-V-PowerShell-Befehle sind nur verfügbar, wenn die Hyper-V-Verwaltungstools installiert sind.

**Hyper-V-Hostinformationen anzeigen**

```powershell
[RO][PRIV] Get-VMHost |
    Select-Object Name, LogicalProcessorCount,
        MemoryCapacity, VirtualMachinePath,
        VirtualHardDiskPath
```

**Alle virtuellen Maschinen anzeigen**

```powershell
[RO][PRIV] Get-VM |
    Select-Object Name, State, Status, CPUUsage,
        MemoryAssigned, Uptime, Version
```

**Bestimmte VM anzeigen**

```powershell
[RO][PRIV] Get-VM -Name "<VM-NAME>" |
    Format-List *
```

Die vollständige Ausgabe kann sehr umfangreich sein.

**Nur nicht normal laufende VMs anzeigen**

```powershell
[RO][PRIV] Get-VM |
    Where-Object {
        $_.State -ne 'Running' -or $_.Status -ne 'Operating normally'
    } |
    Select-Object Name, State, Status
```

**Wichtige VM-Zustände**

| Zustand | Bedeutung |
|---|---|
| `Running` | VM ist eingeschaltet |
| `Off` | VM ist ausgeschaltet |
| `Paused` | Ausführung wurde angehalten |
| `Saved` | VM-Zustand wurde gespeichert |
| `Starting` | VM wird gestartet |
| `Stopping` | VM wird beendet |
| `Saving` | Zustand wird gespeichert |
| `Critical` im Status | Hyper-V meldet einen kritischen Zustand |

> Ein Zustand `Running` sagt nichts darüber aus, ob das Gastbetriebssystem vollständig gestartet oder ein Dienst erreichbar ist.

</details>

<details>
<summary><strong>5. Hyper-V-Arbeitsspeicher und CPU prüfen</strong></summary>

**VM-Arbeitsspeicher anzeigen**

```powershell
[RO][PRIV] Get-VMMemory -VMName "<VM-NAME>" |
    Select-Object VMName, DynamicMemoryEnabled,
        Startup, Minimum, Maximum, Buffer,
        Priority
```

**Speicherzuweisung aller VMs anzeigen**

```powershell
[RO][PRIV] Get-VM |
    Select-Object Name, State,
        @{Name='MemoryAssigned_GB';Expression={
            [math]::Round($_.MemoryAssigned / 1GB, 2)
        }},
        CPUUsage, Uptime
```

**Prozessorausweisung einer VM anzeigen**

```powershell
[RO][PRIV] Get-VMProcessor -VMName "<VM-NAME>" |
    Select-Object VMName, Count, Reserve,
        Maximum, RelativeWeight, CompatibilityForMigrationEnabled
```

**Typische Ressourcenprobleme**

- Der Host besitzt nicht genügend verfügbaren RAM zum Starten einer VM.
- Zu viele virtuelle CPUs wurden vergeben.
- Dynamischer Arbeitsspeicher erreicht sein Maximum.
- Gastbetriebssystem oder Anwendung benötigt mehr Startspeicher.
- Host führt gleichzeitig speicherintensive Sicherungs- oder Scanvorgänge aus.
- Mehrere VMs konkurrieren um dieselben physischen Ressourcen.
- NUMA- oder CPU-Kompatibilitätsanforderungen verhindern eine Migration.
- Ein Gast verbraucht RAM, ohne ihn an den Host zurückzugeben.

**Zusätzlich innerhalb der VM prüfen**

Windows-Gast:

```powershell
[RO] Get-Counter `
    '\Processor(_Total)\% Processor Time',
    '\Memory\Available MBytes'
```

Linux-Gast:

```bash
[RO] free -h
```

```bash
[RO] vmstat 1 5
```

</details>

<details>
<summary><strong>6. Hyper-V-Netzwerk untersuchen</strong></summary>

**Virtuelle Switches anzeigen**

```powershell
[RO][PRIV] Get-VMSwitch |
    Select-Object Name, SwitchType, NetAdapterInterfaceDescription
```

**Virtuelle Netzwerkadapter einer VM anzeigen**

```powershell
[RO][PRIV] Get-VMNetworkAdapter -VMName "<VM-NAME>" |
    Select-Object VMName, Name, SwitchName,
        Status, MacAddress, IPAddresses
```

**Alle VM-Netzwerkadapter anzeigen**

```powershell
[RO][PRIV] Get-VMNetworkAdapter -All |
    Select-Object VMName, Name, SwitchName,
        Status, MacAddress, IPAddresses
```

**VLAN-Konfiguration anzeigen**

```powershell
[RO][PRIV] Get-VMNetworkAdapterVlan -VMName "<VM-NAME>"
```

**Erweiterte Adapterfunktionen anzeigen**

```powershell
[RO][PRIV] Get-VMNetworkAdapterAdvancedFeature `
    -VMName "<VM-NAME>"
```

**Typische Ursachen**

- VM ist mit dem falschen virtuellen Switch verbunden.
- Switch wurde gelöscht oder umbenannt.
- VLAN-ID stimmt nicht.
- Physischer Hostadapter ist getrennt.
- MAC-Adresse wird durch Port-Security blockiert.
- Statische IP-Adresse im Gast ist falsch.
- DHCP ist im virtuellen Netzwerk nicht erreichbar.
- Eine Hostfirewall blockiert Management- oder Gastverkehr.
- Virtueller Switch besitzt den falschen Typ.

**Hyper-V-Switchtypen**

| Typ | Verbindung |
|---|---|
| External | Verbindung zum physischen Netzwerk |
| Internal | Kommunikation zwischen Host und VMs |
| Private | Kommunikation nur zwischen VMs desselben Hosts |

</details>

<details>
<summary><strong>7. Hyper-V-Datenträger und Checkpoints prüfen</strong></summary>

**Virtuelle Festplatten einer VM anzeigen**

```powershell
[RO][PRIV] Get-VMHardDiskDrive -VMName "<VM-NAME>" |
    Select-Object VMName, ControllerType,
        ControllerNumber, ControllerLocation, Path
```

**Informationen über eine bekannte VHD- oder VHDX-Datei**

```powershell
[RO][PRIV][SENS] Get-VHD -Path "<VHDX-PFAD>" |
    Select-Object Path, VhdFormat, VhdType,
        FileSize, Size, MinimumSize, ParentPath,
        Attached
```

**Checkpoints einer VM anzeigen**

```powershell
[RO][PRIV] Get-VMSnapshot -VMName "<VM-NAME>" |
    Select-Object VMName, Name, SnapshotType,
        CreationTime, ParentSnapshotName
```

**Checkpoints aller VMs anzeigen**

```powershell
[RO][PRIV] Get-VM |
    Get-VMSnapshot |
    Select-Object VMName, Name, SnapshotType,
        CreationTime
```

**Speicherpfade und freien Speicher vergleichen**

```powershell
[RO] Get-Volume |
    Select-Object DriveLetter, FileSystemLabel,
        HealthStatus, SizeRemaining, Size
```

**Typische Ursachen**

- VHDX-Datei fehlt oder wurde verschoben.
- Berechtigungen auf dem Speicherpfad fehlen.
- Ein differenzierender Datenträger findet seinen Parent nicht.
- Snapshot- beziehungsweise AVHDX-Dateien wachsen stark.
- Das Hostvolume ist voll.
- Ein Cluster Shared Volume ist nicht verfügbar.
- SAN-, NAS- oder SMB-Speicher ist nicht erreichbar.
- VHDX ist bereits anderweitig eingebunden.
- Dateisystem oder physischer Datenträger meldet Fehler.

> AVHDX-Dateien und Snapshotketten dürfen nicht manuell im Dateisystem gelöscht oder umbenannt werden. Dadurch kann die virtuelle Festplattenkette unbrauchbar werden.

</details>

<details>
<summary><strong>8. Hyper-V-Integrationsdienste und Ereignisprotokolle prüfen</strong></summary>

**Integrationsdienste einer VM anzeigen**

```powershell
[RO][PRIV] Get-VMIntegrationService -VMName "<VM-NAME>" |
    Select-Object Name, Enabled, PrimaryStatusDescription,
        SecondaryStatusDescription
```

**Hyper-V-VMMS-Ereignisse**

```powershell
[RO][SENS] Get-WinEvent -LogName `
    'Microsoft-Windows-Hyper-V-VMMS-Admin' `
    -ErrorAction SilentlyContinue |
Select-Object -First 100 TimeCreated, LevelDisplayName, Id, Message
```

**Hyper-V-Worker-Ereignisse**

```powershell
[RO][SENS] Get-WinEvent -LogName `
    'Microsoft-Windows-Hyper-V-Worker-Admin' `
    -ErrorAction SilentlyContinue |
Select-Object -First 100 TimeCreated, LevelDisplayName, Id, Message
```

**Nur Ereignisse der letzten 24 Stunden**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = 'Microsoft-Windows-Hyper-V-VMMS-Admin'
    StartTime = (Get-Date).AddHours(-24)
} -ErrorAction SilentlyContinue |
Select-Object TimeCreated, LevelDisplayName, Id, Message
```

**Typische Meldungsbereiche**

- Startfehler
- Arbeitsspeicher konnte nicht reserviert werden
- Virtuelle Festplatte nicht gefunden
- Zugriff auf Speicherpfad verweigert
- Virtueller Switch nicht vorhanden
- Checkpoint konnte nicht erstellt oder zusammengeführt werden
- Migration fehlgeschlagen
- Konfigurationsversion nicht unterstützt
- Integrationsdienst nicht verfügbar

</details>

<details>
<summary><strong>9. KVM und libvirt unter Linux prüfen</strong></summary>

**Alle libvirt-VMs anzeigen**

```bash
[RO][PRIV] sudo virsh list --all
```

**Status einer VM**

```bash
[RO][PRIV] sudo virsh domstate "<VM-NAME>"
```

**Ausführliche VM-Informationen**

```bash
[RO][PRIV][SENS] sudo virsh dominfo "<VM-NAME>"
```

**Virtuelle Netzwerkadapter**

```bash
[RO][PRIV][SENS] sudo virsh domiflist "<VM-NAME>"
```

**Virtuelle Datenträger**

```bash
[RO][PRIV][SENS] sudo virsh domblklist "<VM-NAME>" --details
```

**VM-Ressourcenstatistik**

```bash
[TEST][PRIV][SENS] sudo virsh domstats "<VM-NAME>"
```

**Snapshots anzeigen**

```bash
[RO][PRIV] sudo virsh snapshot-list "<VM-NAME>"
```

**Virtuelle Netzwerke anzeigen**

```bash
[RO][PRIV] sudo virsh net-list --all
```

**Storage-Pools anzeigen**

```bash
[RO][PRIV] sudo virsh pool-list --all
```

**Storage-Volumes eines Pools anzeigen**

```bash
[RO][PRIV][SENS] sudo virsh vol-list "<POOL-NAME>"
```

> `virsh` kann je nach Verbindung auf eine lokale oder entfernte libvirt-Instanz zugreifen. Vor Änderungen muss geprüft werden, welche Verbindung und welcher Host tatsächlich verwendet werden.

</details>

<details>
<summary><strong>10. KVM-, QEMU- und libvirt-Dienste untersuchen</strong></summary>

Je nach Distribution und libvirt-Version können unterschiedliche Dienste verwendet werden.

**Klassischer libvirt-Dienst**

```bash
[RO] systemctl status libvirtd --no-pager
```

**Modularer QEMU-Dienst**

```bash
[RO] systemctl status virtqemud --no-pager
```

**Laufende QEMU-Prozesse anzeigen**

```bash
[RO][SENS] ps -ef | grep '[q]emu-system'
```

**libvirt-Protokolle**

```bash
[RO][PRIV][SENS] sudo journalctl -u libvirtd \
    --since "-24 hours" --no-pager
```

**virtqemud-Protokolle**

```bash
[RO][PRIV][SENS] sudo journalctl -u virtqemud \
    --since "-24 hours" --no-pager
```

**Kernelunterstützung prüfen**

```bash
[RO] lsmod | grep -E '^kvm|kvm_'
```

**CPU-Virtualisierungsmerkmale anzeigen**

```bash
[RO] lscpu |
    grep -E 'Virtualization|Hypervisor|Architecture'
```

**KVM-Gerät prüfen**

```bash
[RO][FILE] ls -l /dev/kvm
```

**Typische Ursachen**

- Virtualisierung ist in BIOS beziehungsweise UEFI deaktiviert.
- `/dev/kvm` fehlt oder besitzt falsche Berechtigungen.
- libvirt-Dienst ist nicht aktiv.
- VM-Konfiguration verweist auf fehlende Datenträger.
- Storage-Pool ist nicht aktiv.
- Virtuelles Netzwerk ist nicht aktiv.
- AppArmor oder SELinux blockiert den Zugriff.
- QEMU-Version unterstützt eine Geräteoption nicht.
- CPU-Modell ist nach einer Migration nicht kompatibel.
- Host besitzt nicht genügend RAM.

</details>

<details>
<summary><strong>11. VMware und andere Hypervisoren systematisch eingrenzen</strong></summary>

Die genauen Befehle hängen von Produkt, Version und Managementplattform ab. Ohne bestätigte Plattform sollten keine produktspezifischen Befehle übernommen werden.

**Zu prüfende Bereiche**

- Hostverbindungsstatus
- VM-Energiezustand
- Hostressourcen
- Datastore-Kapazität
- Snapshotstatus
- Virtuelle Switches und Portgruppen
- VLAN-Zuordnung
- Virtuelle Netzwerkkarten
- Virtuelle Datenträger
- VMware Tools beziehungsweise Gasterweiterungen
- HA- und Clusterstatus
- vMotion- beziehungsweise Migrationsereignisse
- Alarme und Aufgabenverlauf
- Lizenz- und Zertifikatsstatus
- Managementserver-Verbindung

**Typische Fehler**

| Beobachtung | Mögliche Ursache |
|---|---|
| VM ist „orphaned“ oder „inaccessible“ | Konfigurationsdatei oder Datastore nicht erreichbar |
| Snapshot kann nicht erstellt werden | Datastore voll oder Snapshotkette fehlerhaft |
| Migration scheitert | CPU, Netzwerk, Storage oder Kompatibilität |
| VM-Netzwerk fehlt | Portgruppe oder virtueller Switch falsch |
| Konsole funktioniert, Netzwerk nicht | Gastnetzwerk, VLAN oder Portgruppe |
| Mehrere Hosts nicht verwaltbar | Managementserver, Zertifikat oder Netzwerk |
| HA startet VM nicht | Clusterkapazität, Admission Control oder Storage |
| Tools-Status veraltet | Gasterweiterungen fehlen oder sind inkompatibel |

> Änderungen an Datastore-Dateien dürfen nur mit dokumentierten Herstellerverfahren durchgeführt werden.

</details>

<details>
<summary><strong>12. Docker-Client und Docker-Daemon unterscheiden</strong></summary>

Docker besteht mindestens aus:

- Docker-Client
- Docker-Daemon beziehungsweise Engine
- Container Runtime
- Images
- Container
- Netzwerke
- Volumes

Der Client kann installiert sein, obwohl der Daemon nicht erreichbar ist.

**Client- und Serverversion anzeigen**

```bash
[RO] docker version
```

Wenn nur der Clientbereich erscheint und der Serverbereich einen Fehler meldet, kann der Docker-Daemon nicht erreicht werden.

**Ausführliche Docker-Informationen**

```bash
[RO][SENS] docker info
```

Die Ausgabe kann enthalten:

- Hostname
- Betriebssystem
- Kernelversion
- Storage-Treiber
- Anzahl der Container und Images
- Netzwerk-Plugins
- Registryinformationen
- Sicherheitsoptionen
- Docker-Root-Verzeichnis
- Proxyinformationen

**Docker-Kontext anzeigen**

```bash
[RO][SENS] docker context show
```

**Alle Docker-Kontexte anzeigen**

```bash
[RO][SENS] docker context ls
```

> Ein falscher Docker-Kontext kann dazu führen, dass Befehle gegen einen anderen Host oder Docker Desktop statt gegen die erwartete Engine ausgeführt werden.

</details>

<details>
<summary><strong>13. Docker-Dienst unter Linux prüfen</strong></summary>

**Docker-Dienststatus**

```bash
[RO] systemctl status docker --no-pager
```

**Container-Runtime prüfen**

```bash
[RO] systemctl status containerd --no-pager
```

**Docker-Protokolle der letzten 24 Stunden**

```bash
[RO][PRIV][SENS] sudo journalctl -u docker \
    --since "-24 hours" --no-pager
```

**containerd-Protokolle**

```bash
[RO][PRIV][SENS] sudo journalctl -u containerd \
    --since "-24 hours" --no-pager
```

**Docker-Socket prüfen**

```bash
[RO][FILE] ls -l /var/run/docker.sock
```

**Typische Fehlermeldungen**

| Meldung | Mögliche Ursache |
|---|---|
| `Cannot connect to the Docker daemon` | Daemon gestoppt, falscher Socket oder falscher Kontext |
| `permission denied` am Socket | Benutzer besitzt keine erforderliche Berechtigung |
| `no space left on device` | Speicherplatz oder Inodes ausgeschöpft |
| `address already in use` | Hostport bereits belegt |
| `network not found` | Konfiguriertes Docker-Netzwerk fehlt |
| `volume not found` | Extern erwartetes Volume fehlt |
| `manifest unknown` | Image oder Tag existiert nicht |
| `no matching manifest` | Architektur oder Plattform wird nicht angeboten |
| `pull access denied` | Registry, Anmeldung oder Berechtigung |
| `toomanyrequests` | Registry-Limit erreicht |

</details>

<details>
<summary><strong>14. Containerstatus und Exit-Code prüfen</strong></summary>

**Laufende Container anzeigen**

```bash
[RO][SENS] docker ps
```

**Alle Container einschließlich beendeter Container**

```bash
[RO][SENS] docker ps -a
```

**Kompakte Zustandsübersicht**

```bash
[RO][SENS] docker ps -a \
    --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'
```

**Zustand eines Containers detailliert anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format '{{json .State}}'
```

**Wichtige Zustandsinformationen gezielt anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format 'Status={{.State.Status}} ExitCode={{.State.ExitCode}} OOMKilled={{.State.OOMKilled}} Error={{.State.Error}} StartedAt={{.State.StartedAt}} FinishedAt={{.State.FinishedAt}}'
```

**Neustartzähler anzeigen**

```bash
[RO] docker inspect "<CONTAINER>" \
    --format 'RestartCount={{.RestartCount}}'
```

**Typische Exit-Codes**

| Exit-Code | Typische Bedeutung |
|---|---|
| `0` | Prozess wurde erfolgreich beendet |
| `1` | Allgemeiner Anwendungsfehler |
| `2` | Häufig falsche Argumente oder Anwendungsfehler |
| `125` | Docker konnte den Container nicht starten |
| `126` | Befehl gefunden, aber nicht ausführbar |
| `127` | Befehl nicht gefunden |
| `137` | Prozess erhielt häufig `SIGKILL`; OOM oder erzwungenes Beenden möglich |
| `139` | Segmentation Fault möglich |
| `143` | Prozess erhielt normalerweise `SIGTERM` |

> Ein Exit-Code beschreibt zunächst nur das Ende des Hauptprozesses. Die genaue Ursache muss mit Containerprotokoll, Docker-Ereignissen und Hostmeldungen bestätigt werden.

</details>

<details>
<summary><strong>15. Containerprotokolle sicher auswerten</strong></summary>

**Letzte 100 Protokollzeilen**

```bash
[RO][SENS] docker logs --tail 100 "<CONTAINER>"
```

**Protokolle mit Zeitstempeln**

```bash
[RO][SENS] docker logs --timestamps --tail 100 "<CONTAINER>"
```

**Protokolle seit einem bestimmten Zeitraum**

```bash
[RO][SENS] docker logs --since 1h "<CONTAINER>"
```

**Protokolle fortlaufend beobachten**

```bash
[TEST][SENS] docker logs --follow --tail 100 "<CONTAINER>"
```

Die fortlaufende Ausgabe wird mit `Strg` + `C` beendet. Dadurch wird normalerweise nicht der Container beendet, sondern nur die lokale Anzeige.

**Wichtige Einschränkungen**

- `docker logs` funktioniert abhängig vom verwendeten Logging-Treiber.
- Anwendungen können zusätzlich in Dateien, Datenbanken oder externe Systeme protokollieren.
- Protokolle können Passwörter, Tokens, URLs, Benutzernamen oder personenbezogene Daten enthalten.
- Unbegrenzte Logabfragen können sehr große Datenmengen ausgeben.
- Fehlende Ausgabe bedeutet nicht automatisch, dass kein Fehler vorhanden ist.
- Ein Container kann bereits vor Initialisierung der Anwendungsprotokollierung beendet werden.

</details>

<details>
<summary><strong>16. Healthcheck und Anwendungszustand prüfen</strong></summary>

Ein Docker-Healthcheck bewertet einen im Image oder Container definierten Test.

**Healthcheckstatus anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format '{{json .State.Health}}'
```

**Kompakte Anzeige**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format 'Status={{.State.Status}} Health={{if .State.Health}}{{.State.Health.Status}}{{else}}nicht definiert{{end}}'
```

**Healthcheck-Konfiguration anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format '{{json .Config.Healthcheck}}'
```

**Mögliche Health-Zustände**

| Zustand | Bedeutung |
|---|---|
| `starting` | Startphase oder noch nicht genügend Prüfungen |
| `healthy` | Definierter Test war erfolgreich |
| `unhealthy` | Definierter Test ist wiederholt fehlgeschlagen |
| Nicht vorhanden | Kein Docker-Healthcheck definiert |

**Wichtige Bewertung**

- `healthy` bestätigt nur den definierten Test.
- Ein zu einfacher Test kann echte Fehler übersehen.
- Ein zu strenger Test kann einen funktionierenden Dienst als fehlerhaft markieren.
- Der Test kann von Werkzeugen abhängen, die im Image fehlen.
- Ein Healthcheck kann intern funktionieren, obwohl der Dienst extern nicht erreichbar ist.
- Ein Container kann `Up` sein und trotzdem `unhealthy`.

</details>

<details>
<summary><strong>17. Containerressourcen und OOM-Fehler untersuchen</strong></summary>

**Aktuelle Ressourcennutzung einmalig anzeigen**

```bash
[TEST][SENS] docker stats --no-stream
```

**Nur einen Container anzeigen**

```bash
[TEST][SENS] docker stats --no-stream "<CONTAINER>"
```

**Konfigurierte Ressourcenlimits anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format 'Memory={{.HostConfig.Memory}} MemorySwap={{.HostConfig.MemorySwap}} NanoCPUs={{.HostConfig.NanoCpus}} PidsLimit={{.HostConfig.PidsLimit}}'
```

**Prüfen, ob der Container wegen Speichermangel beendet wurde**

```bash
[RO] docker inspect "<CONTAINER>" \
    --format 'OOMKilled={{.State.OOMKilled}} ExitCode={{.State.ExitCode}}'
```

**Linux-Kernelmeldungen zu OOM**

```bash
[RO][PRIV][SENS] sudo journalctl -k -b --no-pager |
    grep -Ei 'out of memory|oom-kill|killed process'
```

**Typische Ursachen**

- Container besitzt ein zu niedriges Speicherlimit.
- Host besitzt keinen freien Arbeitsspeicher.
- Anwendung besitzt ein Speicherleck.
- Java-, Node.js- oder Datenbankkonfiguration ignoriert die Containergrenze.
- Zu viele Prozesse erreichen das PID-Limit.
- Hohe I/O-Wartezeit wird als CPU- oder Anwendungsproblem fehlinterpretiert.
- Ein Container konkurriert ohne Limits mit anderen Workloads.

> Ein höheres Speicherlimit behebt kein Speicherleck. Zuerst müssen Verbrauch, Wachstum und Anwendungsprotokolle untersucht werden.

</details>

<details>
<summary><strong>18. Docker-Prozesse und Hauptprozess prüfen</strong></summary>

**Prozesse im Container anzeigen**

```bash
[RO][SENS] docker top "<CONTAINER>"
```

**Konfigurierten Startbefehl anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format 'Entrypoint={{json .Config.Entrypoint}} Cmd={{json .Config.Cmd}}'
```

**Arbeitsverzeichnis und Benutzer anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format 'User={{.Config.User}} WorkingDir={{.Config.WorkingDir}}'
```

**Typische Ursachen eines sofortigen Containerendes**

- Hauptprozess beendet sich regulär.
- Startbefehl oder Entrypoint ist falsch.
- Binärdatei oder Skript fehlt.
- Datei besitzt keine Ausführungsberechtigung.
- Konfigurationsdatei fehlt.
- Umgebungsvariable ist nicht gesetzt.
- Abhängiger Dienst ist noch nicht erreichbar.
- Datenbankmigration schlägt fehl.
- Architektur des Images passt nicht zum Host.
- Anwendung läuft als falscher Benutzer.
- Gemountete Datei verdeckt eine Datei aus dem Image.

> Ein Container bleibt nur so lange aktiv, wie sein Hauptprozess läuft. Das erfolgreiche Erstellen des Containers bedeutet nicht, dass dieser Prozess dauerhaft läuft.

</details>

<details>
<summary><strong>19. Docker-Portveröffentlichungen und Listener prüfen</strong></summary>

**Portzuordnungen aller Container**

```bash
[RO][SENS] docker ps \
    --format 'table {{.Names}}\t{{.Ports}}'
```

**Portzuordnung eines Containers**

```bash
[RO][SENS] docker port "<CONTAINER>"
```

**Detaillierte Portkonfiguration**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format '{{json .NetworkSettings.Ports}}'
```

**Listener auf dem Linux-Host**

```bash
[RO][PRIV][SENS] sudo ss -lntup
```

**Listener auf Windows**

```powershell
[RO][PRIV][SENS] Get-NetTCPConnection -State Listen |
    Sort-Object LocalPort |
    Select-Object LocalAddress, LocalPort, OwningProcess
```

**Listener auf macOS**

```bash
[RO][PRIV][SENS] sudo lsof -nP -iTCP -sTCP:LISTEN
```

**Wichtige Unterscheidung**

```text
Client
  │
  ▼
Host-IP:Hostport
  │
Portveröffentlichung
  ▼
Container-IP:Containerport
  │
  ▼
Anwendungslistener
```

Ein Fehler kann an jeder Stelle liegen.

**Typische Ursachen**

- Kein Hostport wurde veröffentlicht.
- Falscher Containerport wurde eingetragen.
- Anwendung lauscht auf einem anderen Port.
- Anwendung bindet nur an `127.0.0.1` im Container.
- Hostport wird bereits verwendet.
- Hostfirewall blockiert den Port.
- Reverse Proxy zeigt auf den falschen Hostnamen oder Port.
- Anwendung startet erst nach längerer Initialisierung.
- IPv4- und IPv6-Bindung werden verwechselt.

</details>

<details>
<summary><strong>20. Docker-Netzwerke und DNS untersuchen</strong></summary>

**Docker-Netzwerke anzeigen**

```bash
[RO][SENS] docker network ls
```

**Netzwerkdetails anzeigen**

```bash
[RO][SENS] docker network inspect "<NETZWERK>"
```

Die Ausgabe kann Container-IP-Adressen, Netzwerknamen und weitere interne Informationen enthalten.

**Netzwerke eines Containers anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format '{{json .NetworkSettings.Networks}}'
```

**DNS-Konfiguration im Container anzeigen**

```bash
[RO][SENS] docker exec "<CONTAINER>" cat /etc/resolv.conf
```

Der Befehl funktioniert nur, wenn der Container läuft und `cat` im Image vorhanden ist.

**Namensauflösung im Container testen**

```bash
[TEST][SENS] docker exec "<CONTAINER>" \
    getent hosts "<ZIELNAME>"
```

`getent` ist nicht in jedem Container-Image vorhanden.

**TCP-Verbindung aus einem Container testen**

```bash
[TEST][SENS] docker exec "<CONTAINER>" \
    curl -v --connect-timeout 5 "http://<ZIEL>:<PORT>/"
```

`curl` ist nicht in jedem Image installiert. Fehlende Diagnosewerkzeuge dürfen nicht unkontrolliert in einen Produktivcontainer installiert werden.

**Typische Ursachen**

- Container befinden sich in unterschiedlichen Netzwerken.
- Falscher DNS-Name wird verwendet.
- Dienstname stimmt nicht mit Compose-Konfiguration überein.
- Anwendung nutzt `localhost` für einen anderen Container.
- Netzwerk wurde nach Containererstellung geändert.
- DNS-Server des Hosts ist nicht erreichbar.
- Überschneidende IP-Netze verursachen falsche Routen.
- VPN kollidiert mit dem Docker-Adressbereich.
- Firewall oder Forwardingregel blockiert den Verkehr.

> `localhost` innerhalb eines Containers bezeichnet normalerweise den Container selbst und nicht den Docker-Host oder einen anderen Container.

</details>

<details>
<summary><strong>21. Docker-Volumes und Bind-Mounts untersuchen</strong></summary>

**Volumes anzeigen**

```bash
[RO][SENS] docker volume ls
```

**Volumeinformationen anzeigen**

```bash
[RO][SENS] docker volume inspect "<VOLUME>"
```

**Mounts eines Containers anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format '{{json .Mounts}}'
```

**Kompakte Mountübersicht**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format '{{range .Mounts}}{{println .Type .Source "->" .Destination "RW=" .RW}}{{end}}'
```

**Speicherverbrauch der Docker-Objekte**

```bash
[TEST][SENS] docker system df
```

Ausführlich:

```bash
[TEST][SENS] docker system df -v
```

**Typische Ursachen fehlender Daten**

- Falsches Volume wurde eingebunden.
- Volume wurde unter einem neuen Projektnamen erstellt.
- Bind-Mount verweist auf einen falschen Hostpfad.
- Ein leerer Hostpfad verdeckt vorhandene Image-Daten.
- Anwendung schreibt außerhalb des vorgesehenen Mountpoints.
- Container läuft als Benutzer ohne Schreibberechtigung.
- Volume wurde versehentlich entfernt.
- NFS-, SMB- oder Netzwerkspeicher ist nicht verfügbar.
- SELinux verhindert den Zugriff.
- Datenträger des Docker-Hosts ist voll.
- Bei Docker Desktop wurde die Dateifreigabe oder virtuelle Storage-Schicht gestört.

> `docker volume prune` und `docker system prune` dürfen nicht als allgemeine Fehlerbehebung ausgeführt werden. Sie können nicht verwendete, aber weiterhin benötigte Daten oder Images entfernen.

</details>

<details>
<summary><strong>22. Docker-Images und Architektur prüfen</strong></summary>

**Lokale Images anzeigen**

```bash
[RO][SENS] docker image ls
```

**Imageinformationen anzeigen**

```bash
[RO][SENS] docker image inspect "<IMAGE>:<TAG>"
```

**Architektur eines lokalen Images**

```bash
[RO] docker image inspect "<IMAGE>:<TAG>" \
    --format 'OS={{.Os}} Architecture={{.Architecture}}'
```

**Hostarchitektur**

Linux:

```bash
[RO] uname -m
```

macOS:

```bash
[RO] uname -m
```

Windows:

```powershell
[RO] Get-CimInstance Win32_OperatingSystem |
    Select-Object OSArchitecture
```

**Typische Fehlermeldungen**

| Meldung | Mögliche Ursache |
|---|---|
| `no matching manifest` | Image unterstützt die Hostplattform nicht |
| `exec format error` | Binärdatei besitzt falsche Architektur oder fehlerhaften Interpreter |
| `manifest unknown` | Tag oder Image existiert nicht |
| `pull access denied` | Privates Image oder falscher Name |
| `unauthorized` | Registryanmeldung oder Berechtigung fehlt |
| `certificate signed by unknown authority` | Registryzertifikat wird nicht vertraut |
| `unexpected EOF` | Download oder Netzwerkverbindung abgebrochen |

**Multi-Architektur-Images**

Ein Image-Tag kann verschiedene plattformspezifische Manifestvarianten enthalten. Deshalb muss geprüft werden, ob genau die benötigte Kombination aus Betriebssystem und Architektur angeboten wird.

</details>

<details>
<summary><strong>23. Umgebungsvariablen und Geheimnisse prüfen</strong></summary>

**Konfigurierte Containerumgebung anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format '{{range .Config.Env}}{{println .}}{{end}}'
```

> Diese Ausgabe kann Passwörter, Tokens, API-Schlüssel und Datenbankzugänge enthalten. Sie darf nicht unredigiert in Tickets, Dokumentationen oder externe Systeme kopiert werden.

**Nur Namen der Umgebungsvariablen anzeigen**

```bash
[RO][SENS] docker inspect "<CONTAINER>" \
    --format '{{range .Config.Env}}{{println .}}{{end}}' |
    sed 's/=.*$/=<REDACTED>/'
```

**Typische Fehler**

- Pflichtvariable fehlt.
- Variablenname ist falsch geschrieben.
- Wert enthält unbeabsichtigte Leerzeichen.
- Sonderzeichen wurden durch Shell oder Compose interpretiert.
- Datenbankhostname zeigt auf `localhost`.
- Portnummer ist falsch.
- Geheimnis wurde rotiert, Container aber nicht neu erstellt.
- `.env`-Datei wurde aus einem anderen Verzeichnis geladen.
- Compose-Projekt verwendet eine andere Konfigurationsdatei.
- Variable ist im Image festgelegt und wird unerwartet überschrieben.

**Sicherheitsregel**

Geheimnisse sollten nicht dauerhaft als Klartext in:

- Screenshots
- Tickets
- BookStack-Seiten
- Chatverläufen
- öffentlichen Repositories
- ungeschützten Diagnoseberichten

gespeichert werden.

</details>

<details>
<summary><strong>24. Docker-Compose-Projekte untersuchen</strong></summary>

Je nach Installation wird das aktuelle Plugin mit `docker compose` verwendet. Ältere Systeme können noch das separate Werkzeug `docker-compose` besitzen.

**Projektstatus anzeigen**

```bash
[RO][SENS] docker compose ps -a
```

**Compose-Prozesse anzeigen**

```bash
[RO][SENS] docker compose top
```

**Letzte Protokollzeilen aller Dienste**

```bash
[RO][SENS] docker compose logs --tail 100
```

**Protokoll eines Dienstes**

```bash
[RO][SENS] docker compose logs --tail 100 "<DIENST>"
```

**Zusammengeführte Konfiguration prüfen**

```bash
[RO][SENS] docker compose config
```

> `docker compose config` kann aufgelöste Umgebungsvariablen und sensible Werte enthalten. Die Ausgabe muss vor Weitergabe redigiert werden.

**Dienste der Konfiguration anzeigen**

```bash
[RO] docker compose config --services
```

**Images der Konfiguration anzeigen**

```bash
[RO][SENS] docker compose config --images
```

**Typische Compose-Fehler**

- Befehl wird im falschen Verzeichnis ausgeführt.
- Falsche Compose-Datei wird verwendet.
- Projektname hat sich geändert.
- Externes Netzwerk oder Volume fehlt.
- `.env`-Datei fehlt.
- Variable wurde nicht ersetzt.
- Abhängiger Dienst ist gestartet, aber noch nicht betriebsbereit.
- Port ist bereits belegt.
- Bind-Mount-Pfad existiert auf dem Host nicht.
- Image-Tag zeigt inzwischen auf eine andere Version.
- Mehrere Compose-Dateien überschreiben sich unerwartet.

</details>

<details>
<summary><strong>25. Docker-Ereignisse und Neustartschleifen untersuchen</strong></summary>

**Ereignisse der letzten Stunde**

```bash
[RO][SENS] docker events --since 1h
```

Der Befehl wartet nach Ausgabe vorhandener Ereignisse auf neue Ereignisse und wird mit `Strg` + `C` beendet.

**Ereignisse eines Containers**

```bash
[RO][SENS] docker events \
    --since 1h \
    --filter container="<CONTAINER>"
```

**Nur bestimmte Ereignistypen**

```bash
[RO][SENS] docker events \
    --since 1h \
    --filter container="<CONTAINER>" \
    --filter event=die
```

**Neustartrichtlinie anzeigen**

```bash
[RO] docker inspect "<CONTAINER>" \
    --format '{{json .HostConfig.RestartPolicy}}'
```

**Typische Neustartrichtlinien**

| Richtlinie | Verhalten |
|---|---|
| `no` | Kein automatischer Neustart |
| `always` | Container wird grundsätzlich neu gestartet |
| `unless-stopped` | Neustart, außer er wurde ausdrücklich beendet |
| `on-failure` | Neustart bei fehlerhaftem Exit-Code |

Eine Neustartrichtlinie kann die eigentliche Störung verdecken. Der Container erscheint wiederholt kurz als laufend, obwohl der Hauptprozess ständig abstürzt.

**Prüfreihenfolge bei Neustartschleifen**

1. Neustartzähler erfassen.
2. Exit-Code und OOM-Status prüfen.
3. Protokolle mit Zeitstempeln lesen.
4. Startbefehl und Umgebungsvariablen kontrollieren.
5. Mounts und Berechtigungen prüfen.
6. Abhängige Dienste untersuchen.
7. Hostereignisse und Speicherzustand prüfen.
8. Erst danach über Änderungen an der Neustartrichtlinie entscheiden.

</details>

<details>
<summary><strong>26. Docker Desktop unter Windows und macOS eingrenzen</strong></summary>

Docker Desktop führt Linux-Container normalerweise innerhalb einer verwalteten Virtualisierungsumgebung aus. Dadurch existieren zusätzliche Schichten:

```text
Docker-Client
    │
Docker Desktop
    │
Verwaltete Linux-VM beziehungsweise Virtualisierungsschicht
    │
Docker Engine
    │
Container
```

**Plattformübergreifende Prüfungen**

```bash
[RO] docker version
```

```bash
[RO][SENS] docker info
```

```bash
[RO][SENS] docker context ls
```

```bash
[RO][SENS] docker ps -a
```

```bash
[TEST][SENS] docker system df
```

**Zusätzlich unter Windows prüfen**

- Läuft Docker Desktop?
- Wird der erwartete Docker-Kontext verwendet?
- Funktioniert WSL 2, falls dieses Backend verwendet wird?
- Besitzt die virtuelle Docker-Festplatte freien Speicher?
- Sind Unternehmensrichtlinien oder Sicherheitssoftware beteiligt?

**WSL-Status anzeigen**

```powershell
[RO] wsl --status
```

**WSL-Distributionen anzeigen**

```powershell
[RO][SENS] wsl --list --verbose
```

**Zusätzlich unter macOS prüfen**

- Läuft Docker Desktop?
- Ist genügend freier Speicher auf dem Mac vorhanden?
- Wird der erwartete Kontext verwendet?
- Passt das Image zu `arm64` oder `amd64`?
- Sind Bind-Mount-Pfade verfügbar?
- Blockiert eine Sicherheits- oder Netzwerksoftware die Verbindung?
- Ist die virtuelle Docker-Disk ausgelastet?

> Das Beenden oder Zurücksetzen von Docker Desktop kann alle laufenden Container unterbrechen. Ein Factory Reset kann lokale Images, Container, Netzwerke und andere Daten entfernen und darf nicht als allgemeine Diagnosemaßnahme verwendet werden.

</details>

<details>
<summary><strong>27. Podman-Container unter Linux untersuchen</strong></summary>

Podman besitzt viele Docker-ähnliche Befehle, verwendet aber kein identisches Betriebsmodell. Rootless- und Rootful-Container besitzen getrennte Ansichten.

**Container anzeigen**

```bash
[RO][SENS] podman ps -a
```

**Podman-Systeminformationen**

```bash
[RO][SENS] podman info
```

**Containerdetails**

```bash
[RO][SENS] podman inspect "<CONTAINER>"
```

**Protokolle**

```bash
[RO][SENS] podman logs --tail 100 "<CONTAINER>"
```

**Ressourcennutzung**

```bash
[TEST][SENS] podman stats --no-stream
```

**Netzwerke**

```bash
[RO][SENS] podman network ls
```

**Volumes**

```bash
[RO][SENS] podman volume ls
```

**Speicherverbrauch**

```bash
[TEST][SENS] podman system df
```

**Wichtige Besonderheit**

Ein Container, der als normaler Benutzer erstellt wurde, erscheint normalerweise nicht automatisch in der Root-Ansicht:

```bash
[RO][SENS] podman ps -a
```

und:

```bash
[RO][PRIV][SENS] sudo podman ps -a
```

können deshalb unterschiedliche Container anzeigen.

</details>

<details>
<summary><strong>28. Snapshots, Checkpoints und Sicherungen richtig bewerten</strong></summary>

Snapshots und Checkpoints speichern abhängig von der Plattform:

- Datenträgeränderungen
- VM-Konfiguration
- gegebenenfalls Arbeitsspeicherzustand
- Abhängigkeiten zu Parent-Dateien

Sie sind für kurzfristige Rückfallpunkte geeignet, ersetzen aber keine unabhängige Sicherung.

**Risiken lang bestehender Snapshots**

- Stark wachsender Speicherverbrauch
- Zusätzliche I/O-Latenz
- Lange Zusammenführung
- Komplexe Snapshotketten
- Ausfall bei fehlender Parent-Datei
- Datastore oder Hostvolume läuft voll
- Anwendungskonsistenz ist nicht garantiert
- Sicherungssoftware wird beeinträchtigt

**Vor einer Snapshotaktion prüfen**

- Wer hat den Snapshot erstellt?
- Warum wurde er erstellt?
- Wie alt ist er?
- Wie groß ist er?
- Wird er von einer Sicherung verwendet?
- Ist eine Zusammenführung aktiv?
- Ist genügend Speicher für die Zusammenführung vorhanden?
- Ist die Anwendung im Snapshot konsistent?
- Existiert eine unabhängige Sicherung?

> Snapshotdateien niemals manuell löschen. Erstellung, Zusammenführung und Entfernung müssen über das vorgesehene Managementwerkzeug erfolgen.

</details>

<details>
<summary><strong>29. Zeitfehler in virtuellen Systemen untersuchen</strong></summary>

Eine VM kann Zeit aus mehreren Quellen erhalten:

- Hypervisor
- virtuelle Hardwareuhr
- Gastbetriebssystem-Zeitdienst
- Active Directory
- externer NTP-Server

**Windows-Gast**

```cmd
[RO] w32tm /query /source
```

```cmd
[RO] w32tm /query /status
```

**Linux-Gast**

```bash
[RO] timedatectl status
```

```bash
[RO] chronyc tracking
```

falls chrony verwendet wird.

**Typische Ursachen**

- Hypervisor und NTP korrigieren gleichzeitig.
- Hostzeit ist falsch.
- VM wurde aus einem alten Snapshot gestartet.
- VM war lange pausiert.
- Migration verursachte einen Zeitsprung.
- Virtueller Domänencontroller verwendet eine falsche Quelle.
- Gasterweiterungen setzen die Zeit zurück.

Bei Authentifizierungs-, Zertifikats- und Protokollproblemen sollte die Zeit frühzeitig geprüft werden.

</details>

<details>
<summary><strong>30. Kritische Änderungen und gefährliche Schnelllösungen</strong></summary>

Folgende Maßnahmen dürfen nicht unkontrolliert durchgeführt werden:

| Maßnahme | Risiko |
|---|---|
| VM hart ausschalten | Datenverlust und Dateisystemfehler |
| Container mit `kill` beenden | Anwendung erhält keine reguläre Beendigungszeit |
| Docker Factory Reset | Verlust lokaler Docker-Daten |
| `docker system prune` | Entfernt nicht verwendete Docker-Objekte |
| `docker volume prune` | Kann persistente Daten entfernen |
| Snapshotdateien manuell löschen | Virtuelle Datenträgerkette kann unbrauchbar werden |
| VHDX oder QCOW2 während des Betriebs kopieren | Kopie kann inkonsistent sein |
| VM auf Snapshot zurücksetzen | Neuere Daten und Zustände gehen verloren |
| Hypervisordienst neu starten | Mehrere VMs können betroffen sein |
| Netzwerkbrücke oder Switch neu erstellen | Alle verbundenen Gäste können getrennt werden |
| Storage aushängen | VMs und Container verlieren Datenträgerzugriff |
| Rechte auf Docker-Socket weit öffnen | Praktisch administrative Kontrolle über den Host |
| Secrets unredigiert exportieren | Zugangsdaten werden offengelegt |

**Vor einer Änderung erforderlich**

- Exakter Zielhost
- Exakte VM beziehungsweise exakter Container
- Aktueller Zustand
- Abhängige Dienste
- Sicherung
- Wartungsfenster
- Rückfallplan
- Verantwortliche Freigabe
- Funktionsprüfung nach der Änderung

</details>

<details>
<summary><strong>31. Sichere Reihenfolge der Fehleranalyse</strong></summary>

1. Betroffene Anwendung, VM oder Container eindeutig bestimmen.
2. Umfang der Störung feststellen.
3. Host, Hypervisor und Managementzugang prüfen.
4. Hostressourcen und Speicherplatz kontrollieren.
5. VM- beziehungsweise Containerstatus und Startzeit erfassen.
6. Exit-Code, Healthcheck und Ereignisse prüfen.
7. Protokolle zum Fehlerzeitpunkt auswerten.
8. Virtuelles Netzwerk und Portzuordnung untersuchen.
9. Virtuelle Datenträger, Volumes und Mounts kontrollieren.
10. Abhängige Dienste und Namensauflösung prüfen.
11. Ressourcenlimits und OOM-Ereignisse untersuchen.
12. Image-, Versions- und Architekturkompatibilität prüfen.
13. Snapshot-, Migrations- und Änderungsverlauf berücksichtigen.
14. Sicherung und Rückfallplan verifizieren.
15. Erst danach eine Änderung oder einen kontrollierten Neustart durchführen.
16. Anwendung aus interner und externer Sicht testen.
17. Host, VM, Container und Monitoring erneut kontrollieren.
18. Ursache und Maßnahme dokumentieren.

</details>

<details>
<summary><strong>32. Schnelle Befehlsübersicht</strong></summary>

| Aufgabe | Hyper-V | KVM/libvirt | Docker auf Windows, Linux und macOS |
|---|---|---|---|
| Hostinformationen | `[RO][PRIV] Get-VMHost` | Hostbefehle wie `free`, `df`, `uptime` | `[RO][SENS] docker info` |
| Alle Gäste | `[RO][PRIV] Get-VM` | `[RO][PRIV] sudo virsh list --all` | `[RO][SENS] docker ps -a` |
| Gaststatus | `[RO][PRIV] Get-VM -Name "<VM>"` | `[RO][PRIV] sudo virsh domstate "<VM>"` | `[RO] docker inspect "<CONTAINER>" --format '{{json .State}}'` |
| Ressourcen | VM-, Host- und Performance-Counter | `[TEST][PRIV] sudo virsh domstats "<VM>"` | `[TEST] docker stats --no-stream` |
| Netzwerke | `[RO][PRIV] Get-VMSwitch` | `[RO][PRIV] sudo virsh net-list --all` | `[RO] docker network ls` |
| Gastnetzadapter | `[RO][PRIV] Get-VMNetworkAdapter -VMName "<VM>"` | `[RO][PRIV] sudo virsh domiflist "<VM>"` | `[RO] docker inspect "<CONTAINER>" --format '{{json .NetworkSettings.Networks}}'` |
| Datenträger | `[RO][PRIV] Get-VMHardDiskDrive -VMName "<VM>"` | `[RO][PRIV] sudo virsh domblklist "<VM>" --details` | `[RO] docker inspect "<CONTAINER>" --format '{{json .Mounts}}'` |
| Snapshots | `[RO][PRIV] Get-VMSnapshot -VMName "<VM>"` | `[RO][PRIV] sudo virsh snapshot-list "<VM>"` | Nicht direkt vergleichbar |
| Protokolle | Hyper-V-Ereignisprotokolle | Journal und VM-Protokolle | `[RO][SENS] docker logs --tail 100 "<CONTAINER>"` |
| Ereignisse | Windows-Ereignisanzeige | Journal | `[RO][SENS] docker events --since 1h` |
| Ports | Gast und virtuellen Switch prüfen | Gast und Bridge prüfen | `[RO] docker port "<CONTAINER>"` |
| Volumes | VHD/VHDX und Hostvolume | Storage-Pools und Volumes | `[RO] docker volume ls` |
| Speicherverbrauch | Hostvolume und VHDX-Größe | `df`, Pools und Images | `[TEST] docker system df -v` |
| Architektur | Host- und Gastarchitektur | `[RO] uname -m` | `docker image inspect ... --format '{{.Architecture}}'` |
| Healthcheck | Gast- beziehungsweise anwendungsspezifisch | Gast- beziehungsweise anwendungsspezifisch | `docker inspect ... --format '{{json .State.Health}}'` |

</details>

<details>
<summary><strong>33. Entscheidungsmatrix</strong></summary>

| Befund | Wahrscheinliche Ursache | Nächster Schritt |
|---|---|---|
| VM läuft, Konsole funktioniert, Netzwerk nicht | Gastnetzwerk, Switch oder VLAN | Virtuelle und interne Netzwerkkonfiguration prüfen |
| VM startet nicht, Host-RAM knapp | Ressourcenproblem | Host- und VM-Speicherzuweisung prüfen |
| Mehrere VMs frieren ein | Host oder gemeinsames Storage | Hostlast und Storage-Latenz prüfen |
| Snapshot wächst stark | Viele Schreibänderungen oder alter Snapshot | Zweck, Größe und Zusammenführung planen |
| Container endet mit Code 127 | Startbefehl nicht gefunden | Entrypoint, Cmd und Image prüfen |
| Container endet mit Code 137 | OOM oder erzwungenes Beenden möglich | OOM-Status und Hostprotokolle prüfen |
| Container läuft, Anwendung nicht erreichbar | Listener, Port oder Healthcheck | Containerlistener und Portzuordnung prüfen |
| Port kann nicht gebunden werden | Hostport bereits belegt | Hostlistener und Compose-Konfiguration prüfen |
| Container findet Datenbank nicht | DNS, Netzwerk oder Hostname | Gemeinsames Netzwerk und Dienstnamen prüfen |
| Daten nach Neuerstellung weg | Fehlendes oder falsches Volume | Mountkonfiguration und vorhandene Volumes prüfen |
| Image startet auf ARM nicht | Plattform nicht unterstützt | Imagearchitektur und Manifest prüfen |
| Docker-Client findet Daemon nicht | Dienst, Socket oder Kontext | `docker version`, Dienst und Kontext prüfen |
| Nur Root sieht Podman-Container | Rootful- und Rootless-Ansicht | Richtigen Benutzerkontext verwenden |
| Host hat Platz, Docker meldet voll | Docker-Disk, Inodes oder Storage-Layer | `docker system df`, `df` und Inodes prüfen |
| Nach Snapshot stimmen Anmeldungen nicht | Zeitabweichung | Gastzeit und Zeitquelle prüfen |

</details>

<details>
<summary><strong>34. Dokumentationsvorlage</strong></summary>

```text
Ticket:
Datum und Uhrzeit:
Bearbeiter:

Betroffene Plattform:
Hypervisor oder Container-Engine:
Version:
Host:
Hostbetriebssystem:
Physischer oder virtueller Host:
Cluster:
Managementsystem:

Betroffene VM oder Container:
VM- beziehungsweise Container-ID:
Image und Tag:
Gastbetriebssystem:
Architektur:
Aktueller Zustand:
Startzeit:
Uptime:
Exit-Code:
Healthcheck:
Neustartzähler:

Umfang der Störung:
Originale Fehlermeldung:
Fehlerzeitpunkt:
Letzte funktionierende Nutzung:
Letzte Änderung:
Update, Snapshot oder Migration:

Host-CPU:
Host-RAM:
Hostspeicher:
Inode-Belegung:
Storage-Zustand:
Virtueller Datenträger:
Snapshots oder Checkpoints:

Virtueller Switch oder Netzwerk:
VLAN:
IP-Adresse:
DNS:
Portveröffentlichung:
Hostlistener:
Containerlistener:
Firewall:

Volumes und Mounts:
Berechtigungen:
Umgebungsvariablen geprüft:
Sensible Werte redigiert:
Abhängige Dienste:
Zeitquelle:

Relevante Hostprotokolle:
Hypervisorprotokolle:
Gastprotokolle:
Containerprotokolle:
OOM-Ereignisse:

Vermutete Ursache:
Durchgeführte Tests:
Sicherung geprüft:
Wartungsfenster:
Durchgeführte Änderung:
Rückfallplan:

Status nach der Maßnahme:
Interne Funktionsprüfung:
Externe Funktionsprüfung:
Monitoring:
Weiterführende Maßnahmen:
```

</details>

---

**Merksatz**

> Bei Virtualisierungs- und Containerfehlern wird immer von außen nach innen geprüft: Host, Virtualisierungsschicht, Netzwerk und Storage, Gast beziehungsweise Container und erst danach die Anwendung. Ein Status `Running` oder `Up` ist noch kein Funktionsnachweis.

**Quellen und weiterführende Dokumentation**

- [Microsoft Learn – Hyper-V mit PowerShell verwalten](https://learn.microsoft.com/windows-server/virtualization/hyper-v/powershell)
- [Microsoft Learn – Hyper-V-PowerShell-Referenz](https://learn.microsoft.com/powershell/module/hyper-v/)
- [Microsoft Learn – Hyper-V-Ereignisprotokolle](https://learn.microsoft.com/windows-server/virtualization/hyper-v/best-practices-analyzer/)
- [libvirt – virsh-Dokumentation](https://www.libvirt.org/manpages/virsh.html)
- [libvirt – Architektur](https://libvirt.org/architecture.html)
- [QEMU – System Emulation](https://www.qemu.org/docs/master/system/index.html)
- [Docker Docs – Diagnose des Docker-Daemons](https://docs.docker.com/engine/daemon/troubleshoot/)
- [Docker Docs – docker inspect](https://docs.docker.com/reference/cli/docker/inspect/)
- [Docker Docs – docker logs](https://docs.docker.com/reference/cli/docker/container/logs/)
- [Docker Docs – docker stats](https://docs.docker.com/reference/cli/docker/container/stats/)
- [Docker Docs – docker events](https://docs.docker.com/reference/cli/docker/system/events/)
- [Docker Docs – Docker-Netzwerke](https://docs.docker.com/engine/network/)
- [Docker Docs – Docker-Volumes](https://docs.docker.com/engine/storage/volumes/)
- [Docker Docs – Compose-Dateireferenz](https://docs.docker.com/reference/compose-file/)
- [Docker Docs – Multi-Platform-Images](https://docs.docker.com/build/building/multi-platform/)
- [Docker Docs – Docker Desktop Troubleshoot](https://docs.docker.com/desktop/troubleshoot-and-support/troubleshoot/)
- [Podman-Dokumentation](https://docs.podman.io/en/latest/)