Files
felhom.eu/documentation/audits/prowlarr-2026-10-15/tools/bench_first_start.sh
T
adminandClaude Opus 5.5 2f1f6c8052
gates / gates (push) Successful in 6m34s
Prowlarr evidence (R-1048) + its apps-page card; the stated app count 62 -> 63; R-1057 filed
- documentation/audits/prowlarr-2026-10-15/: bench (update test proven, C3 failed as it must, soak 7.6 %,
  volume-persistence CLEAN, official-image check), 9202 runs 1-3 (run 1's bump emptied the drill .felhom.yml — a
  test-tool bug, fixed; run 3 re-proved the step and backup -> remove -> restore with the full template), tools.
- website: a Prowlarr card on both apps pages; every stated count 62 -> 63, the media group 19 -> 20; sizing.json +
  sizing-data.json carry Prowlarr (41/44 MB, onboarding), the sizing test and SIZING.md table moved to 63 apps.
- OPEN-ITEMS: R-1057 (a restore of a removed gated app returns without the gate, even from a backup made before the
  setup — measured on 9202); R-1036 notes the count and that wger/plant-it are hidden/abandoned.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 12:58:18 +02:00

26 lines
2.9 KiB
Bash

#!/bin/bash
# bench_first_start.sh <image> — Prowlarr's first start on the bench (LXC 9401), measured. A throwaway container
# `prowlarr-probe` with a throwaway volume `prowlarr-probe-config`; both removed at the end. Swap is off on the bench.
set -u
IMG=$1; C=prowlarr-probe; V=prowlarr-probe-config
docker rm -f $C >/dev/null 2>&1; docker volume rm $V >/dev/null 2>&1
echo "== image"; docker pull -q $IMG; docker image inspect $IMG -f 'id={{.Id}} digest={{index .RepoDigests 0}} size={{.Size}} arch={{.Architecture}}'
echo "== tools in the image (one per run)"
for t in curl wget sh bash python3 node; do echo "$t: $(docker run --rm --entrypoint sh $IMG -c "command -v $t" 2>/dev/null)"; done
echo "== the service's run script (linuxserver s6)"; docker run --rm --entrypoint sh $IMG -c 'cat /etc/s6-overlay/s6-rc.d/svc-prowlarr/run 2>/dev/null; ls /etc/s6-overlay/s6-rc.d/ | grep -i prowlarr'
docker volume create $V >/dev/null
CID=$(docker create --name $C -e TZ=Europe/Budapest -e PUID=1000 -e PGID=1000 -e UMASK=002 --memory 512m -v $V:/config $IMG)
docker start $C >/dev/null; T0=$(date +%s)
CG=$(find /sys/fs/cgroup -type d -name "*$CID*" 2>/dev/null | head -1)
echo "== memory from birth (cgroup $CG), every 2 s for 150 s"
peak=0; for i in $(seq 1 75); do a=$(awk '$1=="anon"{print $2}' $CG/memory.stat 2>/dev/null); [ -n "$a" ] && [ "$a" -gt "$peak" ] && peak=$a; sleep 2; done
echo "peak anon $((peak/1048576)) MiB; oom_kill $(awk '$1=="oom_kill"{print $2}' $CG/memory.events); restarts $(docker inspect $C -f '{{.RestartCount}}'); health-like: $(docker exec $C curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:9696/ping)"
echo "== process list"; docker exec $C ps -o pid,user,args | head -12
echo "== config.xml after the first start (ApiKey redacted)"; docker exec $C cat /config/config.xml | sed -E 's#<ApiKey>[^<]+#<ApiKey><redacted>#'
K=$(docker exec $C sed -n 's#.*<ApiKey>\([^<]*\)</ApiKey>.*#\1#p' /config/config.xml)
echo "== host config through the app's own API (analytics, update, auth)"; docker exec $C curl -s -H "X-Api-Key: $K" http://127.0.0.1:9696/api/v1/config/host | python3 -c "import json,sys; d=json.load(sys.stdin); print({k:d.get(k) for k in ('analyticsEnabled','updateAutomatically','updateMechanism','authenticationMethod','authenticationRequired','bindAddress','port','proxyEnabled','logLevel')})" 2>/dev/null || echo "(no python3 in the bench shell? raw:)"
echo "== open TCP connections from the container (after 150 s)"; docker exec $C sh -c 'cat /proc/net/tcp /proc/net/tcp6 2>/dev/null | awk "NR>1 && \$4==\"01\" {print \$3}" | sort -u'
echo "== first-start log (60 lines)"; docker logs $C 2>&1 | head -60 | sed -E 's#[A-Fa-f0-9]{32}#<hex32>#g'
echo "== files the app wrote under /config"; docker exec $C sh -c 'find /config -maxdepth 2 | head -30'
docker rm -f $C >/dev/null; docker volume rm $V >/dev/null; echo "== removed: $(docker ps -aq -f name=$C | wc -l) containers, $(docker volume ls -q -f name=$V | wc -l) volumes"