diff --git a/misc/build.func b/misc/build.func index b1ce4fdf3..d150d909f 100644 --- a/misc/build.func +++ b/misc/build.func @@ -118,7 +118,7 @@ maxkeys_check() { # Exit if kernel parameters are unavailable if [[ "$per_user_maxkeys" -eq 0 || "$per_user_maxbytes" -eq 0 ]]; then - echo -e "${CROSS}${RD} Error: Unable to read kernel parameters. Ensure proper permissions.${CL}" + msg_error "Unable to read kernel key parameters. Ensure proper permissions." exit 1 fi @@ -135,19 +135,19 @@ maxkeys_check() { # Check if key or byte usage is near limits failure=0 if [[ "$used_lxc_keys" -gt "$threshold_keys" ]]; then - echo -e "${CROSS}${RD} Warning: Key usage is near the limit (${used_lxc_keys}/${per_user_maxkeys}).${CL}" + msg_warn "Key usage is near the limit (${used_lxc_keys}/${per_user_maxkeys})" echo -e "${INFO} Suggested action: Set ${GN}kernel.keys.maxkeys=${new_limit_keys}${CL} in ${BOLD}/etc/sysctl.d/98-community-scripts.conf${CL}." failure=1 fi if [[ "$used_lxc_bytes" -gt "$threshold_bytes" ]]; then - echo -e "${CROSS}${RD} Warning: Key byte usage is near the limit (${used_lxc_bytes}/${per_user_maxbytes}).${CL}" + msg_warn "Key byte usage is near the limit (${used_lxc_bytes}/${per_user_maxbytes})" echo -e "${INFO} Suggested action: Set ${GN}kernel.keys.maxbytes=${new_limit_bytes}${CL} in ${BOLD}/etc/sysctl.d/98-community-scripts.conf${CL}." failure=1 fi # Provide next steps if issues are detected if [[ "$failure" -eq 1 ]]; then - echo -e "${INFO} To apply changes, run: ${BOLD}service procps force-reload${CL}" + msg_error "Kernel key limits exceeded - see suggestions above" exit 1 fi @@ -2034,6 +2034,7 @@ advanced_settings() { ((STEP++)) else whiptail --msgbox "Default bridge 'vmbr0' not found!\n\nPlease configure a network bridge in Proxmox first." 10 58 + msg_error "Default bridge 'vmbr0' not found" exit 1 fi else @@ -3049,7 +3050,7 @@ install_script() { CHOICE="" ;; *) - echo -e "${CROSS}${RD}Invalid option: $CHOICE${CL}" + msg_error "Invalid option: $CHOICE" exit 1 ;; esac @@ -3128,12 +3129,12 @@ check_container_resources() { current_cpu=$(nproc) if [[ "$current_ram" -lt "$var_ram" ]] || [[ "$current_cpu" -lt "$var_cpu" ]]; then - echo -e "\n${INFO}${HOLD} ${GN}Required: ${var_cpu} CPU, ${var_ram}MB RAM ${CL}| ${RD}Current: ${current_cpu} CPU, ${current_ram}MB RAM${CL}" + msg_warn "Under-provisioned: Required ${var_cpu} CPU/${var_ram}MB RAM, Current ${current_cpu} CPU/${current_ram}MB RAM" echo -e "${YWB}Please ensure that the ${APP} LXC is configured with at least ${var_cpu} vCPU and ${var_ram} MB RAM for the build process.${CL}\n" echo -ne "${INFO}${HOLD} May cause data loss! ${INFO} Continue update with under-provisioned LXC? " read -r prompt if [[ ! ${prompt,,} =~ ^(yes)$ ]]; then - echo -e "${CROSS}${HOLD} ${YWB}Exiting based on user input.${CL}" + msg_error "Aborted: under-provisioned LXC (${current_cpu} CPU/${current_ram}MB RAM < ${var_cpu} CPU/${var_ram}MB RAM)" exit 1 fi else @@ -3152,11 +3153,11 @@ check_container_storage() { local used_size=$(df /boot --output=used | tail -n 1) usage=$((100 * used_size / total_size)) if ((usage > 80)); then - echo -e "${INFO}${HOLD} ${YWB}Warning: Storage is dangerously low (${usage}%).${CL}" + msg_warn "Storage is dangerously low (${usage}% used on /boot)" echo -ne "Continue anyway? " read -r prompt if [[ ! ${prompt,,} =~ ^(y|yes)$ ]]; then - echo -e "${CROSS}${HOLD}${YWB}Exiting based on user input.${CL}" + msg_error "Aborted: storage too low (${usage}% used)" exit 1 fi fi @@ -3546,10 +3547,16 @@ build_container() { # Build PCT_OPTIONS as string for export TEMP_DIR=$(mktemp -d) pushd "$TEMP_DIR" >/dev/null + local _func_url if [ "$var_os" == "alpine" ]; then - export FUNCTIONS_FILE_PATH="$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/alpine-install.func)" + _func_url="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/alpine-install.func" else - export FUNCTIONS_FILE_PATH="$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/install.func)" + _func_url="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/install.func" + fi + export FUNCTIONS_FILE_PATH="$(curl -fsSL "$_func_url")" + if [[ -z "$FUNCTIONS_FILE_PATH" || ${#FUNCTIONS_FILE_PATH} -lt 100 ]]; then + msg_error "Failed to download install functions from: $_func_url" + exit 1 fi # Core exports for install.func @@ -3920,7 +3927,9 @@ EOF fi sleep 1 if [ "$i" -eq 10 ]; then - msg_error "LXC Container did not reach running state" + local ct_status + ct_status=$(pct status "$CTID" 2>/dev/null || echo "unknown") + msg_error "LXC Container did not reach running state (status: ${ct_status})" exit 1 fi done @@ -3944,7 +3953,7 @@ EOF if [ -z "$ip_in_lxc" ]; then msg_error "No IP assigned to CT $CTID after 20s" - echo -e "${YW}Troubleshooting:${CL}" + msg_custom "🔧" "${YW}" "Troubleshooting:" echo " • Verify bridge ${BRG} exists and has connectivity" echo " • Check if DHCP server is reachable (if using DHCP)" echo " • Verify static IP configuration (if using static IP)" @@ -3966,8 +3975,7 @@ EOF done if [ "$ping_success" = false ]; then - msg_warn "Network configured (IP: $ip_in_lxc) but connectivity test failed" - echo -e "${YW}Container may have limited internet access. Installation will continue...${CL}" + msg_warn "Network configured (IP: $ip_in_lxc) but connectivity test failed - installation will continue" else msg_ok "Network in LXC is reachable (ping)" fi @@ -4011,7 +4019,10 @@ EOF http://dl-cdn.alpinelinux.org/alpine/latest-stable/main http://dl-cdn.alpinelinux.org/alpine/latest-stable/community EOF' - pct exec "$CTID" -- ash -c "apk add bash newt curl openssh nano mc ncurses jq >/dev/null" + pct exec "$CTID" -- ash -c "apk add bash newt curl openssh nano mc ncurses jq >/dev/null" || { + msg_error "Failed to install base packages in Alpine container" + exit 1 + } else sleep 3 LANG=${LANG:-en_US.UTF-8} @@ -4908,8 +4919,7 @@ create_lxc_container() { return 0 fi - echo - echo "An update for the Proxmox LXC stack is available:" + msg_info "An update for the Proxmox LXC stack is available" echo " pve-container: installed=${_pvec_i:-n/a} candidate=${_pvec_c:-n/a}" echo " lxc-pve : installed=${_lxcp_i:-n/a} candidate=${_lxcp_c:-n/a}" echo @@ -4961,7 +4971,6 @@ create_lxc_container() { exit 205 } if qm status "$CTID" &>/dev/null || pct status "$CTID" &>/dev/null; then - echo -e "ID '$CTID' is already in use." unset CTID msg_error "Cannot use ID that is already in use." exit 206 @@ -5019,17 +5028,40 @@ create_lxc_container() { msg_info "Validating storage '$CONTAINER_STORAGE'" STORAGE_TYPE=$(grep -E "^[^:]+: $CONTAINER_STORAGE$" /etc/pve/storage.cfg | cut -d: -f1 | head -1) + if [[ -z "$STORAGE_TYPE" ]]; then + msg_error "Storage '$CONTAINER_STORAGE' not found in /etc/pve/storage.cfg" + exit 213 + fi + case "$STORAGE_TYPE" in - iscsidirect) exit 212 ;; - iscsi | zfs) exit 213 ;; - cephfs) exit 219 ;; - pbs) exit 224 ;; + iscsidirect) + msg_error "Storage '$CONTAINER_STORAGE' uses iSCSI-direct which does not support container rootfs." + exit 212 + ;; + iscsi | zfs) + msg_error "Storage '$CONTAINER_STORAGE' ($STORAGE_TYPE) does not support container rootdir content." + exit 213 + ;; + cephfs) + msg_error "Storage '$CONTAINER_STORAGE' uses CephFS which is not supported for LXC rootfs." + exit 219 + ;; + pbs) + msg_error "Storage '$CONTAINER_STORAGE' is a Proxmox Backup Server — cannot be used for containers." + exit 224 + ;; linstor | rbd | nfs | cifs) - pvesm status -storage "$CONTAINER_STORAGE" &>/dev/null || exit 217 + if ! pvesm status -storage "$CONTAINER_STORAGE" &>/dev/null; then + msg_error "Storage '$CONTAINER_STORAGE' ($STORAGE_TYPE) is not accessible or inactive." + exit 217 + fi ;; esac - pvesm status -content rootdir 2>/dev/null | awk 'NR>1{print $1}' | grep -qx "$CONTAINER_STORAGE" || exit 213 + if ! pvesm status -content rootdir 2>/dev/null | awk 'NR>1{print $1}' | grep -qx "$CONTAINER_STORAGE"; then + msg_error "Storage '$CONTAINER_STORAGE' ($STORAGE_TYPE) does not support 'rootdir' content." + exit 213 + fi msg_ok "Storage '$CONTAINER_STORAGE' ($STORAGE_TYPE) validated" msg_info "Validating template storage '$TEMPLATE_STORAGE'" @@ -5102,8 +5134,7 @@ create_lxc_container() { # If still no template, try to find alternatives if [[ -z "$TEMPLATE" ]]; then - echo "" - echo "[DEBUG] No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}, searching for alternatives..." + msg_warn "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}, searching for alternatives..." # Get all available versions for this OS type AVAILABLE_VERSIONS=() @@ -5377,13 +5408,19 @@ create_lxc_container() { if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH" 2>/dev/null || echo 0)" -lt 1000000 ]]; then msg_info "Template file missing or too small – downloading" rm -f "$TEMPLATE_PATH" - pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1 + pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1 || { + msg_error "Failed to download template '$TEMPLATE' to storage '$TEMPLATE_STORAGE'" + exit 222 + } msg_ok "Template downloaded" elif ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then if [[ -n "$ONLINE_TEMPLATE" ]]; then msg_info "Template appears corrupted – re-downloading" rm -f "$TEMPLATE_PATH" - pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1 + pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1 || { + msg_error "Failed to re-download template '$TEMPLATE'" + exit 222 + } msg_ok "Template re-downloaded" else msg_warn "Template appears corrupted, but no online version exists. Skipping re-download." @@ -5425,20 +5462,17 @@ create_lxc_container() { if ! pct create "$CTID" "local:vztmpl/${TEMPLATE}" $PCT_OPTIONS >>"$LOGFILE" 2>&1; then # Local fallback also failed - check for LXC stack version issue if grep -qiE 'unsupported .* version' "$LOGFILE"; then - echo - echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template." - echo "We can try to upgrade 'pve-container' and 'lxc-pve' now and retry automatically." + msg_warn "pct reported 'unsupported version' – LXC stack might be too old for this template" offer_lxc_stack_upgrade_and_maybe_retry "yes" rc=$? case $rc in 0) : ;; # success - container created, continue 2) - echo "Upgrade was declined. Please update and re-run: - apt update && apt install --only-upgrade pve-container lxc-pve" + msg_error "Upgrade declined. Please update and re-run: apt update && apt install --only-upgrade pve-container lxc-pve" exit 231 ;; 3) - echo "Upgrade and/or retry failed. Please inspect: $LOGFILE" + msg_error "Upgrade and/or retry failed. Please inspect: $LOGFILE" exit 231 ;; esac @@ -5457,20 +5491,17 @@ create_lxc_container() { else # Already on local storage and still failed - check LXC stack version if grep -qiE 'unsupported .* version' "$LOGFILE"; then - echo - echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template." - echo "We can try to upgrade 'pve-container' and 'lxc-pve' now and retry automatically." + msg_warn "pct reported 'unsupported version' – LXC stack might be too old for this template" offer_lxc_stack_upgrade_and_maybe_retry "yes" rc=$? case $rc in 0) : ;; # success - container created, continue 2) - echo "Upgrade was declined. Please update and re-run: - apt update && apt install --only-upgrade pve-container lxc-pve" + msg_error "Upgrade declined. Please update and re-run: apt update && apt install --only-upgrade pve-container lxc-pve" exit 231 ;; 3) - echo "Upgrade and/or retry failed. Please inspect: $LOGFILE" + msg_error "Upgrade and/or retry failed. Please inspect: $LOGFILE" exit 231 ;; esac diff --git a/misc/core.func b/misc/core.func index c77324edc..044810f35 100644 --- a/misc/core.func +++ b/misc/core.func @@ -276,7 +276,7 @@ shell_check() { msg_error "Your default shell is currently not set to Bash. To use these scripts, please switch to the Bash shell." echo -e "\nExiting..." sleep 2 - exit + exit 1 fi } @@ -293,7 +293,7 @@ root_check() { msg_error "Please run this script as root." echo -e "\nExiting..." sleep 2 - exit + exit 1 fi } @@ -345,11 +345,10 @@ pve_check() { # ------------------------------------------------------------------------------ arch_check() { if [ "$(dpkg --print-architecture)" != "amd64" ]; then - echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n" - echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n" - echo -e "Exiting..." + msg_error "This script will not work with PiMox (ARM architecture detected)." + msg_warn "Visit https://github.com/asylumexp/Proxmox for ARM64 support." sleep 2 - exit + exit 1 fi } @@ -530,7 +529,9 @@ silent() { if [[ $rc -ne 0 ]]; then # Source explain_exit_code if needed if ! declare -f explain_exit_code >/dev/null 2>&1; then - source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func) + if ! source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func); then + explain_exit_code() { echo "unknown (error_handler.func download failed)"; } + fi fi local explanation @@ -785,8 +786,8 @@ fatal() { # ------------------------------------------------------------------------------ exit_script() { clear - echo -e "\n${CROSS}${RD}User exited script${CL}\n" - exit + msg_error "User exited script" + exit 0 } # ------------------------------------------------------------------------------ @@ -807,6 +808,7 @@ get_header() { if [ ! -s "$local_header_path" ]; then if ! curl -fsSL "$header_url" -o "$local_header_path"; then + msg_warn "Failed to download header: $header_url" return 1 fi fi @@ -847,10 +849,10 @@ header_info() { ensure_tput() { if ! command -v tput >/dev/null 2>&1; then if grep -qi 'alpine' /etc/os-release; then - apk add --no-cache ncurses >/dev/null 2>&1 + apk add --no-cache ncurses >/dev/null 2>&1 || msg_warn "Failed to install ncurses (tput may be unavailable)" elif command -v apt-get >/dev/null 2>&1; then apt-get update -qq >/dev/null - apt-get install -y -qq ncurses-bin >/dev/null 2>&1 + apt-get install -y -qq ncurses-bin >/dev/null 2>&1 || msg_warn "Failed to install ncurses-bin (tput may be unavailable)" fi fi } @@ -1310,6 +1312,7 @@ prompt_select() { # Validate options if [[ $num_options -eq 0 ]]; then + msg_warn "prompt_select called with no options" echo "" >&2 return 1 fi @@ -1552,22 +1555,30 @@ check_or_create_swap() { local swap_size_mb swap_size_mb=$(prompt_input "Enter swap size in MB (e.g., 2048 for 2GB):" "2048" 60) if ! [[ "$swap_size_mb" =~ ^[0-9]+$ ]]; then - msg_error "Invalid size input. Aborting." + msg_error "Invalid swap size: '${swap_size_mb}' (must be a number in MB)" return 1 fi local swap_file="/swapfile" msg_info "Creating ${swap_size_mb}MB swap file at $swap_file" - if dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" status=progress && - chmod 600 "$swap_file" && - mkswap "$swap_file" && - swapon "$swap_file"; then - msg_ok "Swap file created and activated successfully" - else - msg_error "Failed to create or activate swap" + if ! dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" status=progress; then + msg_error "Failed to allocate swap file (dd failed)" return 1 fi + if ! chmod 600 "$swap_file"; then + msg_error "Failed to set permissions on $swap_file" + return 1 + fi + if ! mkswap "$swap_file"; then + msg_error "Failed to format swap file (mkswap failed)" + return 1 + fi + if ! swapon "$swap_file"; then + msg_error "Failed to activate swap (swapon failed)" + return 1 + fi + msg_ok "Swap file created and activated successfully" } # ------------------------------------------------------------------------------ @@ -1649,7 +1660,7 @@ function get_lxc_ip() { LOCAL_IP="$(get_current_ip || true)" if [[ -z "$LOCAL_IP" ]]; then - msg_error "Could not determine LOCAL_IP" + msg_error "Could not determine LOCAL_IP (checked: eth0, hostname -I, ip route, IPv6 targets)" return 1 fi fi diff --git a/misc/tools.func b/misc/tools.func index c3ee29335..ca68b1732 100644 --- a/misc/tools.func +++ b/misc/tools.func @@ -201,6 +201,7 @@ install_packages_with_retry() { fi done + msg_error "Failed to install packages after $((max_retries + 1)) attempts: ${packages[*]}" return 1 } @@ -231,6 +232,7 @@ upgrade_packages_with_retry() { fi done + msg_error "Failed to upgrade packages after $((max_retries + 1)) attempts: ${packages[*]}" return 1 } @@ -675,6 +677,7 @@ verify_repo_available() { if curl -fsSL --max-time 10 "${repo_url}/dists/${suite}/Release" &>/dev/null; then return 0 fi + msg_warn "Repository not available: ${repo_url} (suite: ${suite})" return 1 } @@ -839,6 +842,7 @@ github_api_call() { esac done + msg_error "GitHub API call failed after ${max_retries} attempts: ${url}" return 1 } @@ -900,6 +904,7 @@ codeberg_api_call() { esac done + msg_error "Codeberg API call failed after ${max_retries} attempts: ${url}" return 1 } @@ -1369,7 +1374,9 @@ setup_deb822_repo() { [[ -n "$enabled" ]] && echo "Enabled: $enabled" } >/etc/apt/sources.list.d/${name}.sources - $STD apt update + $STD apt update || { + msg_warn "apt update failed after adding repository: ${name}" + } } # ------------------------------------------------------------------------------ @@ -1377,12 +1384,16 @@ setup_deb822_repo() { # ------------------------------------------------------------------------------ hold_package_version() { local package="$1" - $STD apt-mark hold "$package" + $STD apt-mark hold "$package" || { + msg_warn "Failed to hold package version: ${package}" + } } unhold_package_version() { local package="$1" - $STD apt-mark unhold "$package" + $STD apt-mark unhold "$package" || { + msg_warn "Failed to unhold package version: ${package}" + } } # ------------------------------------------------------------------------------ @@ -1412,6 +1423,7 @@ enable_and_start_service() { local service="$1" if ! systemctl enable "$service" &>/dev/null; then + msg_error "Failed to enable service: $service" return 1 fi @@ -1454,6 +1466,7 @@ extract_version_from_json() { version=$(echo "$json" | jq -r ".${field} // empty") if [[ -z "$version" ]]; then + msg_warn "JSON field '${field}' is empty in API response" return 1 fi @@ -1473,8 +1486,9 @@ get_latest_github_release() { local temp_file=$(mktemp) if ! github_api_call "https://api.github.com/repos/${repo}/releases/latest" "$temp_file"; then + msg_warn "GitHub API call failed for ${repo}" rm -f "$temp_file" - return 0 + return 1 fi local version @@ -1483,7 +1497,7 @@ get_latest_github_release() { if [[ -z "$version" ]]; then msg_error "Could not determine latest version for ${repo}" - return 0 + return 1 fi echo "$version" @@ -1499,8 +1513,9 @@ get_latest_codeberg_release() { # Codeberg API: get all releases and pick the first non-draft/non-prerelease if ! codeberg_api_call "https://codeberg.org/api/v1/repos/${repo}/releases" "$temp_file"; then + msg_warn "Codeberg API call failed for ${repo}" rm -f "$temp_file" - return 0 + return 1 fi local version @@ -1515,7 +1530,7 @@ get_latest_codeberg_release() { if [[ -z "$version" ]]; then msg_error "Could not determine latest version for ${repo}" - return 0 + return 1 fi echo "$version" @@ -1646,6 +1661,7 @@ get_latest_gh_tag() { sort -V | tail -n1) if [[ -z "$latest" ]]; then + msg_warn "No matching tags found for ${repo}${prefix:+ (prefix: $prefix)}" return 1 fi @@ -1881,7 +1897,7 @@ check_for_codeberg_release() { releases_json=$(curl -fsSL --max-time 20 \ -H 'Accept: application/json' \ "https://codeberg.org/api/v1/repos/${source}/releases" 2>/dev/null) || { - msg_error "Unable to fetch releases for ${app}" + msg_error "Unable to fetch releases for ${app} (codeberg.org/api/v1/repos/${source}/releases)" return 1 } @@ -2014,12 +2030,12 @@ function download_with_progress() { if [[ -z "$content_length" ]]; then if ! curl -fL# -o "$output" "$url"; then - msg_error "Download failed" + msg_error "Download failed: $url" return 1 fi else if ! curl -fsSL "$url" | pv -s "$content_length" >"$output"; then - msg_error "Download failed" + msg_error "Download failed: $url" return 1 fi fi @@ -2562,7 +2578,10 @@ _gh_scan_older_releases() { -H 'Accept: application/vnd.github+json' \ -H 'X-GitHub-Api-Version: 2022-11-28' \ "${header[@]}" \ - "https://api.github.com/repos/${repo}/releases?per_page=15" 2>/dev/null) || return 1 + "https://api.github.com/repos/${repo}/releases?per_page=15" 2>/dev/null) || { + msg_warn "Failed to fetch older releases for ${repo}" + return 1 + } local count count=$(echo "$releases_list" | jq 'length') @@ -3104,7 +3123,9 @@ function setup_composer() { # Scenario 1: Already installed - just self-update if [[ -n "$INSTALLED_VERSION" ]]; then msg_info "Update Composer $INSTALLED_VERSION" - $STD "$COMPOSER_BIN" self-update --no-interaction || true + $STD "$COMPOSER_BIN" self-update --no-interaction || { + msg_warn "Composer self-update failed, continuing with current version" + } local UPDATED_VERSION UPDATED_VERSION=$("$COMPOSER_BIN" --version 2>/dev/null | awk '{print $3}') cache_installed_version "composer" "$UPDATED_VERSION" @@ -3140,7 +3161,9 @@ function setup_composer() { fi chmod +x "$COMPOSER_BIN" - $STD "$COMPOSER_BIN" self-update --no-interaction || true + $STD "$COMPOSER_BIN" self-update --no-interaction || { + msg_warn "Composer self-update failed after fresh install" + } local FINAL_VERSION FINAL_VERSION=$("$COMPOSER_BIN" --version 2>/dev/null | awk '{print $3}') @@ -5223,7 +5246,9 @@ function setup_mysql() { ensure_apt_working || return 1 # Perform upgrade with retry logic (non-fatal if fails) - upgrade_packages_with_retry "mysql-server" "mysql-client" || true + upgrade_packages_with_retry "mysql-server" "mysql-client" || { + msg_warn "MySQL package upgrade had issues, continuing with current version" + } cache_installed_version "mysql" "$MYSQL_VERSION" msg_ok "Update MySQL $MYSQL_VERSION" @@ -5413,7 +5438,9 @@ function setup_nodejs() { } # Force APT cache refresh after repository setup - $STD apt update + $STD apt update || { + msg_warn "apt update failed after Node.js repository setup" + } ensure_dependencies curl ca-certificates gnupg @@ -5656,7 +5683,10 @@ EOF if [[ "$DISTRO_ID" == "ubuntu" ]]; then # Ubuntu: Use ondrej/php PPA msg_info "Adding ondrej/php PPA for Ubuntu" - $STD apt install -y software-properties-common + $STD apt install -y software-properties-common || { + msg_error "Failed to install software-properties-common" + return 1 + } # Don't use $STD for add-apt-repository as it uses background processes add-apt-repository -y ppa:ondrej/php >>"$(get_active_logfile)" 2>&1 else @@ -5667,7 +5697,9 @@ EOF } fi ensure_apt_working || return 1 - $STD apt update + $STD apt update || { + msg_warn "apt update failed after PHP repository setup" + } # Get available PHP version from repository local AVAILABLE_PHP_VERSION="" @@ -5962,7 +5994,9 @@ function setup_postgresql() { } fi - $STD systemctl enable --now postgresql 2>/dev/null || true + $STD systemctl enable --now postgresql 2>/dev/null || { + msg_warn "Failed to enable/start PostgreSQL service" + } # Add PostgreSQL binaries to PATH if ! grep -q '/usr/lib/postgresql' /etc/environment 2>/dev/null; then @@ -5976,7 +6010,9 @@ function setup_postgresql() { if [[ -n "$PG_MODULES" ]]; then IFS=',' read -ra MODULES <<<"$PG_MODULES" for module in "${MODULES[@]}"; do - $STD apt install -y "postgresql-${PG_VERSION}-${module}" 2>/dev/null || true + $STD apt install -y "postgresql-${PG_VERSION}-${module}" 2>/dev/null || { + msg_warn "Failed to install PostgreSQL module: ${module}" + } done fi } @@ -6635,7 +6671,9 @@ function setup_clickhouse() { ensure_apt_working || return 1 # Perform upgrade with retry logic (non-fatal if fails) - upgrade_packages_with_retry "clickhouse-server" "clickhouse-client" || true + upgrade_packages_with_retry "clickhouse-server" "clickhouse-client" || { + msg_warn "ClickHouse package upgrade had issues, continuing with current version" + } cache_installed_version "clickhouse" "$CLICKHOUSE_VERSION" msg_ok "Update ClickHouse $CLICKHOUSE_VERSION" return 0 @@ -6770,7 +6808,9 @@ function setup_rust() { } # Update to latest patch version - $STD rustup update "$RUST_TOOLCHAIN"