Linux CLI Best Practices
A condensed summary of the 25 most important Linux CLI practices for Python backend teams - fast, safe terminal workflows on servers and laptops.
-
Prefer SIGTERM over SIGKILL: Allow uvicorn/Gunicorn to drain connections before
kill -9(Process & Resource Management). -
Run APIs under systemd or Kubernetes: Not naked
nohupin SSH sessions - survives disconnects and reboots. -
Persist ops with tmux: Long migrations and log tails survive laptop sleep (SSH & Remote Work).
-
Allow SSH before enabling firewall: Open port 22 (or bastion path) before
ufw enable- avoid lockout. -
Non-root service user: Run Python on high ports behind nginx/caddy - never as root for port 80.
-
Diagnose with journalctl:
systemctl statusthenjournalctl -u <unit> -n 200on VMs (Sysadmin Essentials). -
Lock down secret files:
chmod 600on.envand credential files. -
Prefer ripgrep in repos:
rgrespects.gitignoreand skips.venv/(Search & Regex). -
Scope find and grep: Never search from
/unfiltered - start at/var/log/appor project root. -
Use jq on JSON logs: Filter
level,request_id,duration_ms- notgrep Erroron structured lines (Pipes & Text Processing). -
curl -sf for health smoke: Scripts fail on 5xx; add
-w time_totalfor latency spot checks. -
ss replaces netstat:
ss -tlnpfor listening ports and backlog. -
lsof for port conflicts:
lsof -i :8000before killing random python PIDs. -
Start bash scripts with
set -euo pipefail: Fail fast; catch pipeline errors. -
Use
$()not backticks: Nested command substitution and clearer quoting. -
Redirect stderr in logs:
cmd > out.log 2>&1for post-mortem bundles. -
Use
uv sync --frozenin deploy: Reproducible env from lockfile - notpip install -rwithout hash. -
pipx for global CLIs: ruff, httpie, copier isolated from project venv (Python-in-the-Shell).
-
Never sudo pip: Breaks distro Python - venv/uv only.
-
ProxyJump in SSH config: Document bastion path for staging/prod - no ad-hoc IP typing.
-
LocalForward bind 127.0.0.1: Database tunnels not exposed on all interfaces.
-
df and du before deploy: Disk full breaks log writes and uploads.
-
Commit smoke scripts to
bin/: Same curl health checks locally, in CI, and post-deploy SSH. -
Promote repeated aliases to scripts: Versioned
bin/with review beats personal shell only. -
LC_ALL=C for ASCII logs: Predictable sort/awk when grepping access logs.
FAQs
htop or top?
htop interactive default; top when minimal image lacks htop package.
bash scripts vs Python ops?
Shell for glue on server; Python when logic exceeds ~20 lines or needs tests in repo.
Windows developers?
WSL2 for same CLI doc; production triage still Linux SSH.
Log tail in K8s?
kubectl logs -f deploy/billing-api - same jq filters on container stdout.
Related
- Robust Scripts - bash patterns
- Deploying FastAPI - production commands
- CI/CD Pipelines - parity with local
- Production Debugging - incident tools
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.