Refactor dev MOTD/SSH setup and journal cleanup

Moved MOTD/SSH setup for dev mode in LXC containers to run after installation and when containers are kept for debugging, improving reliability and clarity. Updated journalctl cleanup to avoid using $STD and suppress errors if systemd-journald is not initialized. Also refactored indentation in misc/api.func for consistency.
This commit is contained in:
CanbiZ 2025-11-17 15:09:36 +01:00
parent 1090081a66
commit a7daaee5ae
3 changed files with 172 additions and 163 deletions

View File

@ -48,82 +48,82 @@
# - Shared function with error_handler.func for consistency # - Shared function with error_handler.func for consistency
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
explain_exit_code() { explain_exit_code() {
local code="$1" local code="$1"
case "$code" in case "$code" in
# --- 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?)" ;; 126) echo "Command invoked cannot execute (permission problem?)" ;;
127) echo "Command not found" ;; 127) echo "Command not found" ;;
128) echo "Invalid argument to exit" ;; 128) echo "Invalid argument to exit" ;;
130) echo "Terminated by Ctrl+C (SIGINT)" ;; 130) echo "Terminated by Ctrl+C (SIGINT)" ;;
137) echo "Killed (SIGKILL / Out of memory?)" ;; 137) echo "Killed (SIGKILL / Out of memory?)" ;;
139) echo "Segmentation fault (core dumped)" ;; 139) echo "Segmentation fault (core dumped)" ;;
143) echo "Terminated (SIGTERM)" ;; 143) echo "Terminated (SIGTERM)" ;;
# --- 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" ;; 255) echo "DPKG: Fatal internal error" ;;
# --- Node.js / npm / pnpm / yarn --- # --- Node.js / npm / pnpm / yarn ---
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 "Node.js: Inspector error" ;;
254) echo "npm/pnpm/yarn: Unknown fatal error" ;; 254) echo "npm/pnpm/yarn: Unknown fatal error" ;;
# --- Python / pip / uv --- # --- Python / pip / uv ---
210) echo "Python: Virtualenv / uv environment missing or broken" ;; 210) echo "Python: Virtualenv / uv environment missing or broken" ;;
211) echo "Python: Dependency resolution failed" ;; 211) echo "Python: Dependency resolution failed" ;;
212) echo "Python: Installation aborted (permissions or EXTERNALLY-MANAGED)" ;; 212) echo "Python: Installation aborted (permissions or EXTERNALLY-MANAGED)" ;;
# --- PostgreSQL --- # --- PostgreSQL ---
231) echo "PostgreSQL: Connection failed (server not running / wrong socket)" ;; 231) echo "PostgreSQL: Connection failed (server not running / wrong socket)" ;;
232) echo "PostgreSQL: Authentication failed (bad user/password)" ;; 232) echo "PostgreSQL: Authentication failed (bad user/password)" ;;
233) echo "PostgreSQL: Database does not exist" ;; 233) echo "PostgreSQL: Database does not exist" ;;
234) echo "PostgreSQL: Fatal error in query / syntax" ;; 234) echo "PostgreSQL: Fatal error in query / syntax" ;;
# --- MySQL / MariaDB --- # --- MySQL / MariaDB ---
241) echo "MySQL/MariaDB: Connection failed (server not running / wrong socket)" ;; 241) echo "MySQL/MariaDB: Connection failed (server not running / wrong socket)" ;;
242) echo "MySQL/MariaDB: Authentication failed (bad user/password)" ;; 242) echo "MySQL/MariaDB: Authentication failed (bad user/password)" ;;
243) echo "MySQL/MariaDB: Database does not exist" ;; 243) echo "MySQL/MariaDB: Database does not exist" ;;
244) echo "MySQL/MariaDB: Fatal error in query / syntax" ;; 244) echo "MySQL/MariaDB: Fatal error in query / syntax" ;;
# --- MongoDB --- # --- MongoDB ---
251) echo "MongoDB: Connection failed (server not running)" ;; 251) echo "MongoDB: Connection failed (server not running)" ;;
252) echo "MongoDB: Authentication failed (bad user/password)" ;; 252) echo "MongoDB: Authentication failed (bad user/password)" ;;
253) echo "MongoDB: Database not found" ;; 253) echo "MongoDB: Database not found" ;;
254) echo "MongoDB: Fatal query error" ;; 254) echo "MongoDB: Fatal query error" ;;
# --- Proxmox Custom Codes --- # --- Proxmox Custom Codes ---
200) echo "Custom: Failed to create lock file" ;; 200) echo "Custom: Failed to create lock file" ;;
203) echo "Custom: Missing CTID variable" ;; 203) echo "Custom: Missing CTID variable" ;;
204) echo "Custom: Missing PCT_OSTYPE variable" ;; 204) echo "Custom: Missing PCT_OSTYPE variable" ;;
205) echo "Custom: Invalid CTID (<100)" ;; 205) echo "Custom: Invalid CTID (<100)" ;;
206) echo "Custom: CTID already in use (check 'pct list' and /etc/pve/lxc/)" ;; 206) echo "Custom: CTID already in use (check 'pct list' and /etc/pve/lxc/)" ;;
207) echo "Custom: Password contains unescaped special characters (-, /, \\, *, etc.)" ;; 207) echo "Custom: Password contains unescaped special characters (-, /, \\, *, etc.)" ;;
208) echo "Custom: Invalid configuration (DNS/MAC/Network format error)" ;; 208) echo "Custom: Invalid configuration (DNS/MAC/Network format error)" ;;
209) echo "Custom: Container creation failed (check logs for pct create output)" ;; 209) echo "Custom: Container creation failed (check logs for pct create output)" ;;
210) echo "Custom: Cluster not quorate" ;; 210) echo "Custom: Cluster not quorate" ;;
211) echo "Custom: Timeout waiting for template lock (concurrent download in progress)" ;; 211) echo "Custom: Timeout waiting for template lock (concurrent download in progress)" ;;
214) echo "Custom: Not enough storage space" ;; 214) echo "Custom: Not enough storage space" ;;
215) echo "Custom: Container created but not listed (ghost state - check /etc/pve/lxc/)" ;; 215) echo "Custom: Container created but not listed (ghost state - check /etc/pve/lxc/)" ;;
216) echo "Custom: RootFS entry missing in config (incomplete creation)" ;; 216) echo "Custom: RootFS entry missing in config (incomplete creation)" ;;
217) echo "Custom: Storage does not support rootdir (check storage capabilities)" ;; 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)" ;; 218) echo "Custom: Template file corrupted or incomplete download (size <1MB or invalid archive)" ;;
220) echo "Custom: Unable to resolve template path" ;; 220) echo "Custom: Unable to resolve template path" ;;
221) echo "Custom: Template file exists but not readable (check file permissions)" ;; 221) echo "Custom: Template file exists but not readable (check file permissions)" ;;
222) echo "Custom: Template download failed after 3 attempts (network/storage issue)" ;; 222) echo "Custom: Template download failed after 3 attempts (network/storage issue)" ;;
223) echo "Custom: Template not available after download (storage sync issue)" ;; 223) echo "Custom: Template not available after download (storage sync issue)" ;;
225) echo "Custom: No template available for OS/Version (check 'pveam available')" ;; 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)" ;; 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" ;;
esac esac
} }
# ============================================================================== # ==============================================================================
@ -151,26 +151,26 @@ explain_exit_code() {
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
post_to_api() { post_to_api() {
echo "post_to_api" echo "post_to_api"
if ! command -v curl &>/dev/null; then if ! command -v curl &>/dev/null; then
return return
fi fi
if [ "$DIAGNOSTICS" = "no" ]; then if [ "$DIAGNOSTICS" = "no" ]; then
return return
fi fi
if [ -z "$RANDOM_UUID" ]; then if [ -z "$RANDOM_UUID" ]; then
return return
fi fi
local API_URL="http://api.community-scripts.org/dev/upload" local API_URL="http://api.community-scripts.org/dev/upload"
local pve_version="not found" local pve_version="not found"
pve_version=$(pveversion | awk -F'[/ ]' '{print $2}') pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
JSON_PAYLOAD=$( JSON_PAYLOAD=$(
cat <<EOF cat <<EOF
{ {
"ct_type": $CT_TYPE, "ct_type": $CT_TYPE,
"type":"lxc", "type":"lxc",
@ -186,12 +186,12 @@ post_to_api() {
"random_id": "$RANDOM_UUID" "random_id": "$RANDOM_UUID"
} }
EOF EOF
) )
if [[ "$DIAGNOSTICS" == "yes" ]]; then if [[ "$DIAGNOSTICS" == "yes" ]]; then
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \ RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "$JSON_PAYLOAD") || true -d "$JSON_PAYLOAD") || true
fi fi
} }
@ -209,30 +209,30 @@ EOF
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
post_to_api_vm() { post_to_api_vm() {
if [[ ! -f /usr/local/community-scripts/diagnostics ]]; then if [[ ! -f /usr/local/community-scripts/diagnostics ]]; then
return return
fi fi
DIAGNOSTICS=$(grep -i "^DIAGNOSTICS=" /usr/local/community-scripts/diagnostics | awk -F'=' '{print $2}') DIAGNOSTICS=$(grep -i "^DIAGNOSTICS=" /usr/local/community-scripts/diagnostics | awk -F'=' '{print $2}')
if ! command -v curl &>/dev/null; then if ! command -v curl &>/dev/null; then
return return
fi fi
if [ "$DIAGNOSTICS" = "no" ]; then if [ "$DIAGNOSTICS" = "no" ]; then
return return
fi fi
if [ -z "$RANDOM_UUID" ]; then if [ -z "$RANDOM_UUID" ]; then
return return
fi fi
local API_URL="http://api.community-scripts.org/dev/upload" local API_URL="http://api.community-scripts.org/dev/upload"
local pve_version="not found" local pve_version="not found"
pve_version=$(pveversion | awk -F'[/ ]' '{print $2}') pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
DISK_SIZE_API=${DISK_SIZE%G} DISK_SIZE_API=${DISK_SIZE%G}
JSON_PAYLOAD=$( JSON_PAYLOAD=$(
cat <<EOF cat <<EOF
{ {
"ct_type": 2, "ct_type": 2,
"type":"vm", "type":"vm",
@ -248,12 +248,12 @@ post_to_api_vm() {
"random_id": "$RANDOM_UUID" "random_id": "$RANDOM_UUID"
} }
EOF EOF
) )
if [[ "$DIAGNOSTICS" == "yes" ]]; then if [[ "$DIAGNOSTICS" == "yes" ]]; then
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \ RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "$JSON_PAYLOAD") || true -d "$JSON_PAYLOAD") || true
fi fi
} }
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -276,49 +276,49 @@ EOF
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
post_update_to_api() { post_update_to_api() {
if ! command -v curl &>/dev/null; then if ! command -v curl &>/dev/null; then
return return
fi fi
# Initialize flag if not set (prevents 'unbound variable' error with set -u) # Initialize flag if not set (prevents 'unbound variable' error with set -u)
POST_UPDATE_DONE=${POST_UPDATE_DONE:-false} POST_UPDATE_DONE=${POST_UPDATE_DONE:-false}
if [ "$POST_UPDATE_DONE" = true ]; then if [ "$POST_UPDATE_DONE" = true ]; then
return 0 return 0
fi fi
exit_code=${2:-1} exit_code=${2:-1}
local API_URL="http://api.community-scripts.org/dev/upload/updatestatus" local API_URL="http://api.community-scripts.org/dev/upload/updatestatus"
local status="${1:-failed}" local status="${1:-failed}"
if [[ "$status" == "failed" ]]; then if [[ "$status" == "failed" ]]; then
local exit_code="${2:-1}" local exit_code="${2:-1}"
elif [[ "$status" == "success" ]]; then elif [[ "$status" == "success" ]]; then
local exit_code="${2:-0}" local exit_code="${2:-0}"
fi fi
if [[ -z "$exit_code" ]]; then if [[ -z "$exit_code" ]]; then
exit_code=1 exit_code=1
fi fi
error=$(explain_exit_code "$exit_code") error=$(explain_exit_code "$exit_code")
if [ -z "$error" ]; then if [ -z "$error" ]; then
error="Unknown error" error="Unknown error"
fi fi
JSON_PAYLOAD=$( JSON_PAYLOAD=$(
cat <<EOF cat <<EOF
{ {
"status": "$status", "status": "$status",
"error": "$error", "error": "$error",
"random_id": "$RANDOM_UUID" "random_id": "$RANDOM_UUID"
} }
EOF EOF
) )
if [[ "$DIAGNOSTICS" == "yes" ]]; then if [[ "$DIAGNOSTICS" == "yes" ]]; then
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \ RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "$JSON_PAYLOAD") || true -d "$JSON_PAYLOAD") || true
fi fi
POST_UPDATE_DONE=true POST_UPDATE_DONE=true
} }

View File

@ -2746,21 +2746,6 @@ EOF'
# Install SSH keys # Install SSH keys
install_ssh_keys_into_ct install_ssh_keys_into_ct
# Dev mode: Setup MOTD/SSH AFTER network is ready and before installation
# This ensures the container is fully booted and accessible via SSH
if [[ "${DEV_MODE_MOTD:-false}" == "true" ]]; then
msg_dev "Setting up MOTD and SSH for debugging access"
# Load common install functions and run motd_ssh if available
if pct exec "$CTID" -- bash -c "
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/install.func)
declare -f motd_ssh >/dev/null 2>&1 && motd_ssh || true
" >/dev/null 2>&1; then
msg_dev "MOTD/SSH ready - container accessible via SSH (IP: $ip_in_lxc)"
else
msg_warn "MOTD/SSH setup failed, but continuing with installation"
fi
fi
# Run application installer # Run application installer
# NOTE: We disable error handling here because: # NOTE: We disable error handling here because:
# 1. Container errors are caught by error_handler INSIDE container # 1. Container errors are caught by error_handler INSIDE container
@ -2850,6 +2835,18 @@ EOF'
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}" echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
elif [[ "$response" =~ ^[Nn]$ ]]; then elif [[ "$response" =~ ^[Nn]$ ]]; then
echo -e "\n${TAB}${YW}Container ${CTID} kept for debugging${CL}" echo -e "\n${TAB}${YW}Container ${CTID} kept for debugging${CL}"
# Dev mode: Setup MOTD/SSH for debugging access to broken container
if [[ "${DEV_MODE_MOTD:-false}" == "true" ]]; then
echo -e "${TAB}${HOLD}${DGN}Setting up MOTD and SSH for debugging...${CL}"
if pct exec "$CTID" -- bash -c "
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/install.func)
declare -f motd_ssh >/dev/null 2>&1 && motd_ssh || true
" >/dev/null 2>&1; then
local ct_ip=$(pct exec "$CTID" ip a s dev eth0 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1)
echo -e "${BFR}${CM}${GN}MOTD/SSH ready - SSH into container: ssh root@${ct_ip}${CL}"
fi
fi
fi fi
else else
# Timeout - auto-remove # Timeout - auto-remove
@ -3760,6 +3757,17 @@ create_lxc_container() {
# - Posts final "done" status to API telemetry # - Posts final "done" status to API telemetry
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
description() { description() {
# Dev mode: Setup MOTD/SSH on successful installation
if [[ "${DEV_MODE_MOTD:-false}" == "true" ]]; then
msg_dev "Setting up MOTD and SSH for debugging access"
if pct exec "$CTID" -- bash -c "
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/install.func)
declare -f motd_ssh >/dev/null 2>&1 && motd_ssh || true
" >/dev/null 2>&1; then
msg_dev "MOTD/SSH configured successfully"
fi
fi
IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1) IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
# Generate LXC Description # Generate LXC Description

View File

@ -834,8 +834,9 @@ cleanup_lxc() {
if command -v composer &>/dev/null; then $STD composer clear-cache || true; fi if command -v composer &>/dev/null; then $STD composer clear-cache || true; fi
if command -v journalctl &>/dev/null; then if command -v journalctl &>/dev/null; then
$STD journalctl --rotate || true # Journal rotation may fail if systemd-journald not fully initialized yet
$STD journalctl --vacuum-time=10m || true journalctl --rotate 2>/dev/null || true
journalctl --vacuum-time=10m 2>/dev/null || true
fi fi
msg_ok "Cleaned" msg_ok "Cleaned"
} }