gates / gates (push) Successful in 6m30s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
19 lines
1.3 KiB
Python
19 lines
1.3 KiB
Python
#!/usr/bin/env python3
|
|
"""mounts.py — every media app's (and the file browser's) bind mounts under /mnt/felhom-drives, and whether its own
|
|
mount table holds a dead drive (`shutdown`). Run INSIDE the guest. Also: the controller's override files."""
|
|
import json, os, subprocess
|
|
def sh(c): return subprocess.run(c, shell=True, capture_output=True, text=True).stdout.strip()
|
|
for c in ("sonarr", "radarr", "qbittorrent", "transmission", "plex", "jellyfin", "prowlarr", "filebrowser"):
|
|
if not sh(f"docker ps -q -f name=^{c}$"):
|
|
print(f"{c:12} not running"); continue
|
|
ms = json.loads(sh(f"docker inspect {c} -f '{{{{json .Mounts}}}}'") or "[]")
|
|
binds = sorted(f"{m['Destination']}{'' if m.get('RW') else ':ro'}" for m in ms if m.get("Type") == "bind" and m["Source"].startswith("/mnt/felhom-drives"))
|
|
mi = sh(f"docker exec {c} cat /proc/self/mountinfo")
|
|
dead = sorted({l.split()[4] for l in mi.splitlines() if " - " in l and "shutdown" in l.split(" - ")[1].split()[2:3][0].split(",")} if mi else set())
|
|
started = sh(f"docker inspect {c} -f '{{{{.State.StartedAt}}}}'")[:19]
|
|
print(f"{c:12} started={started} binds={binds} dead={dead}")
|
|
for d in sorted(os.listdir("/opt/docker/stacks")):
|
|
p = f"/opt/docker/stacks/{d}/docker-compose.override.yml"
|
|
if os.path.exists(p):
|
|
print(f"override {d}:\n" + open(p).read())
|