Why Python for System Administration
Python has become the go-to language for system administrators and DevOps engineers. Its readable syntax, extensive standard library, and rich ecosystem of third-party packages make it perfect for automating repetitive tasks. This guide will teach you practical Python skills for everyday system administration.
Setting Up Your Python Environment
Start with a proper Python setup:
# Check Python version (3.8+ recommended)
python3 --version
# Create virtual environment for your scripts
python3 -m venv ~/admin-scripts
source ~/admin-scripts/bin/activate
# Install common packages
pip install requests paramiko psutil pyyaml
File and Directory Operations
The pathlib module provides an object-oriented interface for filesystem operations:
from pathlib import Path
import shutil
# Working with paths
config_dir = Path("/etc/myapp")
log_file = config_dir / "logs" / "app.log"
# Check if exists
if log_file.exists():
print(f"Log size: {log_file.stat().st_size} bytes")
# Iterate over files
for conf_file in config_dir.glob("*.conf"):
print(f"Found config: {conf_file.name}")
# Read file content
content = Path("/etc/hosts").read_text()
# Write file
Path("/tmp/output.txt").write_text("Hello, World!")
# Copy files with shutil
shutil.copy("/etc/hosts", "/tmp/hosts.backup")
shutil.copytree("/etc/nginx", "/tmp/nginx-backup")
Executing System Commands
The subprocess module is essential for running shell commands:
import subprocess
# Simple command execution
result = subprocess.run(["df", "-h"], capture_output=True, text=True)
print(result.stdout)
# Check return code
if result.returncode != 0:
print(f"Error: {result.stderr}")
# Run with shell (be careful with user input)
result = subprocess.run(
"ps aux | grep nginx | wc -l",
shell=True,
capture_output=True,
text=True
)
# Get live output
process = subprocess.Popen(
["tail", "-f", "/var/log/syslog"],
stdout=subprocess.PIPE,
text=True
)
for line in process.stdout:
if "error" in line.lower():
print(f"ERROR FOUND: {line}")
System Monitoring with psutil
psutil provides cross-platform system monitoring:
import psutil
# CPU information
print(f"CPU Usage: {psutil.cpu_percent(interval=1)}%")
print(f"CPU Cores: {psutil.cpu_count()}")
# Memory information
mem = psutil.virtual_memory()
print(f"Total RAM: {mem.total / (1024**3):.2f} GB")
print(f"Used RAM: {mem.percent}%")
# Disk usage
for partition in psutil.disk_partitions():
usage = psutil.disk_usage(partition.mountpoint)
print(f"{partition.mountpoint}: {usage.percent}% used")
# Network connections
connections = psutil.net_connections()
listening = [c for c in connections if c.status == 'LISTEN']
print(f"Listening ports: {len(listening)}")
# Process management
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent']):
if proc.info['cpu_percent'] > 50:
print(f"High CPU: {proc.info['name']} ({proc.info['pid']})")
Log File Analysis
Parsing logs is a common sysadmin task:
import re
from collections import Counter
from datetime import datetime
def analyze_nginx_logs(log_path):
pattern = r'(\d+\.\d+\.\d+\.\d+).*\[(.+?)\].*"(\w+) (.+?) HTTP'
ips = Counter()
paths = Counter()
with open(log_path) as f:
for line in f:
match = re.search(pattern, line)
if match:
ip, timestamp, method, path = match.groups()
ips[ip] += 1
paths[path] += 1
print("Top 10 IPs:")
for ip, count in ips.most_common(10):
print(f" {ip}: {count} requests")
print("\nTop 10 Paths:")
for path, count in paths.most_common(10):
print(f" {path}: {count} requests")
# Usage
analyze_nginx_logs("/var/log/nginx/access.log")
Working with APIs
The requests library simplifies HTTP operations:
import requests
# GET request
response = requests.get("https://api.github.com/users/torvalds")
if response.ok:
data = response.json()
print(f"Name: {data['name']}")
print(f"Repos: {data['public_repos']}")
# POST request with authentication
headers = {"Authorization": f"Bearer {api_token}"}
payload = {"name": "New Server", "type": "web"}
response = requests.post(
"https://api.service.com/servers",
json=payload,
headers=headers
)
# Handle errors
try:
response.raise_for_status()
except requests.HTTPError as e:
print(f"API Error: {e}")
SSH Automation with Paramiko
Automate remote server management:
import paramiko
def run_remote_command(host, username, key_path, command):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
client.connect(
hostname=host,
username=username,
key_filename=key_path
)
stdin, stdout, stderr = client.exec_command(command)
output = stdout.read().decode()
errors = stderr.read().decode()
return output, errors
finally:
client.close()
# Usage
servers = ["web1.example.com", "web2.example.com"]
for server in servers:
output, _ = run_remote_command(
server, "admin", "~/.ssh/id_rsa", "uptime"
)
print(f"{server}: {output.strip()}")
Configuration File Management
Handle various config formats:
import yaml
import json
import configparser
# YAML (common in modern tools)
with open("config.yaml") as f:
config = yaml.safe_load(f)
print(config["database"]["host"])
# JSON
with open("settings.json") as f:
settings = json.load(f)
# INI files
config = configparser.ConfigParser()
config.read("/etc/myapp/app.ini")
db_host = config["database"]["host"]
Practical Script: Disk Space Monitor
A complete example script for monitoring disk space:
#!/usr/bin/env python3
"""Disk space monitoring script with email alerts."""
import psutil
import smtplib
from email.message import EmailMessage
from datetime import datetime
THRESHOLD = 85 # Alert when usage exceeds this percentage
ADMIN_EMAIL = "admin@example.com"
SMTP_SERVER = "smtp.example.com"
def check_disk_usage():
alerts = []
for partition in psutil.disk_partitions():
try:
usage = psutil.disk_usage(partition.mountpoint)
if usage.percent >= THRESHOLD:
alerts.append({
"mount": partition.mountpoint,
"percent": usage.percent,
"free_gb": usage.free / (1024**3)
})
except PermissionError:
continue
return alerts
def send_alert(alerts):
msg = EmailMessage()
msg["Subject"] = f"Disk Space Alert - {datetime.now():%Y-%m-%d}"
msg["From"] = "monitor@example.com"
msg["To"] = ADMIN_EMAIL
body = "The following partitions are running low on space:\n\n"
for alert in alerts:
body += f" {alert['mount']}: {alert['percent']}% used "
body += f"({alert['free_gb']:.2f} GB free)\n"
msg.set_content(body)
with smtplib.SMTP(SMTP_SERVER) as smtp:
smtp.send_message(msg)
if __name__ == "__main__":
alerts = check_disk_usage()
if alerts:
print(f"Found {len(alerts)} partitions above threshold")
send_alert(alerts)
else:
print("All partitions within acceptable limits")
Error Handling and Logging
Professional scripts need proper logging:
import logging
from logging.handlers import RotatingFileHandler
# Configure logging
logger = logging.getLogger("admin_script")
logger.setLevel(logging.INFO)
handler = RotatingFileHandler(
"/var/log/admin-scripts/script.log",
maxBytes=10*1024*1024, # 10MB
backupCount=5
)
formatter = logging.Formatter(
"%(asctime)s - %(levelname)s - %(message)s"
)
handler.setFormatter(formatter)
logger.addHandler(handler)
# Usage
logger.info("Script started")
try:
# ... your code ...
logger.info("Operation completed successfully")
except Exception as e:
logger.error(f"Operation failed: {e}", exc_info=True)
Conclusion
Python transforms system administration from manual, error-prone tasks into reliable, automated processes. Start with simple scripts for file operations and command execution, then gradually build more sophisticated tools for monitoring, API integration, and multi-server management. The time invested in learning Python automation pays dividends in efficiency and reliability.
Looking to advance your Python and automation skills? Explore our collection of Python programming and DevOps books for comprehensive learning resources.