$ run as a normal user# run as root (or with sudo)
Run commands with subprocess
subprocess.run with a list of arguments (no shell) is safe and gives you output and exit code.
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.
Read environment and arguments
os.environ holds the environment; sys.argv the command-line arguments (better: argparse, see Build command-line tools).
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")Check disks, memory and processes
The standard library covers basics; psutil (pip install psutil) gives CPU, memory, disks, processes and connections on every OS.
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)Check the network
socket tests ports; ssl reads certificates — great for monitoring scripts.
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")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.
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)