Python und das Betriebssystem¶
Mit Dateien, Prozessen, Umgebungsvariablen und Systeminformationen arbeiten und Python in die tägliche Administration integrieren.
Einer der häufigsten Einsatzzwecke von Python im Administrationsalltag ist die Interaktion mit dem Betriebssystem. Dateien müssen verarbeitet, Verzeichnisse durchsucht, externe Programme gestartet und Systeminformationen ausgewertet werden.
Viele Aufgaben, die früher ausschließlich mit Shell-Skripten gelöst wurden, lassen sich mit Python strukturierter, robuster und leichter wartbar umsetzen. Gleichzeitig kann Python bestehende Werkzeuge und Betriebssystemfunktionen weiterhin nutzen.
In diesem Kapitel lernen Sie, wie Python mit dem Betriebssystem zusammenarbeitet und wie typische Administrationsaufgaben automatisiert werden können.
Dateien und Verzeichnisse verwalten¶
Dateien erstellen und schreiben¶
Die Basis jeder Dateiverwaltung ist das Erstellen und Schreiben von Dateien. In Python geschieht dies mit der eingebauten Funktion open(). Im Gegensatz zu Java oder C# ist das Öffnen einer Datei in Python sehr einfach und flexibel.
# Eine neue Logdatei erstellen und eine Zeile schreiben
with open('server.log', 'w', encoding='utf-8') as log_file:
log_file.write('Server gestartet am 2024-06-01 08:00\n')
Der with-Block sorgt dafür, dass die Datei automatisch geschlossen wird, auch wenn ein Fehler auftritt. Das ist eine bewährte Praxis, die Ressourcensicherheit garantiert.
Dateien lesen¶
Zum Auslesen von Dateien bietet sich ebenfalls open() an:
with open('server.log', 'r', encoding='utf-8') as log_file:
for line in log_file:
print(line.strip()) # Zeilen einzeln verarbeiten
Das zeilenweise Lesen ist besonders bei großen Logdateien effizient, da nicht die gesamte Datei auf einmal geladen wird.
Dateien löschen und umbenennen¶
Für Dateioperationen wie Löschen oder Umbenennen verwendet man das os-Modul:
import os
# Datei löschen
if os.path.exists('old_backup.zip'):
os.remove('old_backup.zip')
# Datei umbenennen
os.rename('temp.log', 'server.log')
Vor dem Löschen empfiehlt sich immer eine Existenzprüfung, um Fehler zu vermeiden.
Dateien kopieren¶
Das shutil-Modul bietet Funktionen für das Kopieren von Dateien und Verzeichnissen, was in der Shell oft mit cp oder copy erledigt wird:
Dies ist nützlich für Backup-Skripte oder das Verschieben von Konfigurationsdateien.
Verzeichnisse erstellen und durchsuchen¶
Ein häufiger Anwendungsfall ist das Anlegen von Verzeichnissen und das Durchlaufen von Verzeichnisbäumen.
import os
# Verzeichnis erstellen, falls es nicht existiert
os.makedirs('backup/2024-06-01', exist_ok=True)
# Alle Dateien in einem Verzeichnis auflisten
for entry in os.listdir('backup'):
path = os.path.join('backup', entry)
if os.path.isfile(path):
print(f'Datei: {entry}')
elif os.path.isdir(path):
print(f'Verzeichnis: {entry}')
Für rekursive Durchsuchungen ist os.walk() ideal:
for root, dirs, files in os.walk('backup'):
print(f'Im Verzeichnis: {root}')
for file in files:
print(f' Datei: {file}')
Praxisbeispiel: Logdateien archivieren¶
Ein typisches Admin-Skript archiviert alte Logdateien und verschiebt sie in ein Backup-Verzeichnis:
import os
import shutil
from datetime import datetime, timedelta
log_dir = '/var/log/myapp'
backup_dir = '/var/backups/myapp_logs'
os.makedirs(backup_dir, exist_ok=True)
# Logdateien älter als 7 Tage verschieben
cutoff = datetime.now() - timedelta(days=7)
for filename in os.listdir(log_dir):
if filename.endswith('.log'):
filepath = os.path.join(log_dir, filename)
mtime = datetime.fromtimestamp(os.path.getmtime(filepath))
if mtime < cutoff:
dest = os.path.join(backup_dir, filename)
shutil.move(filepath, dest)
print(f'Archiviert: {filename}')
Hinweis zu Pfadtrennzeichen¶
Unter Windows verwendet man \ als Pfadtrenner, unter Linux /. Python's os.path.join() kümmert sich automatisch um das richtige Trennzeichen, was Skripte plattformunabhängig macht.
Zusammenfassung¶
Python bietet mit open(), os und shutil einfache und mächtige Werkzeuge für die Dateiverwaltung. Im Vergleich zu Shell-Skripten ermöglichen diese Module komplexe Logik, Fehlerbehandlung und Plattformunabhängigkeit in einem einzigen Skript. So lassen sich Routineaufgaben wie Backup, Logrotation oder Konfigurationsmanagement elegant automatisieren.
Mit Umgebungsvariablen arbeiten¶
Umgebungsvariablen lesen und nutzen¶
Umgebungsvariablen sind zentrale Konfigurationspunkte im Betriebssystem, die Programme und Skripte steuern können. In Python greift man über das Modul os auf sie zu. Das ist vergleichbar mit dem Zugriff auf Umgebungsvariablen in Bash (VAR) oder PowerShell (Env:VAR).
import os
# Eine Umgebungsvariable lesen
path = os.environ.get('PATH')
print(f'PATH: {path}')
# Standardwert verwenden, falls Variable nicht gesetzt ist
db_host = os.environ.get('DB_HOST', 'localhost')
print(f'Datenbankhost: {db_host}')
Praxis-Tipp: Verwenden Sie os.environ.get(), um Fehler zu vermeiden, wenn eine Variable nicht existiert. Ein direkter Zugriff wie os.environ['VAR'] löst eine Ausnahme aus, wenn die Variable fehlt.
Umgebungsvariablen setzen und ändern¶
Umgebungsvariablen innerhalb eines laufenden Python-Prozesses zu setzen oder zu ändern, schreibt man in os.environ. Diese Änderungen wirken nur im aktuellen Prozess und dessen Kindprozessen.
import os
# Neue Umgebungsvariable setzen
os.environ['MY_VAR'] = 'wert'
# Variable ändern
os.environ['PATH'] = os.environ.get('PATH', '') + ':/custom/bin'
# Bestätigen
print(os.environ['MY_VAR'])
Wichtig: Änderungen an os.environ beeinflussen nicht die Systemumgebung dauerhaft. Für dauerhafte Änderungen müssen Sie die Variable im Betriebssystem setzen (z.B. in .bashrc, PowerShell-Profil oder Systemsteuerung).
Umgebungsvariablen für Konfigurationen und Zugangsdaten¶
In der Praxis werden sensible Daten wie API-Schlüssel oder Datenbankpasswörter nicht im Code, sondern in Umgebungsvariablen gespeichert. So bleiben sie getrennt von der Anwendung und können leicht geändert werden.
import os
api_key = os.environ.get('API_KEY')
if not api_key:
raise RuntimeError('API_KEY ist nicht gesetzt')
# API-Key verwenden
print(f'API-Key Länge: {len(api_key)}')
Best Practice: Dokumentieren Sie, welche Umgebungsvariablen Ihre Skripte erwarten, und prüfen Sie deren Existenz beim Start.
Python Dotenv: Umgebungsvariablen aus Dateien laden¶
Gerade in Entwicklungs- und Testumgebungen ist es praktisch, Umgebungsvariablen in einer .env-Datei zu speichern, statt sie im System zu setzen. Das Paket python-dotenv liest diese Datei und lädt die Variablen in os.environ.
Installation:
Beispiel .env-Datei:
Python-Skript zum Laden:
from dotenv import load_dotenv
import os
load_dotenv() # Lädt Variablen aus .env ins os.environ
print(os.environ.get('DB_HOST')) # Ausgabe: 192.168.1.100
Vorteil gegenüber Shell-Skripten: Dotenv ermöglicht es, Umgebungsvariablen plattformunabhängig und projektbezogen zu verwalten, ohne die globale Shell-Umgebung zu verändern.
Typische Anwendungsfälle in der Administration¶
- Automatisierte Backups: Zugangsdaten für entfernte Server oder Cloud-Dienste über Umgebungsvariablen sicher bereitstellen.
- Monitoring-Skripte: API-Token für Monitoring-Tools aus Umgebungsvariablen lesen.
- Konfigurationsmanagement: Unterschiedliche Umgebungen (Test, Produktion) durch verschiedene
.env-Dateien abbilden.
Zusammenfassung¶
- Umgebungsvariablen sind essenziell für flexible und sichere Konfigurationen.
os.environ.get()ist der sichere Weg zum Lesen.- Änderungen in
os.environwirken nur temporär im Prozess. python-dotenverleichtert das Management von Umgebungsvariablen in Entwicklungsumgebungen.
Durch den gezielten Einsatz von Umgebungsvariablen mit Python automatisieren Sie administrative Aufgaben effizient und behalten dabei die Kontrolle über sensible Daten.
Externe Programme ausführen¶
Externe Programme mit subprocess ausführen¶
In der Systemadministration ist es oft notwendig, externe Programme oder Shell-Kommandos aus Python-Skripten heraus auszuführen, z. B. um Systeminformationen zu sammeln, Dienste zu steuern oder bestehende Werkzeuge in Automatisierungsprozesse einzubinden.
Das moderne und empfohlene Modul dafür ist subprocess. Es ersetzt ältere Module wie os.system und bietet mehr Kontrolle über Eingabe, Ausgabe und Fehlerbehandlung.
Einfaches Ausführen eines Kommandos¶
Möchten Sie z. B. unter Linux den Befehl ls -l /var/log ausführen und die Ausgabe direkt sehen, verwenden Sie:
import subprocess
# Einfaches Kommando ausführen und Ausgabe direkt auf der Konsole anzeigen
subprocess.run(['ls', '-l', '/var/log'], check=True)
Unter Windows wäre ein vergleichbares Beispiel dir C:\Windows:
Das Argument check=True sorgt dafür, dass bei einem Fehler (nicht 0 Rückgabewert) eine Ausnahme ausgelöst wird, was Fehler früh sichtbar macht.
Ausgabe eines Kommandos in Python weiterverarbeiten¶
Oft wollen Sie die Ausgabe eines Kommandos nicht nur sehen, sondern weiterverarbeiten, z. B. um Logdateien zu filtern oder Netzwerkstatus auszuwerten.
result = subprocess.run(
['ip', 'addr'],
capture_output=True, # Ausgabe wird in result.stdout gespeichert
text=True, # Ausgabe als String statt Bytes
check=True
)
print('IP-Konfiguration:')
print(result.stdout)
Unter Windows könnten Sie ipconfig analog ausführen.
Fehlerausgabe und Rückgabewert auswerten¶
Neben der Standardausgabe (stdout) ist oft auch die Fehlerausgabe (stderr) relevant:
result = subprocess.run(
['systemctl', 'status', 'nginx'],
capture_output=True,
text=True
)
if result.returncode == 0:
print('Nginx läuft.')
else:
print('Fehler beim Abfragen des Dienststatus:')
print(result.stderr)
Shell-Kommandos mit shell=True¶
Manchmal brauchen Sie komplexe Shell-Befehle oder Pipes. Dann können Sie shell=True verwenden:
# Beispiel: Ausgabe von 'ps aux | grep ssh' unter Linux
result = subprocess.run(
'ps aux | grep ssh',
shell=True,
capture_output=True,
text=True
)
print(result.stdout)
Warnung: shell=True kann Sicherheitsrisiken bergen, wenn Benutzereingaben ungeprüft eingebunden werden. Verwenden Sie es nur, wenn nötig und mit Vorsicht.
Vergleich zu Shell-Skripten¶
- Vorteil Python: Bessere Fehlerbehandlung, strukturierte Ausgabe, einfache Weiterverarbeitung von Ergebnissen
- Shell-Skript: Kürzer für einfache Befehle, aber schwerer zu warten und zu erweitern
Python eignet sich besonders, wenn mehrere externe Werkzeuge kombiniert, deren Ausgaben analysiert oder automatisierte Entscheidungen getroffen werden sollen.
Beispiel: Backup-Verzeichnis mit tar archivieren¶
Ein typisches Admin-Szenario ist das automatisierte Erstellen von Backups:
import datetime
import subprocess
backup_dir = '/var/backups/myapp'
archive_name = f'/var/backups/myapp_backup_{datetime.date.today()}.tar.gz'
try:
subprocess.run(
['tar', '-czf', archive_name, '-C', backup_dir, '.'],
check=True
)
print(f'Backup erfolgreich erstellt: {archive_name}')
except subprocess.CalledProcessError as e:
print(f'Fehler beim Backup: {e}')
Unter Windows könnten Sie stattdessen powershell-Befehle oder Compress-Archive verwenden.
Best Practices¶
- Verwenden Sie
subprocess.run()für einfache Aufrufe mitcheck=True, um Fehler sofort zu erkennen. - Nutzen Sie
capture_output=Trueundtext=True, wenn Sie Ausgaben in Python weiterverarbeiten wollen. - Vermeiden Sie
shell=True, außer wenn komplexe Shell-Features benötigt werden. - Fangen Sie Ausnahmen wie
subprocess.CalledProcessErrorab, um Fehler gezielt zu behandeln. - Dokumentieren Sie externe Kommandos und deren erwartete Ergebnisse, um Wartbarkeit sicherzustellen.
Mit diesen Grundlagen können Sie externe Programme sicher und effektiv in Ihre Python-Automatisierung integrieren.
Systeminformationen ermitteln¶
Betriebssysteminformationen mit dem Modul platform¶
Das Python-Modul platform liefert grundlegende Informationen zum Betriebssystem und zur Hardware. Für Administratoren ist es wichtig, schnell zu erkennen, auf welchem System ein Skript läuft, um systemabhängige Befehle oder Pfade korrekt zu handhaben.
import platform
print("System:", platform.system()) # z.B. 'Linux' oder 'Windows'
print("Release:", platform.release()) # z.B. '5.15.0-58-generic' oder '10'
print("Version:", platform.version()) # detaillierte OS-Version
print("Maschine:", platform.machine()) # z.B. 'x86_64'
print("Prozessor:", platform.processor()) # z.B. 'Intel64 Family 6 Model 158'
Diese Informationen entsprechen in etwa den Ausgaben von uname -a unter Linux oder systeminfo in der Windows-Eingabeaufforderung.
Systeminformationen mit os und os.uname()¶
Unter Linux und Unix liefert os.uname() detaillierte Systemdaten:
import os
if hasattr(os, "uname"):
uname = os.uname()
print(f"System: {uname.sysname}")
print(f"Node Name: {uname.nodename}")
print(f"Release: {uname.release}")
print(f"Version: {uname.version}")
print(f"Machine: {uname.machine}")
else:
print("os.uname() wird auf diesem System nicht unterstützt")
Unter Windows steht diese Funktion nicht zur Verfügung, hier ist platform die bessere Wahl.
Hardwareinformationen mit psutil¶
Für detaillierte Hardware- und Systemdaten ist das Drittanbieter-Modul psutil sehr hilfreich. Es ermöglicht den Zugriff auf CPU-Auslastung, Speichernutzung, Festplatteninformationen und mehr – wichtige Daten für Monitoring und Automatisierung.
Installation:
Beispiel zur CPU- und Speicherabfrage:
import psutil
# CPU-Kerne
print(f"Logische CPU-Kerne: {psutil.cpu_count(logical=True)}")
print(f"Physische CPU-Kerne: {psutil.cpu_count(logical=False)}")
# CPU-Auslastung in Prozent
print(f"CPU-Auslastung (gesamt): {psutil.cpu_percent(interval=1)} %")
# Arbeitsspeicher
mem = psutil.virtual_memory()
print(f"Gesamter RAM: {mem.total / (1024 ** 3):.2f} GB")
print(f"Verfügbarer RAM: {mem.available / (1024 ** 3):.2f} GB")
print(f"RAM-Auslastung: {mem.percent} %")
# Festplattennutzung (Root-Partition)
disk = psutil.disk_usage("/")
print(f"Gesamter Speicher /: {disk.total / (1024 ** 3):.2f} GB")
print(f"Freier Speicher /: {disk.free / (1024 ** 3):.2f} GB")
print(f"Belegter Speicher /: {disk.percent} %")
Python-Laufzeitumgebung mit sys und platform¶
Neben Systeminformationen ist es oft wichtig, Details zur Python-Umgebung zu kennen, z.B. für Skripte, die plattformübergreifend laufen sollen.
import sys
import platform
print(f"Python-Version: {sys.version}")
print(f"Implementierung: {platform.python_implementation()}")
print(f"Interpreter-Pfad: {sys.executable}")
Praxis-Tipp: Systeminformationen für bedingte Logik nutzen¶
In Automatisierungsskripten ist es üblich, Betriebssystem-spezifische Befehle auszuführen. Ein einfaches Beispiel:
import platform
import subprocess
system = platform.system()
if system == "Linux":
# Beispiel: Linux-spezifischer Befehl
subprocess.run(["ls", "-l", "/var/log"])
elif system == "Windows":
# Windows-spezifischer Befehl
subprocess.run(["dir", "C:\\Windows\\System32"], shell=True)
else:
print(f"Unbekanntes System: {system}")
Im Vergleich zu Shell-Skripten bietet Python mehr Flexibilität, z.B. bessere Fehlerbehandlung, plattformübergreifende Module und einfachere Integration in komplexe Automatisierungsabläufe.
Zusammenfassung¶
platformist das Standardmodul für grundlegende Systeminformationen auf allen Plattformen.os.uname()liefert unter Linux/Unix detaillierte Systemdaten.psutilermöglicht tiefe Einblicke in Hardware- und Systemzustände.sysundplatformhelfen, die Python-Laufzeitumgebung zu erkennen.- Systeminformationen sind essenziell, um plattformabhängige Automatisierungen sicher und robust zu gestalten.
Diese Werkzeuge bilden die Basis, um mit Python verlässliche und wartbare Administrationsskripte zu schreiben, die auf verschiedenen Systemen konsistent funktionieren.
Netzwerk- und Prozessinformationen¶
Prozesse überwachen und analysieren¶
Für die Prozessverwaltung und -überwachung ist das Modul psutil das Standardwerkzeug in Python. Es ist plattformübergreifend und bietet umfassende Informationen zu laufenden Prozessen, CPU- und Speicherauslastung sowie Netzwerkverbindungen.
Zunächst installieren Sie psutil mit:
Ein einfaches Beispiel, um alle laufenden Prozesse mit ihrer PID und dem Namen aufzulisten:
import psutil
for proc in psutil.process_iter(['pid', 'name']):
print(f"PID: {proc.info['pid']}, Name: {proc.info['name']}")
Dies ist vergleichbar mit dem Befehl ps unter Linux oder Get-Process in PowerShell, aber mit der Flexibilität, die Ausgabe in Python weiterzuverarbeiten.
Prozesse gezielt filtern und Ressourcenverbrauch prüfen¶
Oft möchte man Prozesse mit hohem Ressourcenverbrauch finden, z. B. um Speicherfresser zu identifizieren:
for proc in psutil.process_iter(['pid', 'name', 'memory_actual_info']):
mem = proc.info['memory_actual_info']
if mem and mem.rss > 100 * 1024 * 1024: # > 100 MB
print(f"Hoher Speicherverbrauch: PID {proc.info['pid']} - {proc.info['name']} ({mem.rss / 1024 ** 2:.1f} MB)")
Netzwerkverbindungen und Ports auslesen¶
psutil erlaubt auch die Abfrage offener Netzwerkverbindungen, was für Sicherheitsüberprüfungen oder Monitoring wichtig ist:
for conn in psutil.net_connections(kind='inet'):
laddr = f"{conn.laddr.ip}:{conn.laddr.port}" if conn.laddr else ""
raddr = f"{conn.raddr.ip}:{conn.raddr.port}" if conn.raddr else "-"
print(f"{conn.pid or '-':>5} {conn.status:>13} {laddr:>22} -> {raddr:>22}")
Dies entspricht unter Linux dem Befehl netstat -tunap oder ss, unter Windows netstat -ano.
Systemweite Netzwerkstatistiken¶
Neben einzelnen Verbindungen können Sie auch die gesamte Netzwerkauslastung abfragen:
net_io = psutil.net_io_counters()
print(f"Gesendete Bytes: {net_io.bytes_sent}")
print(f"Empfangene Bytes: {net_io.bytes_recv}")
Prozesse starten und steuern¶
Python erlaubt auch das Starten und Steuern von Prozessen, z. B. um externe Tools zu automatisieren:
import subprocess
# Beispiel: ping ausführen und Ausgabe lesen
result = subprocess.run(['ping', '-c', '3', '8.8.8.8'], capture_output=True, text=True)
print(result.stdout)
Im Gegensatz zu Shell-Skripten ermöglicht Python eine bessere Fehlerbehandlung und flexible Weiterverarbeitung der Ausgabe.
Best Practices¶
- Verwenden Sie
psutilfür plattformübergreifende Prozess- und Netzwerkinfos. - Nutzen Sie Filter, um nur relevante Prozesse oder Verbindungen zu analysieren.
- Kombinieren Sie Prozess- und Netzwerkdaten für umfassende Monitoring-Skripte.
- Vermeiden Sie direkte Shell-Aufrufe, wenn Python-Module verfügbar sind, um Portabilität und Sicherheit zu erhöhen.
Zusammenfassung¶
Mit psutil und subprocess bietet Python leistungsfähige Werkzeuge, um Prozesse und Netzwerkstatus systematisch zu erfassen und zu steuern. Dies erleichtert die Automatisierung von Überwachungsaufgaben, Fehleranalysen und Infrastrukturmanagement erheblich – und zwar auf Linux und Windows gleichermaßen.