Merge from VE
This commit is contained in:
parent
7f68c58181
commit
6f9a1965f9
155
misc/api.func
155
misc/api.func
@ -1,6 +1,6 @@
|
|||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: michelroegl-brunner
|
# Author: michelroegl-brunner
|
||||||
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
|
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# API.FUNC - TELEMETRY & DIAGNOSTICS API
|
# API.FUNC - TELEMETRY & DIAGNOSTICS API
|
||||||
@ -36,14 +36,16 @@
|
|||||||
#
|
#
|
||||||
# - Maps numeric exit codes to human-readable error descriptions
|
# - Maps numeric exit codes to human-readable error descriptions
|
||||||
# - Supports:
|
# - Supports:
|
||||||
# * Generic/Shell errors (1, 2, 126, 127, 128, 130, 137, 139, 143)
|
# * Generic/Shell errors (1, 2, 124, 126-130, 134, 137, 139, 141, 143)
|
||||||
# * Package manager errors (APT, DPKG: 100, 101, 255)
|
# * curl/wget errors (6, 7, 22, 28, 35)
|
||||||
# * Node.js/npm errors (243-249, 254)
|
# * Package manager errors (APT, DPKG: 100-102, 255)
|
||||||
# * Python/pip/uv errors (210-212)
|
# * Systemd/Service errors (150-154)
|
||||||
# * PostgreSQL errors (231-234)
|
# * Python/pip/uv errors (160-162)
|
||||||
# * MySQL/MariaDB errors (241-244)
|
# * PostgreSQL errors (170-173)
|
||||||
# * MongoDB errors (251-254)
|
# * MySQL/MariaDB errors (180-183)
|
||||||
|
# * MongoDB errors (190-193)
|
||||||
# * Proxmox custom codes (200-231)
|
# * Proxmox custom codes (200-231)
|
||||||
|
# * Node.js/npm errors (243, 245-249)
|
||||||
# - Returns description string for given exit code
|
# - Returns description string for given exit code
|
||||||
# - Shared function with error_handler.func for consistency
|
# - Shared function with error_handler.func for consistency
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@ -53,73 +55,98 @@ explain_exit_code() {
|
|||||||
# --- Generic / Shell ---
|
# --- Generic / Shell ---
|
||||||
1) echo "General error / Operation not permitted" ;;
|
1) echo "General error / Operation not permitted" ;;
|
||||||
2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
|
2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
|
||||||
126) echo "Command invoked cannot execute (permission problem?)" ;;
|
|
||||||
127) echo "Command not found" ;;
|
# --- curl / wget errors (commonly seen in downloads) ---
|
||||||
128) echo "Invalid argument to exit" ;;
|
6) echo "curl: DNS resolution failed (could not resolve host)" ;;
|
||||||
130) echo "Terminated by Ctrl+C (SIGINT)" ;;
|
7) echo "curl: Failed to connect (network unreachable / host down)" ;;
|
||||||
137) echo "Killed (SIGKILL / Out of memory?)" ;;
|
22) echo "curl: HTTP error returned (404, 429, 500+)" ;;
|
||||||
139) echo "Segmentation fault (core dumped)" ;;
|
28) echo "curl: Operation timeout (network slow or server not responding)" ;;
|
||||||
143) echo "Terminated (SIGTERM)" ;;
|
35) echo "curl: SSL/TLS handshake failed (certificate error)" ;;
|
||||||
|
|
||||||
# --- Package manager / APT / DPKG ---
|
# --- Package manager / APT / DPKG ---
|
||||||
100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
|
100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
|
||||||
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
|
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
|
||||||
255) echo "DPKG: Fatal internal error" ;;
|
102) echo "APT: Lock held by another process (dpkg/apt still running)" ;;
|
||||||
|
|
||||||
# --- Node.js / npm / pnpm / yarn ---
|
# --- Common shell/system errors ---
|
||||||
|
124) echo "Command timed out (timeout command)" ;;
|
||||||
|
126) echo "Command invoked cannot execute (permission problem?)" ;;
|
||||||
|
127) echo "Command not found" ;;
|
||||||
|
128) echo "Invalid argument to exit" ;;
|
||||||
|
130) echo "Terminated by Ctrl+C (SIGINT)" ;;
|
||||||
|
134) echo "Process aborted (SIGABRT - possibly Node.js heap overflow)" ;;
|
||||||
|
137) echo "Killed (SIGKILL / Out of memory?)" ;;
|
||||||
|
139) echo "Segmentation fault (core dumped)" ;;
|
||||||
|
141) echo "Broken pipe (SIGPIPE - output closed prematurely)" ;;
|
||||||
|
143) echo "Terminated (SIGTERM)" ;;
|
||||||
|
|
||||||
|
# --- Systemd / Service errors (150-154) ---
|
||||||
|
150) echo "Systemd: Service failed to start" ;;
|
||||||
|
151) echo "Systemd: Service unit not found" ;;
|
||||||
|
152) echo "Permission denied (EACCES)" ;;
|
||||||
|
153) echo "Build/compile failed (make/gcc/cmake)" ;;
|
||||||
|
154) echo "Node.js: Native addon build failed (node-gyp)" ;;
|
||||||
|
|
||||||
|
# --- Python / pip / uv (160-162) ---
|
||||||
|
160) echo "Python: Virtualenv / uv environment missing or broken" ;;
|
||||||
|
161) echo "Python: Dependency resolution failed" ;;
|
||||||
|
162) echo "Python: Installation aborted (permissions or EXTERNALLY-MANAGED)" ;;
|
||||||
|
|
||||||
|
# --- PostgreSQL (170-173) ---
|
||||||
|
170) echo "PostgreSQL: Connection failed (server not running / wrong socket)" ;;
|
||||||
|
171) echo "PostgreSQL: Authentication failed (bad user/password)" ;;
|
||||||
|
172) echo "PostgreSQL: Database does not exist" ;;
|
||||||
|
173) echo "PostgreSQL: Fatal error in query / syntax" ;;
|
||||||
|
|
||||||
|
# --- MySQL / MariaDB (180-183) ---
|
||||||
|
180) echo "MySQL/MariaDB: Connection failed (server not running / wrong socket)" ;;
|
||||||
|
181) echo "MySQL/MariaDB: Authentication failed (bad user/password)" ;;
|
||||||
|
182) echo "MySQL/MariaDB: Database does not exist" ;;
|
||||||
|
183) echo "MySQL/MariaDB: Fatal error in query / syntax" ;;
|
||||||
|
|
||||||
|
# --- MongoDB (190-193) ---
|
||||||
|
190) echo "MongoDB: Connection failed (server not running)" ;;
|
||||||
|
191) echo "MongoDB: Authentication failed (bad user/password)" ;;
|
||||||
|
192) echo "MongoDB: Database not found" ;;
|
||||||
|
193) echo "MongoDB: Fatal query error" ;;
|
||||||
|
|
||||||
|
# --- Proxmox Custom Codes (200-231) ---
|
||||||
|
200) echo "Proxmox: Failed to create lock file" ;;
|
||||||
|
203) echo "Proxmox: Missing CTID variable" ;;
|
||||||
|
204) echo "Proxmox: Missing PCT_OSTYPE variable" ;;
|
||||||
|
205) echo "Proxmox: Invalid CTID (<100)" ;;
|
||||||
|
206) echo "Proxmox: CTID already in use" ;;
|
||||||
|
207) echo "Proxmox: Password contains unescaped special characters" ;;
|
||||||
|
208) echo "Proxmox: Invalid configuration (DNS/MAC/Network format)" ;;
|
||||||
|
209) echo "Proxmox: Container creation failed" ;;
|
||||||
|
210) echo "Proxmox: Cluster not quorate" ;;
|
||||||
|
211) echo "Proxmox: Timeout waiting for template lock" ;;
|
||||||
|
212) echo "Proxmox: Storage type 'iscsidirect' does not support containers (VMs only)" ;;
|
||||||
|
213) echo "Proxmox: Storage type does not support 'rootdir' content" ;;
|
||||||
|
214) echo "Proxmox: Not enough storage space" ;;
|
||||||
|
215) echo "Proxmox: Container created but not listed (ghost state)" ;;
|
||||||
|
216) echo "Proxmox: RootFS entry missing in config" ;;
|
||||||
|
217) echo "Proxmox: Storage not accessible" ;;
|
||||||
|
218) echo "Proxmox: Template file corrupted or incomplete" ;;
|
||||||
|
219) echo "Proxmox: CephFS does not support containers - use RBD" ;;
|
||||||
|
220) echo "Proxmox: Unable to resolve template path" ;;
|
||||||
|
221) echo "Proxmox: Template file not readable" ;;
|
||||||
|
222) echo "Proxmox: Template download failed" ;;
|
||||||
|
223) echo "Proxmox: Template not available after download" ;;
|
||||||
|
224) echo "Proxmox: PBS storage is for backups only" ;;
|
||||||
|
225) echo "Proxmox: No template available for OS/Version" ;;
|
||||||
|
231) echo "Proxmox: LXC stack upgrade failed" ;;
|
||||||
|
|
||||||
|
# --- Node.js / npm / pnpm / yarn (243-249) ---
|
||||||
243) echo "Node.js: Out of memory (JavaScript heap out of memory)" ;;
|
243) echo "Node.js: Out of memory (JavaScript heap out of memory)" ;;
|
||||||
245) echo "Node.js: Invalid command-line option" ;;
|
245) echo "Node.js: Invalid command-line option" ;;
|
||||||
246) echo "Node.js: Internal JavaScript Parse Error" ;;
|
246) echo "Node.js: Internal JavaScript Parse Error" ;;
|
||||||
247) echo "Node.js: Fatal internal error" ;;
|
247) echo "Node.js: Fatal internal error" ;;
|
||||||
248) echo "Node.js: Invalid C++ addon / N-API failure" ;;
|
248) echo "Node.js: Invalid C++ addon / N-API failure" ;;
|
||||||
249) echo "Node.js: Inspector error" ;;
|
249) echo "npm/pnpm/yarn: Unknown fatal error" ;;
|
||||||
254) echo "npm/pnpm/yarn: Unknown fatal error" ;;
|
|
||||||
|
|
||||||
# --- Python / pip / uv ---
|
# --- DPKG ---
|
||||||
210) echo "Python: Virtualenv / uv environment missing or broken" ;;
|
255) echo "DPKG: Fatal internal error" ;;
|
||||||
211) echo "Python: Dependency resolution failed" ;;
|
|
||||||
212) echo "Python: Installation aborted (permissions or EXTERNALLY-MANAGED)" ;;
|
|
||||||
|
|
||||||
# --- PostgreSQL ---
|
|
||||||
231) echo "PostgreSQL: Connection failed (server not running / wrong socket)" ;;
|
|
||||||
232) echo "PostgreSQL: Authentication failed (bad user/password)" ;;
|
|
||||||
233) echo "PostgreSQL: Database does not exist" ;;
|
|
||||||
234) echo "PostgreSQL: Fatal error in query / syntax" ;;
|
|
||||||
|
|
||||||
# --- MySQL / MariaDB ---
|
|
||||||
241) echo "MySQL/MariaDB: Connection failed (server not running / wrong socket)" ;;
|
|
||||||
242) echo "MySQL/MariaDB: Authentication failed (bad user/password)" ;;
|
|
||||||
243) echo "MySQL/MariaDB: Database does not exist" ;;
|
|
||||||
244) echo "MySQL/MariaDB: Fatal error in query / syntax" ;;
|
|
||||||
|
|
||||||
# --- MongoDB ---
|
|
||||||
251) echo "MongoDB: Connection failed (server not running)" ;;
|
|
||||||
252) echo "MongoDB: Authentication failed (bad user/password)" ;;
|
|
||||||
253) echo "MongoDB: Database not found" ;;
|
|
||||||
254) echo "MongoDB: Fatal query error" ;;
|
|
||||||
|
|
||||||
# --- Proxmox Custom Codes ---
|
|
||||||
200) echo "Custom: Failed to create lock file" ;;
|
|
||||||
203) echo "Custom: Missing CTID variable" ;;
|
|
||||||
204) echo "Custom: Missing PCT_OSTYPE variable" ;;
|
|
||||||
205) echo "Custom: Invalid CTID (<100)" ;;
|
|
||||||
206) echo "Custom: CTID already in use (check 'pct list' and /etc/pve/lxc/)" ;;
|
|
||||||
207) echo "Custom: Password contains unescaped special characters (-, /, \\, *, etc.)" ;;
|
|
||||||
208) echo "Custom: Invalid configuration (DNS/MAC/Network format error)" ;;
|
|
||||||
209) echo "Custom: Container creation failed (check logs for pct create output)" ;;
|
|
||||||
210) echo "Custom: Cluster not quorate" ;;
|
|
||||||
211) echo "Custom: Timeout waiting for template lock (concurrent download in progress)" ;;
|
|
||||||
214) echo "Custom: Not enough storage space" ;;
|
|
||||||
215) echo "Custom: Container created but not listed (ghost state - check /etc/pve/lxc/)" ;;
|
|
||||||
216) echo "Custom: RootFS entry missing in config (incomplete creation)" ;;
|
|
||||||
217) echo "Custom: Storage does not support rootdir (check storage capabilities)" ;;
|
|
||||||
218) echo "Custom: Template file corrupted or incomplete download (size <1MB or invalid archive)" ;;
|
|
||||||
220) echo "Custom: Unable to resolve template path" ;;
|
|
||||||
221) echo "Custom: Template file exists but not readable (check file permissions)" ;;
|
|
||||||
222) echo "Custom: Template download failed after 3 attempts (network/storage issue)" ;;
|
|
||||||
223) echo "Custom: Template not available after download (storage sync issue)" ;;
|
|
||||||
225) echo "Custom: No template available for OS/Version (check 'pveam available')" ;;
|
|
||||||
231) echo "Custom: LXC stack upgrade/retry failed (outdated pve-container - check https://github.com/community-scripts/ProxmoxVE/discussions/8126)" ;;
|
|
||||||
|
|
||||||
# --- Default ---
|
# --- Default ---
|
||||||
*) echo "Unknown error" ;;
|
*) echo "Unknown error" ;;
|
||||||
|
|||||||
135
misc/build.func
135
misc/build.func
@ -1,8 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
|
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/branch/main/LICENSE
|
||||||
# Revision: 1
|
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# BUILD.FUNC - LXC CONTAINER BUILD & CONFIGURATION
|
# BUILD.FUNC - LXC CONTAINER BUILD & CONFIGURATION
|
||||||
@ -81,109 +80,6 @@ variables() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
# Community-Scripts bootstrap loader
|
|
||||||
# - Always sources build.func from remote
|
|
||||||
# - Updates local core files only if build.func changed
|
|
||||||
# - Local cache: /usr/local/community-scripts/core
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# FUNC_DIR="/usr/local/community-scripts/core"
|
|
||||||
# mkdir -p "$FUNC_DIR"
|
|
||||||
|
|
||||||
# BUILD_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func"
|
|
||||||
# BUILD_REV="$FUNC_DIR/build.rev"
|
|
||||||
# DEVMODE="${DEVMODE:-no}"
|
|
||||||
|
|
||||||
# # --- Step 1: fetch build.func content once, compute hash ---
|
|
||||||
# build_content="$(curl -fsSL "$BUILD_URL")" || {
|
|
||||||
# echo "❌ Failed to fetch build.func"
|
|
||||||
# exit 1
|
|
||||||
# }
|
|
||||||
|
|
||||||
# newhash=$(printf "%s" "$build_content" | sha256sum | awk '{print $1}')
|
|
||||||
# oldhash=$(cat "$BUILD_REV" 2>/dev/null || echo "")
|
|
||||||
|
|
||||||
# # --- Step 2: if build.func changed, offer update for core files ---
|
|
||||||
# if [ "$newhash" != "$oldhash" ]; then
|
|
||||||
# echo "⚠️ build.func changed!"
|
|
||||||
|
|
||||||
# while true; do
|
|
||||||
# read -rp "Refresh local core files? [y/N/diff]: " ans
|
|
||||||
# case "$ans" in
|
|
||||||
# [Yy]*)
|
|
||||||
# echo "$newhash" >"$BUILD_REV"
|
|
||||||
|
|
||||||
# update_func_file() {
|
|
||||||
# local file="$1"
|
|
||||||
# local url="https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/$file"
|
|
||||||
# local local_path="$FUNC_DIR/$file"
|
|
||||||
|
|
||||||
# echo "⬇️ Downloading $file ..."
|
|
||||||
# curl -fsSL "$url" -o "$local_path" || {
|
|
||||||
# echo "❌ Failed to fetch $file"
|
|
||||||
# exit 1
|
|
||||||
# }
|
|
||||||
# echo "✔️ Updated $file"
|
|
||||||
# }
|
|
||||||
|
|
||||||
# update_func_file core.func
|
|
||||||
# update_func_file error_handler.func
|
|
||||||
# update_func_file tools.func
|
|
||||||
# break
|
|
||||||
# ;;
|
|
||||||
# [Dd]*)
|
|
||||||
# for file in core.func error_handler.func tools.func; do
|
|
||||||
# local_path="$FUNC_DIR/$file"
|
|
||||||
# url="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/$file"
|
|
||||||
# remote_tmp="$(mktemp)"
|
|
||||||
|
|
||||||
# curl -fsSL "$url" -o "$remote_tmp" || continue
|
|
||||||
|
|
||||||
# if [ -f "$local_path" ]; then
|
|
||||||
# echo "🔍 Diff for $file:"
|
|
||||||
# diff -u "$local_path" "$remote_tmp" || echo "(no differences)"
|
|
||||||
# else
|
|
||||||
# echo "📦 New file $file will be installed"
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# rm -f "$remote_tmp"
|
|
||||||
# done
|
|
||||||
# ;;
|
|
||||||
# *)
|
|
||||||
# echo "❌ Skipped updating local core files"
|
|
||||||
# break
|
|
||||||
# ;;
|
|
||||||
# esac
|
|
||||||
# done
|
|
||||||
# else
|
|
||||||
# if [ "$DEVMODE" != "yes" ]; then
|
|
||||||
# echo "✔️ build.func unchanged → using existing local core files"
|
|
||||||
# fi
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# if [ -n "${_COMMUNITY_SCRIPTS_LOADER:-}" ]; then
|
|
||||||
# return 0 2>/dev/null || exit 0
|
|
||||||
# fi
|
|
||||||
# _COMMUNITY_SCRIPTS_LOADER=1
|
|
||||||
|
|
||||||
# # --- Step 3: always source local versions of the core files ---
|
|
||||||
# source "$FUNC_DIR/core.func"
|
|
||||||
# source "$FUNC_DIR/error_handler.func"
|
|
||||||
# source "$FUNC_DIR/tools.func"
|
|
||||||
|
|
||||||
# # --- Step 4: finally, source build.func directly from memory ---
|
|
||||||
# # (no tmp file needed)
|
|
||||||
# source <(printf "%s" "$build_content")
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Load core + error handler functions from community-scripts repo
|
|
||||||
#
|
|
||||||
# - Prefer curl if available, fallback to wget
|
|
||||||
# - Load: core.func, error_handler.func, api.func
|
|
||||||
# - Initialize error traps after loading
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/api.func)
|
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/api.func)
|
||||||
|
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
@ -191,13 +87,11 @@ if command -v curl >/dev/null 2>&1; then
|
|||||||
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/error_handler.func)
|
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/error_handler.func)
|
||||||
load_functions
|
load_functions
|
||||||
catch_errors
|
catch_errors
|
||||||
#echo "(build.func) Loaded core.func via curl"
|
|
||||||
elif command -v wget >/dev/null 2>&1; then
|
elif command -v wget >/dev/null 2>&1; then
|
||||||
source <(wget -qO- https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/core.func)
|
source <(wget -qO- https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/core.func)
|
||||||
source <(wget -qO- https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/error_handler.func)
|
source <(wget -qO- https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/error_handler.func)
|
||||||
load_functions
|
load_functions
|
||||||
catch_errors
|
catch_errors
|
||||||
#echo "(build.func) Loaded core.func via wget"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
@ -266,17 +160,29 @@ maxkeys_check() {
|
|||||||
#
|
#
|
||||||
# - Returns current container IP depending on OS type
|
# - Returns current container IP depending on OS type
|
||||||
# - Debian/Ubuntu: uses `hostname -I`
|
# - Debian/Ubuntu: uses `hostname -I`
|
||||||
# - Alpine: parses eth0 via `ip -4 addr`
|
# - Alpine: parses eth0 via `ip -4 addr` or `ip -6 addr`
|
||||||
|
# - Supports IPv6-only environments as fallback
|
||||||
# - Returns "Unknown" if OS type cannot be determined
|
# - Returns "Unknown" if OS type cannot be determined
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
get_current_ip() {
|
get_current_ip() {
|
||||||
|
CURRENT_IP=""
|
||||||
if [ -f /etc/os-release ]; then
|
if [ -f /etc/os-release ]; then
|
||||||
# Check for Debian/Ubuntu (uses hostname -I)
|
# Check for Debian/Ubuntu (uses hostname -I)
|
||||||
if grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
|
if grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
|
||||||
CURRENT_IP=$(hostname -I | awk '{print $1}')
|
# Try IPv4 first
|
||||||
|
CURRENT_IP=$(hostname -I 2>/dev/null | tr ' ' '\n' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n1)
|
||||||
|
# Fallback to IPv6 if no IPv4
|
||||||
|
if [[ -z "$CURRENT_IP" ]]; then
|
||||||
|
CURRENT_IP=$(hostname -I 2>/dev/null | tr ' ' '\n' | grep -E ':' | head -n1)
|
||||||
|
fi
|
||||||
# Check for Alpine (uses ip command)
|
# Check for Alpine (uses ip command)
|
||||||
elif grep -q 'ID=alpine' /etc/os-release; then
|
elif grep -q 'ID=alpine' /etc/os-release; then
|
||||||
CURRENT_IP=$(ip -4 addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
# Try IPv4 first
|
||||||
|
CURRENT_IP=$(ip -4 addr show eth0 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||||
|
# Fallback to IPv6 if no IPv4
|
||||||
|
if [[ -z "$CURRENT_IP" ]]; then
|
||||||
|
CURRENT_IP=$(ip -6 addr show eth0 scope global 2>/dev/null | awk '/inet6 / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
CURRENT_IP="Unknown"
|
CURRENT_IP="Unknown"
|
||||||
fi
|
fi
|
||||||
@ -308,6 +214,7 @@ update_motd_ip() {
|
|||||||
#
|
#
|
||||||
# - Installs SSH keys into container root account if SSH is enabled
|
# - Installs SSH keys into container root account if SSH is enabled
|
||||||
# - Uses pct push or direct input to authorized_keys
|
# - Uses pct push or direct input to authorized_keys
|
||||||
|
# - Supports both SSH_KEYS_FILE (from advanced settings) and SSH_AUTHORIZED_KEY (from user defaults)
|
||||||
# - Falls back to warning if no keys provided
|
# - Falls back to warning if no keys provided
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
install_ssh_keys_into_ct() {
|
install_ssh_keys_into_ct() {
|
||||||
@ -316,6 +223,13 @@ install_ssh_keys_into_ct() {
|
|||||||
# Ensure SSH_KEYS_FILE is defined (may not be set if advanced_settings was skipped)
|
# Ensure SSH_KEYS_FILE is defined (may not be set if advanced_settings was skipped)
|
||||||
: "${SSH_KEYS_FILE:=}"
|
: "${SSH_KEYS_FILE:=}"
|
||||||
|
|
||||||
|
# If SSH_KEYS_FILE doesn't exist but SSH_AUTHORIZED_KEY is set (from user defaults),
|
||||||
|
# create a temporary SSH_KEYS_FILE with the key
|
||||||
|
if [[ -z "$SSH_KEYS_FILE" || ! -s "$SSH_KEYS_FILE" ]] && [[ -n "${SSH_AUTHORIZED_KEY:-}" ]]; then
|
||||||
|
SSH_KEYS_FILE="$(mktemp)"
|
||||||
|
printf '%s\n' "$SSH_AUTHORIZED_KEY" >"$SSH_KEYS_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -n "$SSH_KEYS_FILE" && -s "$SSH_KEYS_FILE" ]]; then
|
if [[ -n "$SSH_KEYS_FILE" && -s "$SSH_KEYS_FILE" ]]; then
|
||||||
msg_info "Installing selected SSH keys into CT ${CTID}"
|
msg_info "Installing selected SSH keys into CT ${CTID}"
|
||||||
pct exec "$CTID" -- sh -c 'mkdir -p /root/.ssh && chmod 700 /root/.ssh' || {
|
pct exec "$CTID" -- sh -c 'mkdir -p /root/.ssh && chmod 700 /root/.ssh' || {
|
||||||
@ -1025,7 +939,6 @@ base_settings() {
|
|||||||
ENABLE_NESTING=${var_nesting:-"1"}
|
ENABLE_NESTING=${var_nesting:-"1"}
|
||||||
ENABLE_KEYCTL=${var_keyctl:-"0"}
|
ENABLE_KEYCTL=${var_keyctl:-"0"}
|
||||||
ENABLE_MKNOD=${var_mknod:-"0"}
|
ENABLE_MKNOD=${var_mknod:-"0"}
|
||||||
MOUNT_FS=${var_mount_fs:-""}
|
|
||||||
PROTECT_CT=${var_protection:-"no"}
|
PROTECT_CT=${var_protection:-"no"}
|
||||||
CT_TIMEZONE=${var_timezone:-"$timezone"}
|
CT_TIMEZONE=${var_timezone:-"$timezone"}
|
||||||
[[ "${CT_TIMEZONE:-}" == Etc/* ]] && CT_TIMEZONE="host" # pct doesn't accept Etc/* zones
|
[[ "${CT_TIMEZONE:-}" == Etc/* ]] && CT_TIMEZONE="host" # pct doesn't accept Etc/* zones
|
||||||
|
|||||||
140
misc/core.func
140
misc/core.func
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# CORE FUNCTIONS - LXC CONTAINER UTILITIES
|
# CORE FUNCTIONS - LXC CONTAINER UTILITIES
|
||||||
@ -123,6 +123,7 @@ icons() {
|
|||||||
CREATING="${TAB}🚀${TAB}${CL}"
|
CREATING="${TAB}🚀${TAB}${CL}"
|
||||||
ADVANCED="${TAB}🧩${TAB}${CL}"
|
ADVANCED="${TAB}🧩${TAB}${CL}"
|
||||||
FUSE="${TAB}🗂️${TAB}${CL}"
|
FUSE="${TAB}🗂️${TAB}${CL}"
|
||||||
|
GPU="${TAB}🎮${TAB}${CL}"
|
||||||
HOURGLASS="${TAB}⏳${TAB}"
|
HOURGLASS="${TAB}⏳${TAB}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,11 +552,8 @@ msg_info() {
|
|||||||
if ! declare -p MSG_INFO_SHOWN &>/dev/null || ! declare -A MSG_INFO_SHOWN &>/dev/null; then
|
if ! declare -p MSG_INFO_SHOWN &>/dev/null || ! declare -A MSG_INFO_SHOWN &>/dev/null; then
|
||||||
declare -gA MSG_INFO_SHOWN=()
|
declare -gA MSG_INFO_SHOWN=()
|
||||||
fi
|
fi
|
||||||
# Sanitize message for use as associative array key (remove ANSI codes and special chars)
|
[[ -n "${MSG_INFO_SHOWN["$msg"]+x}" ]] && return
|
||||||
local sanitized_msg
|
MSG_INFO_SHOWN["$msg"]=1
|
||||||
sanitized_msg=$(printf '%s' "$msg" | sed 's/\x1b\[[0-9;]*m//g; s/[^a-zA-Z0-9_]/_/g')
|
|
||||||
[[ -n "${MSG_INFO_SHOWN["$sanitized_msg"]+x}" ]] && return
|
|
||||||
MSG_INFO_SHOWN["$sanitized_msg"]=1
|
|
||||||
|
|
||||||
stop_spinner
|
stop_spinner
|
||||||
SPINNER_MSG="$msg"
|
SPINNER_MSG="$msg"
|
||||||
@ -600,7 +598,6 @@ msg_ok() {
|
|||||||
stop_spinner
|
stop_spinner
|
||||||
clear_line
|
clear_line
|
||||||
echo -e "$CM ${GN}${msg}${CL}"
|
echo -e "$CM ${GN}${msg}${CL}"
|
||||||
# Sanitize message for use as associative array key (remove ANSI codes and special chars)
|
|
||||||
local sanitized_msg
|
local sanitized_msg
|
||||||
sanitized_msg=$(printf '%s' "$msg" | sed 's/\x1b\[[0-9;]*m//g; s/[^a-zA-Z0-9_]/_/g')
|
sanitized_msg=$(printf '%s' "$msg" | sed 's/\x1b\[[0-9;]*m//g; s/[^a-zA-Z0-9_]/_/g')
|
||||||
unset 'MSG_INFO_SHOWN['"$sanitized_msg"']' 2>/dev/null || true
|
unset 'MSG_INFO_SHOWN['"$sanitized_msg"']' 2>/dev/null || true
|
||||||
@ -717,7 +714,7 @@ exit_script() {
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
get_header() {
|
get_header() {
|
||||||
local app_name=$(echo "${APP,,}" | tr -d ' ')
|
local app_name=$(echo "${APP,,}" | tr -d ' ')
|
||||||
local app_type=${APP_TYPE:-ct} # Default zu 'ct' falls nicht gesetzt
|
local app_type=${APP_TYPE:-ct} # Default to 'ct' if not set
|
||||||
local header_url="https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/${app_type}/headers/${app_name}"
|
local header_url="https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/${app_type}/headers/${app_name}"
|
||||||
local local_header_path="/usr/local/community-scripts/headers/${app_type}/${app_name}"
|
local local_header_path="/usr/local/community-scripts/headers/${app_type}/${app_name}"
|
||||||
|
|
||||||
@ -820,71 +817,64 @@ is_verbose_mode() {
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# cleanup_lxc()
|
# cleanup_lxc()
|
||||||
#
|
#
|
||||||
# - Comprehensive cleanup of package managers, caches, and logs
|
# - Cleans package manager and language caches (safe for installs AND updates)
|
||||||
# - Supports Alpine (apk), Debian/Ubuntu (apt), Fedora/Rocky/CentOS (dnf/yum),
|
# - Supports Alpine (apk), Debian/Ubuntu (apt), Python, Node.js, Go, Rust, Ruby, PHP
|
||||||
# openSUSE (zypper), Gentoo (emerge), and language package managers
|
# - Uses fallback error handling to prevent cleanup failures from breaking installs
|
||||||
# - Cleans: Python (pip/uv), Node.js (npm/yarn/pnpm), Go, Rust, Ruby, PHP
|
|
||||||
# - Truncates log files and vacuums systemd journal
|
|
||||||
# - Run at end of container creation to minimize disk usage
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
cleanup_lxc() {
|
cleanup_lxc() {
|
||||||
msg_info "Cleaning up"
|
msg_info "Cleaning up"
|
||||||
# OS-specific package manager cleanup
|
|
||||||
if is_alpine; then
|
if is_alpine; then
|
||||||
$STD apk cache clean 2>/dev/null || true
|
$STD apk cache clean || true
|
||||||
rm -rf /var/cache/apk/*
|
rm -rf /var/cache/apk/*
|
||||||
elif command -v apt &>/dev/null; then
|
else
|
||||||
# Debian/Ubuntu/Devuan
|
$STD apt -y autoremove 2>/dev/null || msg_warn "apt autoremove failed (non-critical)"
|
||||||
$STD apt -y autoremove 2>/dev/null || true
|
$STD apt -y autoclean 2>/dev/null || msg_warn "apt autoclean failed (non-critical)"
|
||||||
$STD apt -y autoclean 2>/dev/null || true
|
$STD apt -y clean 2>/dev/null || msg_warn "apt clean failed (non-critical)"
|
||||||
$STD apt -y clean 2>/dev/null || true
|
|
||||||
elif command -v dnf &>/dev/null; then
|
|
||||||
# Fedora/Rocky/AlmaLinux/CentOS 8+
|
|
||||||
$STD dnf clean all 2>/dev/null || true
|
|
||||||
$STD dnf autoremove -y 2>/dev/null || true
|
|
||||||
elif command -v yum &>/dev/null; then
|
|
||||||
# CentOS 7/older RHEL
|
|
||||||
$STD yum clean all 2>/dev/null || true
|
|
||||||
elif command -v zypper &>/dev/null; then
|
|
||||||
# openSUSE
|
|
||||||
$STD zypper clean --all 2>/dev/null || true
|
|
||||||
elif command -v emerge &>/dev/null; then
|
|
||||||
# Gentoo
|
|
||||||
$STD emerge --quiet --depclean 2>/dev/null || true
|
|
||||||
$STD eclean-dist -d 2>/dev/null || true
|
|
||||||
$STD eclean-pkg -d 2>/dev/null || true
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Clear temp artifacts (keep sockets/FIFOs; ignore errors)
|
|
||||||
find /tmp /var/tmp -type f -name 'tmp*' -delete 2>/dev/null || true
|
find /tmp /var/tmp -type f -name 'tmp*' -delete 2>/dev/null || true
|
||||||
find /tmp /var/tmp -type f -name 'tempfile*' -delete 2>/dev/null || true
|
find /tmp /var/tmp -type f -name 'tempfile*' -delete 2>/dev/null || true
|
||||||
|
|
||||||
# Truncate writable log files silently (permission errors ignored)
|
# Python
|
||||||
if command -v truncate >/dev/null 2>&1; then
|
if command -v pip &>/dev/null; then
|
||||||
find /var/log -type f -writable -print0 2>/dev/null |
|
rm -rf /root/.cache/pip 2>/dev/null || true
|
||||||
xargs -0 -n1 truncate -s 0 2>/dev/null || true
|
fi
|
||||||
|
if command -v uv &>/dev/null; then
|
||||||
|
rm -rf /root/.cache/uv 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Node.js npm
|
# Node.js
|
||||||
if command -v npm &>/dev/null; then
|
if command -v npm &>/dev/null; then
|
||||||
rm -rf /root/.npm/_cacache /root/.npm/_logs 2>/dev/null || true
|
rm -rf /root/.npm/_cacache /root/.npm/_logs 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
# Node.js yarn
|
if command -v yarn &>/dev/null; then
|
||||||
#if command -v yarn &>/dev/null; then $STD yarn cache clean 2>/dev/null || true; fi
|
rm -rf /root/.cache/yarn /root/.yarn/cache 2>/dev/null || true
|
||||||
# Node.js pnpm
|
|
||||||
if command -v pnpm &>/dev/null; then $STD pnpm store prune 2>/dev/null || true; fi
|
|
||||||
# Go
|
|
||||||
if command -v go &>/dev/null; then $STD go clean -cache -modcache 2>/dev/null || true; fi
|
|
||||||
# Rust cargo
|
|
||||||
if command -v cargo &>/dev/null; then $STD cargo clean 2>/dev/null || true; fi
|
|
||||||
# Ruby gem
|
|
||||||
if command -v gem &>/dev/null; then $STD gem cleanup 2>/dev/null || true; fi
|
|
||||||
# Composer (PHP)
|
|
||||||
if command -v composer &>/dev/null; then $STD composer clear-cache 2>/dev/null || true; fi
|
|
||||||
|
|
||||||
if command -v journalctl &>/dev/null; then
|
|
||||||
$STD journalctl --vacuum-time=10m 2>/dev/null || true
|
|
||||||
fi
|
fi
|
||||||
|
if command -v pnpm &>/dev/null; then
|
||||||
|
pnpm store prune &>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Go (only build cache, not modules)
|
||||||
|
if command -v go &>/dev/null; then
|
||||||
|
$STD go clean -cache 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Rust (only registry cache, not build artifacts)
|
||||||
|
if command -v cargo &>/dev/null; then
|
||||||
|
rm -rf /root/.cargo/registry/cache /root/.cargo/.package-cache 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ruby
|
||||||
|
if command -v gem &>/dev/null; then
|
||||||
|
rm -rf /root/.gem/cache 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# PHP
|
||||||
|
if command -v composer &>/dev/null; then
|
||||||
|
rm -rf /root/.composer/cache 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
msg_ok "Cleaned"
|
msg_ok "Cleaned"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -954,14 +944,14 @@ function get_lxc_ip() {
|
|||||||
get_current_ip() {
|
get_current_ip() {
|
||||||
local ip
|
local ip
|
||||||
|
|
||||||
# Try direct interface lookup for eth0 FIRST (most reliable for LXC)
|
# Try direct interface lookup for eth0 FIRST (most reliable for LXC) - IPv4
|
||||||
ip=$(ip -4 addr show eth0 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1)
|
ip=$(ip -4 addr show eth0 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1)
|
||||||
if [[ -n "$ip" && "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
if [[ -n "$ip" && "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||||
echo "$ip"
|
echo "$ip"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Fallback: Try hostname -I
|
# Fallback: Try hostname -I (returns IPv4 first if available)
|
||||||
if command -v hostname >/dev/null 2>&1; then
|
if command -v hostname >/dev/null 2>&1; then
|
||||||
ip=$(hostname -I 2>/dev/null | awk '{print $1}')
|
ip=$(hostname -I 2>/dev/null | awk '{print $1}')
|
||||||
if [[ -n "$ip" && "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
if [[ -n "$ip" && "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||||
@ -970,9 +960,9 @@ function get_lxc_ip() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Last resort: Use routing table
|
# Try routing table with IPv4 targets
|
||||||
local targets=("8.8.8.8" "1.1.1.1" "default")
|
local ipv4_targets=("8.8.8.8" "1.1.1.1" "default")
|
||||||
for target in "${targets[@]}"; do
|
for target in "${ipv4_targets[@]}"; do
|
||||||
if [[ "$target" == "default" ]]; then
|
if [[ "$target" == "default" ]]; then
|
||||||
ip=$(ip route get 1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if ($i=="src") print $(i+1)}')
|
ip=$(ip route get 1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if ($i=="src") print $(i+1)}')
|
||||||
else
|
else
|
||||||
@ -984,6 +974,32 @@ function get_lxc_ip() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# IPv6 fallback: Try direct interface lookup for eth0
|
||||||
|
ip=$(ip -6 addr show eth0 scope global 2>/dev/null | awk '/inet6 / {print $2}' | cut -d/ -f1 | head -n1)
|
||||||
|
if [[ -n "$ip" && "$ip" =~ : ]]; then
|
||||||
|
echo "$ip"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# IPv6 fallback: Try hostname -I for IPv6
|
||||||
|
if command -v hostname >/dev/null 2>&1; then
|
||||||
|
ip=$(hostname -I 2>/dev/null | tr ' ' '\n' | grep -E ':' | head -n1)
|
||||||
|
if [[ -n "$ip" && "$ip" =~ : ]]; then
|
||||||
|
echo "$ip"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# IPv6 fallback: Use routing table with IPv6 targets
|
||||||
|
local ipv6_targets=("2001:4860:4860::8888" "2606:4700:4700::1111")
|
||||||
|
for target in "${ipv6_targets[@]}"; do
|
||||||
|
ip=$(ip -6 route get "$target" 2>/dev/null | awk '{for(i=1;i<=NF;i++) if ($i=="src") print $(i+1)}')
|
||||||
|
if [[ -n "$ip" && "$ip" =~ : ]]; then
|
||||||
|
echo "$ip"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user