From fa73cc3cd73890110f8f78a1a6b02a8f9cba066d Mon Sep 17 00:00:00 2001 From: Jamie T Date: Fri, 10 Jul 2026 12:27:57 -0400 Subject: [PATCH 1/3] mqtt.sh: silence orb summary's stderr banner on every poll orb summary logs its startup boilerplate (env vars, config dir, 'Starting Orb' signature) to stderr on every invocation, independent of the actual JSON payload it emits on stdout. At the default 5s mqtt_frequency this generates 3 log lines/poll (~50k+/day) that get captured by Docker's log driver and, on hosts using journald for container logs, amplified into disproportionate disk write volume via journald's per-entry index rewriting. stdout carries the full JSON summary either way; jq only ever reads stdout, so redirecting stderr to /dev/null here has no effect on the data published to MQTT. --- docker/mqtt.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docker/mqtt.sh b/docker/mqtt.sh index 720366d..5c05bd0 100644 --- a/docker/mqtt.sh +++ b/docker/mqtt.sh @@ -117,7 +117,10 @@ while true; do sleep "$MQTT_PAUSE" # output a single line to mosquitto_pub - (/app/orb summary || echo '{}') | jq -c . + # orb summary logs its startup banner to stderr on every invocation; only + # stdout carries the JSON payload jq needs, so drop stderr here to avoid + # flooding the host's journal with a repeated banner every MQTT_PAUSE seconds + (/app/orb summary 2>/dev/null || echo '{}') | jq -c . done | mosquitto_pub -h "$MQTT_HOST" -p "$MQTT_PORT" -u "$MQTT_USER" -P "$MQTT_PASS" \ -t "$STATE_TOPIC" -l -r -k $((MQTT_PAUSE * 2)) From 4daa967494207c7902588967e25692ae261d6ad9 Mon Sep 17 00:00:00 2001 From: Jamie T Date: Fri, 10 Jul 2026 13:00:47 -0400 Subject: [PATCH 2/3] mqtt.sh: only silence orb summary's stderr when mqtt_debug is off The unconditional 2>/dev/null redirect also hid the child process's own logs when mqtt_debug is enabled, which defeats the point of turning debugging on. Gate it on DEBUG_MODE instead: suppressed by default, but let through to the addon's own stderr when mqtt_debug is true. --- docker/mqtt.sh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docker/mqtt.sh b/docker/mqtt.sh index 5c05bd0..1ddf5c7 100644 --- a/docker/mqtt.sh +++ b/docker/mqtt.sh @@ -109,6 +109,17 @@ for entity in $CLEANUP_ENTITIES; do -t "$DISCOVERY_TOPIC" -n -r done +# orb summary logs its startup banner to stderr on every invocation; only +# stdout carries the JSON payload jq needs. That banner repeating every +# MQTT_PAUSE seconds floods the host's journal, so route it to /dev/null by +# default -- but keep it when mqtt_debug is on, since debugging should show +# the child process's own logs rather than silently dropping them. +if [ "$DEBUG_MODE" = "true" ]; then + exec 3>&2 +else + exec 3>/dev/null +fi + # mosquitto_pub -l keeps the connection open and publishes each line of input, outer loop # reconnects on drop, use keep-alive larger than MQTT_PAUSE to avoid needless pings. while true; do @@ -117,10 +128,7 @@ while true; do sleep "$MQTT_PAUSE" # output a single line to mosquitto_pub - # orb summary logs its startup banner to stderr on every invocation; only - # stdout carries the JSON payload jq needs, so drop stderr here to avoid - # flooding the host's journal with a repeated banner every MQTT_PAUSE seconds - (/app/orb summary 2>/dev/null || echo '{}') | jq -c . + (/app/orb summary 2>&3 || echo '{}') | jq -c . done | mosquitto_pub -h "$MQTT_HOST" -p "$MQTT_PORT" -u "$MQTT_USER" -P "$MQTT_PASS" \ -t "$STATE_TOPIC" -l -r -k $((MQTT_PAUSE * 2)) From 55c0b1e1af7645671363799ee78fb0c4231afd18 Mon Sep 17 00:00:00 2001 From: Jamie T Date: Fri, 10 Jul 2026 13:32:29 -0400 Subject: [PATCH 3/3] mqtt.sh: capture orb summary stderr, replay it on failure or in debug mode Co-Authored-By: Claude Sonnet 4.6 --- docker/mqtt.sh | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/docker/mqtt.sh b/docker/mqtt.sh index 1ddf5c7..4cdef70 100644 --- a/docker/mqtt.sh +++ b/docker/mqtt.sh @@ -109,17 +109,6 @@ for entity in $CLEANUP_ENTITIES; do -t "$DISCOVERY_TOPIC" -n -r done -# orb summary logs its startup banner to stderr on every invocation; only -# stdout carries the JSON payload jq needs. That banner repeating every -# MQTT_PAUSE seconds floods the host's journal, so route it to /dev/null by -# default -- but keep it when mqtt_debug is on, since debugging should show -# the child process's own logs rather than silently dropping them. -if [ "$DEBUG_MODE" = "true" ]; then - exec 3>&2 -else - exec 3>/dev/null -fi - # mosquitto_pub -l keeps the connection open and publishes each line of input, outer loop # reconnects on drop, use keep-alive larger than MQTT_PAUSE to avoid needless pings. while true; do @@ -127,8 +116,22 @@ while true; do # sleep first to avoid publishing zeroes on first iteration sleep "$MQTT_PAUSE" - # output a single line to mosquitto_pub - (/app/orb summary 2>&3 || echo '{}') | jq -c . + # output a single line to mosquitto_pub. orb summary prints a startup + # banner to stderr on every invocation, which would flood the journal at + # MQTT_PAUSE cadence -- so capture stderr in a variable (fd 3 carries the + # real stdout out of the command substitution) and only replay it when + # orb fails (it's the only diagnostic we have then) or mqtt_debug is on. + { + ORB_ERRS=$(/app/orb summary 2>&1 >&3) + ORB_RC=$? + if [ "$ORB_RC" -ne 0 ]; then + echo "orb summary failed (exit $ORB_RC):" >&2 + [ -n "$ORB_ERRS" ] && printf '%s\n' "$ORB_ERRS" >&2 + echo '{}' + elif [ "$DEBUG_MODE" = "true" ] && [ -n "$ORB_ERRS" ]; then + printf '%s\n' "$ORB_ERRS" >&2 + fi + } 3>&1 | jq -c . done | mosquitto_pub -h "$MQTT_HOST" -p "$MQTT_PORT" -u "$MQTT_USER" -P "$MQTT_PASS" \ -t "$STATE_TOPIC" -l -r -k $((MQTT_PAUSE * 2))