From dbdc7ddb2408db1c5306ee1952c882110df610e0 Mon Sep 17 00:00:00 2001 From: Stephen Shaw Date: Thu, 28 May 2026 11:15:11 -0600 Subject: [PATCH] Add procps to fix ps: command not found during self-update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The official RoonServer Docker image was missing the procps package, so the stock RoonServer self-update launcher failed at line 56 with "ps: command not found" while killing stale RAATServer processes: for i in $(ps -Awwo pid,args | grep '[R]AATServer' | awk '{print $1}'); do kill -9 $i; done That script is bundled with RoonServer and downloaded at runtime, so we can't refactor it to pkill — the fix is to provide a real ps by adding procps to the runtime dependencies. The healthcheck still reads /proc directly and does not depend on procps. Also assert the ps runtime contract in tests/smoke.sh so a future dependency change can't silently drop procps and reintroduce this bug: one check that ps exists, and one that `ps -Awwo pid,args` (the exact flags the launcher uses) executes. The invocation check asserts ps's own exit code rather than piping through grep|awk, whose exit would be 0 even if ps were missing. Verified in a built image: ps resolves to /usr/bin/ps (procps-ng 4.0.4), the pipeline runs, and the full smoke suite passes (58/0). Fixes RRD-1551 --- Dockerfile | 3 ++- tests/smoke.sh | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5466e15..4e43ffa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,10 +26,11 @@ LABEL org.opencontainers.image.licenses="Proprietary" # libfreetype6 — provides libfreetype.so.6 soname that bundled libharfbuzz links against # cifs-utils — SMB/CIFS network share mounting # ca-certificates — HTTPS for streaming services and cloud APIs +# procps — provides ps, required by RoonServer's self-update script RUN apt-get update \ && apt-get -y install --no-install-recommends \ bash curl xz-utils bzip2 tzdata libicu76 \ - libasound2t64 libfreetype6 cifs-utils ca-certificates \ + libasound2t64 libfreetype6 cifs-utils ca-certificates procps \ && (chmod u-s /usr/sbin/mount.cifs 2>/dev/null || true) \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/log/apt /var/log/dpkg.log \ diff --git a/tests/smoke.sh b/tests/smoke.sh index 204c674..eb9f0a0 100755 --- a/tests/smoke.sh +++ b/tests/smoke.sh @@ -40,6 +40,19 @@ for bin in bash curl bzip2 tar ffmpeg; do docker run --rm --entrypoint which "$IMAGE" "$bin" done +# ps (procps) is a runtime contract: RoonServer's bundled self-update +# launcher runs `ps -Awwo pid,args | grep '[R]AATServer' | awk ...` to +# kill stale RAATServer processes. A missing procps silently breaks +# updates (RRD-1551), so assert both the binary and that the pipeline runs. +check "ps is available (procps — RoonServer self-update)" \ + docker run --rm --entrypoint which "$IMAGE" ps + +# Exercise the exact flags the launcher uses. Checking ps's own exit code +# (not the pipeline's) is deliberate: a missing/broken ps must fail here, +# whereas the full pipeline's exit is awk's, which is 0 even when ps errors. +check "ps self-update invocation runs (ps -Awwo pid,args)" \ + docker run --rm --entrypoint ps "$IMAGE" -Awwo pid,args + # FFmpeg is a static binary from johnvansickle.com — verify it actually # executes on this image's glibc/kernel ABI, not just that the file exists. check "ffmpeg runs (static binary ABI-compatible)" \