diff --git a/install_proxmenux.sh b/install_proxmenux.sh index bf30995b..10d12cbe 100755 --- a/install_proxmenux.sh +++ b/install_proxmenux.sh @@ -335,6 +335,31 @@ update_config() { fi } +# apt output goes to a temporary file: shown only when the command fails, so +# the reader sees why. Non-interactive, because a hidden prompt would hang. +APT_ERROR_LOG="" +run_apt() { + APT_ERROR_LOG=$(mktemp /tmp/proxmenux-apt.XXXXXX) + if DEBIAN_FRONTEND=noninteractive apt-get "$@" >"$APT_ERROR_LOG" 2>&1; then + rm -f "$APT_ERROR_LOG" + APT_ERROR_LOG="" + return 0 + fi + return 1 +} + +show_apt_error() { + [ -n "$APT_ERROR_LOG" ] && [ -f "$APT_ERROR_LOG" ] || return 0 + tail -n 15 "$APT_ERROR_LOG" | sed 's/^/ /' + rm -f "$APT_ERROR_LOG" + APT_ERROR_LOG="" +} + +discard_apt_error() { + [ -n "$APT_ERROR_LOG" ] && rm -f "$APT_ERROR_LOG" + APT_ERROR_LOG="" +} + show_progress() { local step="$1" local total="$2" @@ -680,17 +705,19 @@ install_normal_version() { show_progress $current_step $total_steps "Installing basic dependencies." msg_info "Refreshing apt cache..." - if apt-get update -y; then + if run_apt update -y; then msg_ok "apt cache refreshed." else msg_warn "apt cache refresh failed; checking available packages." + show_apt_error fi msg_info "Installing jq..." if ! command -v jq > /dev/null 2>&1; then - if apt-get install -y jq && command -v jq > /dev/null 2>&1; then + if run_apt install -y jq && command -v jq > /dev/null 2>&1; then update_config "jq" "installed" else + discard_apt_error local jq_url="https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64" if wget -q -O /usr/local/bin/jq "$jq_url" 2>/dev/null && chmod +x /usr/local/bin/jq; then if command -v jq > /dev/null 2>&1; then @@ -718,10 +745,11 @@ install_normal_version() { # dpkg-query for the EXACT package — `dpkg -l | grep -qw python3` # falsely matches `python3-pip`. Issue #205. if ! dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null | grep -q "ok installed"; then - if apt-get install -y "$pkg"; then + if run_apt install -y "$pkg"; then update_config "$pkg" "installed" else msg_error "Failed to install $pkg. Please install it manually." + show_apt_error update_config "$pkg" "failed" return 1 fi diff --git a/install_proxmenux_beta.sh b/install_proxmenux_beta.sh index ed0d5a29..b1388b7b 100644 --- a/install_proxmenux_beta.sh +++ b/install_proxmenux_beta.sh @@ -139,6 +139,31 @@ msg_title() { echo -e "\n" } +# apt output goes to a temporary file: shown only when the command fails, so +# the reader sees why. Non-interactive, because a hidden prompt would hang. +APT_ERROR_LOG="" +run_apt() { + APT_ERROR_LOG=$(mktemp /tmp/proxmenux-apt.XXXXXX) + if DEBIAN_FRONTEND=noninteractive apt-get "$@" >"$APT_ERROR_LOG" 2>&1; then + rm -f "$APT_ERROR_LOG" + APT_ERROR_LOG="" + return 0 + fi + return 1 +} + +show_apt_error() { + [ -n "$APT_ERROR_LOG" ] && [ -f "$APT_ERROR_LOG" ] || return 0 + tail -n 15 "$APT_ERROR_LOG" | sed 's/^/ /' + rm -f "$APT_ERROR_LOG" + APT_ERROR_LOG="" +} + +discard_apt_error() { + [ -n "$APT_ERROR_LOG" ] && rm -f "$APT_ERROR_LOG" + APT_ERROR_LOG="" +} + show_progress() { echo -e "\n${BOLD}${BL}${TAB}Installing ProxMenux Beta: Step ${1} of ${2}${CL}" echo @@ -611,17 +636,19 @@ install_beta() { show_progress $current_step $total_steps "Installing system dependencies" msg_info "Refreshing apt cache..." - if apt-get update -y; then + if run_apt update -y; then msg_ok "apt cache refreshed." else msg_warn "apt cache refresh failed; checking available packages." + show_apt_error fi msg_info "Installing jq..." if ! command -v jq > /dev/null 2>&1; then - if apt-get install -y jq && command -v jq > /dev/null 2>&1; then + if run_apt install -y jq && command -v jq > /dev/null 2>&1; then update_config "jq" "installed" else + discard_apt_error local jq_url="https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64" if wget -q -O /usr/local/bin/jq "$jq_url" 2>/dev/null && chmod +x /usr/local/bin/jq \ && command -v jq > /dev/null 2>&1; then @@ -643,10 +670,11 @@ install_beta() { # dpkg-query for the EXACT package name — `dpkg -l | grep -qw python3` # falsely matches `python3-pip`. Issue #205. if ! dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null | grep -q "ok installed"; then - if apt-get install -y "$pkg"; then + if run_apt install -y "$pkg"; then update_config "$pkg" "installed" else msg_error "Failed to install $pkg. Please install it manually." + show_apt_error update_config "$pkg" "failed" return 1 fi diff --git a/scripts/global/common-functions.sh b/scripts/global/common-functions.sh index ef4ed059..dd95e9bf 100644 --- a/scripts/global/common-functions.sh +++ b/scripts/global/common-functions.sh @@ -114,16 +114,27 @@ cleanup_duplicate_repos_pve9() { } # Helper: back up a file once before modifying, so an accidental - # comment-out is always recoverable next to the original. + # comment-out is always recoverable. Outside sources.list.d: apt reads + # every file there and warns about each copy on every update. + local backup_dir="/var/backups/proxmenux/apt" _backup_once() { local file="$1" [[ -f "$file" ]] || return 0 local ts backup ts=$(date +%Y%m%d_%H%M%S) - backup="${file}.proxmenux-backup.${ts}" + mkdir -p "$backup_dir" + backup="${backup_dir}/$(basename "$file").${ts}" [[ -f "$backup" ]] || cp -a "$file" "$backup" } + # Copies an earlier version left next to the originals move there too. + local stray + for stray in /etc/apt/sources.list.proxmenux-backup.* /etc/apt/sources.list.d/*.proxmenux-backup.*; do + [[ -f "$stray" ]] || continue + mkdir -p "$backup_dir" + mv -f "$stray" "${backup_dir}/$(basename "${stray/.proxmenux-backup./.}")" + done + # ── Phase 1 — comment intra-file duplicates in sources.list by URL+Suite ── if [ -s "$sources_file" ]; then local temp_file @@ -207,7 +218,7 @@ cleanup_duplicate_repos_pve9() { esc_uri=$(printf '%s' "$uri" | sed 's/[][\.^$*/]/\\&/g') esc_suite=$(printf '%s' "$suite" | sed 's/[][\.^$*/]/\\&/g') esc_comp=$(printf '%s' "$first_comp" | sed 's/[][\.^$*/]/\\&/g') - pmx_edit_file "$target_file" -E "/^deb[[:space:]]+${esc_uri}[[:space:]]+${esc_suite}[[:space:]]+.*(^| )${esc_comp}( |$)/s/^/# /" + pmx_edit_file "$target_file" -E "/^deb[[:space:]]+${esc_uri}[[:space:]]+${esc_suite}[[:space:]](.*[[:space:]])?${esc_comp}([[:space:]]|$)/s/^/# /" cleaned_count=$((cleaned_count + 1)) fi }