diff --git a/VERSION b/VERSION index d324349..04cc999 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.15.5 +1.15.6 diff --git a/VERSIONS.md b/VERSIONS.md index 47658fb..9ca820d 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -17,6 +17,7 @@ Git tags: `vMAJOR.FEATURE.FIX` (e.g. `v1.8.0`). File `VERSION` omits the `v` pre | Tag | Date (UTC) | Notes | |-----|------------|--------| +| **v1.15.6** | 2026-07-19 | **Bugfix:** aptdeploy ERROR jump list is self-contained — systemd httpd failures include before/after state, Result/SubState, failed units, and journal snippets (no more vague «see systemd lines»); ldd/--version errors embed concrete missing libs / exit output. | | **v1.15.5** | 2026-07-19 | **Bugfix:** devtesting CHF ladder — `ssh` was draining ladder stdin (only rung 1/23 ran → progress 45/98 then snap 52/52); use `ssh -n` + `mapfile`; incomplete ladder is WARN not false complete. | | **v1.15.4** | 2026-07-19 | **Bugfix:** French sticky titles — page label *surveillance*, stack summary *public + interne*, SUMMARY verdict/totals via i18n (`tout est clair`, `totaux :`). | | **v1.15.3** | 2026-07-19 | **Bugfix:** console language auto-**fr** for `*lefrancpaysan*` domains again — env `TALER_MON_LANG=en` no longer locks English; only `--lang` / `TALER_MON_LANG_SET=1` is explicit. | diff --git a/check_apt_deploy.sh b/check_apt_deploy.sh index 54d5704..e7bc488 100755 --- a/check_apt_deploy.sh +++ b/check_apt_deploy.sh @@ -127,7 +127,7 @@ _merchant_ver() { check_ldd_deep() { local name=$1 - local out + local out missing out=$("$PODMAN_BIN" exec "$name" bash -lc ' set +e bin=$(command -v taler-merchant-httpd) @@ -147,15 +147,48 @@ check_ldd_deep() { info "ldd" "$line" done <<<"$out" if echo "$out" | grep -q 'not found'; then - err "ldd" "shared library missing in $name" "see ldd lines above" + missing=$(echo "$out" | grep 'not found' | tr '\n' ' ' | head -c 280) + err "ldd" "shared library missing in $name" "${missing:-not found (see ldd INFO above)}" return 1 fi return 0 } +# Build a single-line diagnosis for err() so jump lists are self-contained +# (operators should not need to hunt nearby INFO lines). +_apt_systemd_diagnose() { + local out="$1" + local before after failed journal status_line result + before=$(echo "$out" | sed -n 's/^httpd_active: //p' | tail -1) + after=$(echo "$out" | sed -n 's/^after_start_httpd: //p' | tail -1) + failed=$(echo "$out" | sed -n 's/^failed_taler: //p' | grep -v '^none$' | tr '\n' ';' | sed 's/;$//') + [ -z "$failed" ] && failed=$(echo "$out" | grep -E '^\s*●\s+taler-' | head -3 | tr '\n' ';' | sed 's/;$//') + result=$(echo "$out" | sed -n 's/^httpd_Result: //p' | tail -1) + [ -z "$result" ] && result=$(echo "$out" | sed -n 's/^ *Result: //p' | head -1) + status_line=$(echo "$out" | sed -n 's/^httpd_status_line: //p' | tail -1) + journal=$(echo "$out" | sed -n 's/^httpd_journal: //p' | tr '\n' ' ' | head -c 220) + # fallback: first non-meta journal-ish line + if [ -z "$journal" ]; then + journal=$(echo "$out" | grep -E 'taler-merchant-httpd\[[0-9]+\]|Failed|error|Error|NRestarts|Main PID' | head -3 | tr '\n' ' ' | head -c 220) + fi + local parts=() + [ -n "$before" ] && parts+=("before=${before}") + [ -n "$after" ] && parts+=("after_start=${after}") + [ -n "$result" ] && parts+=("Result=${result}") + [ -n "$status_line" ] && parts+=("status=${status_line}") + [ -n "$failed" ] && [ "$failed" != "none" ] && parts+=("failed_units=${failed}") + [ -n "$journal" ] && parts+=("journal=${journal}") + if [ "${#parts[@]}" -eq 0 ]; then + printf '%s' "no status/journal captured (podman exec empty?)" + return + fi + local IFS=' · ' + printf '%s' "${parts[*]}" +} + check_systemd() { local name=$1 - local out active_httpd + local out active_httpd before_httpd detail out=$("$PODMAN_BIN" exec "$name" bash -lc ' set +e echo "system: $(systemctl is-system-running 2>&1)" @@ -163,17 +196,50 @@ check_systemd() { echo "target_active: $(systemctl is-active taler-merchant.target 2>&1)" echo "httpd_active: $(systemctl is-active taler-merchant-httpd.service 2>&1)" echo "httpd_enabled: $(systemctl is-enabled taler-merchant-httpd.service 2>&1)" - systemctl start taler-merchant.target 2>&1 | tail -5 - sleep 2 + # unit properties help when is-active is only "activating"/"failed" + echo "httpd_Result: $(systemctl show -p Result --value taler-merchant-httpd.service 2>&1)" + echo "httpd_SubState: $(systemctl show -p SubState --value taler-merchant-httpd.service 2>&1)" + echo "httpd_NRestarts: $(systemctl show -p NRestarts --value taler-merchant-httpd.service 2>&1)" + echo "httpd_ExecMainStatus: $(systemctl show -p ExecMainStatus --value taler-merchant-httpd.service 2>&1)" + echo "httpd_ExecMainCode: $(systemctl show -p ExecMainCode --value taler-merchant-httpd.service 2>&1)" + # one-line status (Active: failed / activating (start) …) + systemctl status taler-merchant-httpd.service --no-pager -l 2>&1 | head -12 | while IFS= read -r sl; do + echo "httpd_status: $sl" + done + # compact single-line for err detail + st1=$(systemctl status taler-merchant-httpd.service --no-pager -l 2>&1 | sed -n "s/^ *Active: //p" | head -1) + echo "httpd_status_line: ${st1:-?}" + systemctl start taler-merchant.target 2>&1 | tail -8 | while IFS= read -r sl; do + echo "start_target: $sl" + done + # wait longer: "activating" often clears only after dbinit + sleep 5 echo "after_start_target: $(systemctl is-active taler-merchant.target 2>&1)" echo "after_start_httpd: $(systemctl is-active taler-merchant-httpd.service 2>&1)" - systemctl --failed --no-legend 2>/dev/null | grep -i taler || echo "failed_taler: none" + echo "after_httpd_Result: $(systemctl show -p Result --value taler-merchant-httpd.service 2>&1)" + echo "after_httpd_SubState: $(systemctl show -p SubState --value taler-merchant-httpd.service 2>&1)" + # journal: last failure reasons (self-contained for ERROR jump list) + journalctl -u taler-merchant-httpd.service -n 12 --no-pager -o cat 2>/dev/null \ + | sed "/^$/d" | tail -8 | while IFS= read -r jl; do + echo "httpd_journal: $jl" + done + journalctl -u taler-merchant-dbinit.service -n 6 --no-pager -o cat 2>/dev/null \ + | sed "/^$/d" | tail -4 | while IFS= read -r jl; do + echo "dbinit_journal: $jl" + done + ft=$(systemctl --failed --no-legend 2>/dev/null | grep -i taler || true) + if [ -n "$ft" ]; then + echo "$ft" | while IFS= read -r fl; do echo "failed_taler: $fl"; done + else + echo "failed_taler: none" + fi ' 2>/dev/null || echo "systemd probe failed") while IFS= read -r line; do [ -n "$line" ] || continue info "systemd" "$line" done <<<"$out" + before_httpd=$(echo "$out" | sed -n 's/^httpd_active: //p' | tail -1) active_httpd=$(echo "$out" | sed -n 's/^after_start_httpd: //p' | tail -1) # export for caller board APT_LAST_HTTPD="${active_httpd:-?}" @@ -181,7 +247,17 @@ check_systemd() { ok "systemd httpd" "taler-merchant-httpd active after start taler-merchant.target" return 0 fi - err "systemd httpd" "taler-merchant-httpd not active" "after_start_httpd=${active_httpd:-?} · see systemd lines" + detail=$(_apt_systemd_diagnose "$out") + # Prefer after_* Result if present + local after_result after_sub + after_result=$(echo "$out" | sed -n 's/^after_httpd_Result: //p' | tail -1) + after_sub=$(echo "$out" | sed -n 's/^after_httpd_SubState: //p' | tail -1) + [ -n "$after_result" ] && [ "$after_result" != "success" ] && detail="${detail} · after_Result=${after_result}" + [ -n "$after_sub" ] && detail="${detail} · after_SubState=${after_sub}" + # Human one-liner for jump list (no "see …" without content) + err "systemd httpd" \ + "taler-merchant-httpd not active (container=${name})" \ + "${detail}" return 1 } @@ -221,18 +297,21 @@ check_merchant_basics() { done <<<"$out" if echo "$out" | grep -qi 'error while loading shared libraries'; then - err "httpd" "shared library error on --version" "see basics/ldd" + local lib_err + lib_err=$(echo "$out" | grep -i 'error while loading shared libraries' | head -1 | tr '\n' ' ' | head -c 240) + err "httpd" "shared library error on --version" "${lib_err:-see basics INFO lines}" return 1 fi set +e - "$PODMAN_BIN" exec "$name" taler-merchant-httpd --version >/dev/null 2>&1 - local ec=$? + local ver_out ec + ver_out=$("$PODMAN_BIN" exec "$name" taler-merchant-httpd --version 2>&1) + ec=$? set -e if [ "$ec" -eq 0 ]; then ok "httpd --version" "exit 0" else - err "httpd --version" "exit $ec" + err "httpd --version" "exit $ec" "$(printf '%s' "$ver_out" | tr '\n' ' ' | head -c 240)" return 1 fi @@ -308,9 +387,10 @@ check_one() { if ! check_systemd "$name"; then c_fail=1 httpd="${APT_LAST_HTTPD:-FAIL}" + note="${note:+$note; }httpd=${httpd}" # deeper ldd if httpd failed if [ "$ldd" != "FAIL" ]; then - check_ldd_deep "$name" || { ldd="FAIL"; c_fail=1; } + check_ldd_deep "$name" || { ldd="FAIL"; c_fail=1; note="${note:+$note; }ldd"; } fi else httpd="active"