fix(install): log why compose up failed instead of just "exit 1"
navidrome's install died on 2026-08-01 and left no explanation: the log had only "Started container for navidrome (exit 1, up_app.sh:130)". The compose output was captured into `result` and never read, and stderr was not captured at all — so the one thing that says WHY (image pull EOF, port clash, missing external network) was thrown away at the moment it mattered. Capture stderr and print the tail of the output on failure, before checkSuccess (which can exit). Both the rootless and rooted call sites. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
7fae6bc308
commit
1c3af5a533
@ -1,5 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Print the compose output when `up -d` failed, so the log records WHY.
|
||||
# Without this the only trace of a failed app install was "Started container for
|
||||
# <app> (exit 1, up_app.sh:130)" — the compose output was captured into a
|
||||
# variable and dropped. That is the difference between "navidrome's install
|
||||
# failed because the image pull died" and a mystery nobody can answer ten days
|
||||
# later. Tail-capped: a Dockerfile build can emit hundreds of lines, and the
|
||||
# failure is always at the end. Called BEFORE checkSuccess, which may exit.
|
||||
_upReportComposeFailure()
|
||||
{
|
||||
local app_name="$1" rc="$2" output="$3"
|
||||
(( rc == 0 )) && return 0
|
||||
[[ -z "$output" ]] && { isNotice "docker compose gave no output for $app_name (exit $rc)."; return 0; }
|
||||
isNotice "docker compose output for $app_name (exit $rc):"
|
||||
local _l
|
||||
while IFS= read -r _l; do
|
||||
[[ -n "$_l" ]] && isNotice " $_l"
|
||||
done <<< "$(printf '%s\n' "$output" | tail -20)"
|
||||
}
|
||||
|
||||
dockerComposeUp()
|
||||
{
|
||||
local app_name="$1"
|
||||
@ -122,16 +141,18 @@ dockerComposeUp()
|
||||
fi
|
||||
if [[ $CFG_DOCKER_INSTALL_TYPE == "rootless" ]]; then
|
||||
isNotice "Starting container for $app_name, this may take a while..."
|
||||
local result; result=$(dockerCommandRunInstallUser "cd $containers_dir$app_name && COMPOSE_PROGRESS=plain docker compose $setup_compose up $_compose_quiet $_compose_build_flag -d")
|
||||
local result; result=$(dockerCommandRunInstallUser "cd $containers_dir$app_name && COMPOSE_PROGRESS=plain docker compose $setup_compose up $_compose_quiet $_compose_build_flag -d" 2>&1)
|
||||
_rc=$?
|
||||
_upReportComposeFailure "$app_name" "$_rc" "$result"
|
||||
# Restore $? to the compose exit code — a bare `checkSuccess`
|
||||
# after `_rc=$?` would read the assignment's 0 and always print
|
||||
# success, hiding a failed `up -d` (e.g. an image pull EOF).
|
||||
( exit "$_rc" ); checkSuccess "Started container for $app_name"
|
||||
elif [[ $CFG_DOCKER_INSTALL_TYPE == "rooted" ]]; then
|
||||
isNotice "Starting container for $app_name, this may take a while..."
|
||||
local result; result=$(cd "$containers_dir$app_name" && COMPOSE_PROGRESS=plain docker compose $setup_compose up $_compose_quiet $_compose_build_flag -d)
|
||||
local result; result=$(cd "$containers_dir$app_name" && COMPOSE_PROGRESS=plain docker compose $setup_compose up $_compose_quiet $_compose_build_flag -d 2>&1)
|
||||
_rc=$?
|
||||
_upReportComposeFailure "$app_name" "$_rc" "$result"
|
||||
( exit "$_rc" ); checkSuccess "Started container for $app_name"
|
||||
fi
|
||||
# Used for the CLI dockertype switcher.
|
||||
|
||||
@ -937,6 +937,7 @@ declare -gA LP_FN_MAP=(
|
||||
[updaterSetAnchorRef]="cli/commands/updater/cli_updater_commands.sh"
|
||||
[updaterTagOf]="webui/data/generators/updater/webui_updater_scan.sh"
|
||||
[updateTaskFields]="task/crontab_task_processor.sh"
|
||||
[_upReportComposeFailure]="docker/app/compose/up_app.sh"
|
||||
[userExists]="function/checks/user_exists.sh"
|
||||
[validateContainerHealth]="task/crontab_check_processor.sh"
|
||||
[validateDirectoryStructure]="task/crontab_check_processor.sh"
|
||||
@ -1949,6 +1950,7 @@ declare -gA LP_FN_ROOT=(
|
||||
[updaterSetAnchorRef]="scripts"
|
||||
[updaterTagOf]="scripts"
|
||||
[updateTaskFields]="scripts"
|
||||
[_upReportComposeFailure]="scripts"
|
||||
[userExists]="scripts"
|
||||
[validateContainerHealth]="scripts"
|
||||
[validateDirectoryStructure]="scripts"
|
||||
@ -2994,6 +2996,7 @@ updaterRollbackApp() { unset -f updaterRollbackApp; __lpAutoload "${install_scri
|
||||
updaterSetAnchorRef() { unset -f updaterSetAnchorRef; __lpAutoload "${install_scripts_dir}cli/commands/updater/cli_updater_commands.sh"; updaterSetAnchorRef "$@"; }
|
||||
updaterTagOf() { unset -f updaterTagOf; __lpAutoload "${install_scripts_dir}webui/data/generators/updater/webui_updater_scan.sh"; updaterTagOf "$@"; }
|
||||
updateTaskFields() { unset -f updateTaskFields; __lpAutoload "${install_scripts_dir}task/crontab_task_processor.sh"; updateTaskFields "$@"; }
|
||||
_upReportComposeFailure() { unset -f _upReportComposeFailure; __lpAutoload "${install_scripts_dir}docker/app/compose/up_app.sh"; _upReportComposeFailure "$@"; }
|
||||
userExists() { unset -f userExists; __lpAutoload "${install_scripts_dir}function/checks/user_exists.sh"; userExists "$@"; }
|
||||
validateContainerHealth() { unset -f validateContainerHealth; __lpAutoload "${install_scripts_dir}task/crontab_check_processor.sh"; validateContainerHealth "$@"; }
|
||||
validateDirectoryStructure() { unset -f validateDirectoryStructure; __lpAutoload "${install_scripts_dir}task/crontab_check_processor.sh"; validateDirectoryStructure "$@"; }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user