Filters
How to search
  • Plain words find names, texts and examples.
  • "two words" finds the exact phrase.
  • --name or -x finds an option.
  • #word looks only inside commands.
  • @grep finds lessons and labs that use grep.
  • Filters: cat:network · in:labs · in:notes · level:rhcsa · ch:8 · root:yes. Put ! before a word to leave it out. OR between words means one of them.
  • ↑ ↓ to move · Enter to open · Esc to close · / to search

Chapter 6Name in the course: System administration with Python

Run commands and read the system

Python can run any command, read the environment, check processes, disks and network — and return proper exit codes, so cron, systemd and CI know if the script worked.

  • 5 Lessons
  • 0 Commands

$ run as a normal user# run as root (or with sudo)

6.1

Run commands with subprocess

subprocess.run with a list of arguments (no shell) is safe and gives you output and exit code.

run_cmd.py
import subprocess
 
r = subprocess.run(["systemctl", "is-active", "sshd"], capture_output=True, text=True)
print(r.returncode, r.stdout.strip())
 
out = subprocess.run(["df", "-h", "/"], capture_output=True, text=True, check=True).stdout
print(out)
 
try:
    subprocess.run(["dnf", "check-update", "-q"], check=True, timeout=120)
except subprocess.CalledProcessError as e:
    print("updates waiting, exit code", e.returncode)

Watch out

shell=True with text from users or files is a command-injection hole. Use a list of arguments, and shlex.quote if you really need a shell.

6.2

Read environment and arguments

os.environ holds the environment; sys.argv the command-line arguments (better: argparse, see Build command-line tools).

env.py
import os
import sys
 
region = os.environ.get("AZURE_REGION", "westeurope")
token = os.environ["API_TOKEN"]
print(sys.argv[1:] if len(sys.argv) > 1 else "no arguments")

6.3

Check disks, memory and processes

The standard library covers basics; psutil (pip install psutil) gives CPU, memory, disks, processes and connections on every OS.

health.py
import shutil
import psutil
 
du = shutil.disk_usage("/")
print(f"disk / {du.used / du.total:.0%}")
print(f"memory {psutil.virtual_memory().percent}%")
print(f"load {psutil.getloadavg()}")
for p in sorted(psutil.process_iter(["pid", "name", "memory_percent"]), key=lambda p: p.info["memory_percent"] or 0, reverse=True)[:5]:
    print(p.info)

6.4

Check the network

socket tests ports; ssl reads certificates — great for monitoring scripts.

cert_days.py
import socket
import ssl
from datetime import datetime, timezone
 
 
def cert_days_left(host: str, port: int = 443) -> int:
    ctx = ssl.create_default_context()
    with socket.create_connection((host, port), timeout=5) as sock:
        with ctx.wrap_socket(sock, server_hostname=host) as tls:
            not_after = tls.getpeercert()["notAfter"]
    end = datetime.strptime(not_after, "%b %d %H:%M:%S %Y %Z").replace(tzinfo=timezone.utc)
    return (end - datetime.now(timezone.utc)).days
 
 
for site in ["s0sta.com", "babolatksa.com"]:
    print(site, cert_days_left(site), "days")

6.5

Return exit codes

sys.exit(N) ends the script with a status: 0 = OK, other = problem. Monitoring systems use 0/1/2 for OK/WARNING/CRITICAL.

exit_codes.py
import shutil
import sys
 
pct = shutil.disk_usage("/").used / shutil.disk_usage("/").total * 100
if pct > 90:
    print(f"CRITICAL {pct:.0f}%")
    sys.exit(2)
if pct > 80:
    print(f"WARNING {pct:.0f}%")
    sys.exit(1)
print(f"OK {pct:.0f}%")
sys.exit(0)