From 62de6db2afcbcc68e07b7164b698d34dbbd2dc51 Mon Sep 17 00:00:00 2001 From: "courtmanr@gmail.com" Date: Tue, 29 Apr 2025 11:55:36 +0100 Subject: [PATCH] fix: Correct case statement syntax in install script --- scripts/install-pulse.sh | 340 +++++++++++++++++++-------------------- 1 file changed, 170 insertions(+), 170 deletions(-) diff --git a/scripts/install-pulse.sh b/scripts/install-pulse.sh index b09ca1303..151f84b4f 100644 --- a/scripts/install-pulse.sh +++ b/scripts/install-pulse.sh @@ -4,7 +4,7 @@ # This script automates the installation and setup of Pulse within a Proxmox LXC container. # --- Configuration --- -NODE_MAJOR_VERSION=20 # Specify the desired Node.js major version (e.g., 18, 20) +NODE_MAJOR_VERSION=20 # Specify the desired Node.js major version (e.g., 18, 20*) PULSE_DIR="/opt/pulse-proxmox" PULSE_USER="pulse" # Dedicated user to run Pulse SERVICE_NAME="pulse-monitor.service" @@ -19,38 +19,38 @@ INSTALL_MODE="" # Stores the determined action: install, update, remove, cance # --- Argument Parsing --- while [[ "$#" -gt 0 ]]; do case $1 in - --update) MODE_UPDATE=true ;; - *) echo "Unknown parameter passed: $1"; exit 1 ;; + --update*) MODE_UPDATE=true ;; + **) echo "Unknown parameter passed: $1"; exit 1 ;; esac shift done # --- Helper Functions --- -print_info() { +print_info(*) { echo -e "\033[1;34m[INFO]\033[0m $1" } -print_success() { +print_success(*) { echo -e "\033[1;32m[SUCCESS]\033[0m $1" } -print_warning() { +print_warning(*) { echo -e "\033[1;33m[WARNING]\033[0m $1" } -print_error() { +print_error(*) { echo -e "\033[1;31m[ERROR]\033[0m $1 >&2 } -check_root() { - if [ "$(id -u)" -ne 0 ]; then +check_root(*) { + if [ "$(id -u*)" -ne 0 ]; then print_error "This script must be run as root. Please use sudo." exit 1 fi } # --- Installation Status Check & Action Determination --- -check_installation_status_and_determine_action() { +check_installation_status_and_determine_action(*) { # Check if running in non-interactive update mode FIRST if [ "$MODE_UPDATE" = true ]; then print_info "Running in non-interactive update mode..." @@ -72,15 +72,15 @@ check_installation_status_and_determine_action() { INSTALL_MODE="" else # Compare local HEAD with remote main - local_head=$(sudo -u "$PULSE_USER" git rev-parse HEAD 2>/dev/null) - remote_main=$(sudo -u "$PULSE_USER" git rev-parse origin/main 2>/dev/null) + local_head=$(sudo -u "$PULSE_USER" git rev-parse HEAD 2>/dev/null*) + remote_main=$(sudo -u "$PULSE_USER" git rev-parse origin/main 2>/dev/null*) if [ "$local_head" = "$remote_main" ]; then print_info "Pulse is already installed and up-to-date with the main branch." INSTALL_MODE="uptodate" else # Escape parentheses in the warning string - print_warning "Pulse is installed, but an update is available \(local: ${local_head:0:7}, remote: ${remote_main:0:7}\)." + print_warning "Pulse is installed, but an update is available \(local: ${local_head:0:7}, remote: ${remote_main:0:7}*)." # Set default mode to update if different INSTALL_MODE="update" fi @@ -90,55 +90,55 @@ check_installation_status_and_determine_action() { # Prompt based on status if [ "$INSTALL_MODE" = "uptodate" ]; then echo "Choose an action:" - echo " 1) Re-run installation/update process anyway" - echo " 2) Remove Pulse" - echo " 3) Cancel" - read -p "Enter your choice (1-3): " user_choice + echo " 1*) Re-run installation/update process anyway" + echo " 2*) Remove Pulse" + echo " 3*) Cancel" + read -p "Enter your choice (1-3*): " user_choice case $user_choice in - 1) INSTALL_MODE="update" ;; # Treat re-run as update - 2) INSTALL_MODE="remove" ;; - 3) INSTALL_MODE="cancel" ;; - *) print_error "Invalid choice."; INSTALL_MODE="error" ;; + 1*) INSTALL_MODE="update" ;; # Treat re-run as update + 2*) INSTALL_MODE="remove" ;; + 3*) INSTALL_MODE="cancel" ;; + **) print_error "Invalid choice."; INSTALL_MODE="error" ;; esac else # Covers case where fetch failed OR update is available echo "Choose an action:" - echo " 1) Update Pulse to the latest version" - echo " 2) Remove Pulse" - echo " 3) Cancel" - read -p "Enter your choice (1-3): " user_choice + echo " 1*) Update Pulse to the latest version" + echo " 2*) Remove Pulse" + echo " 3*) Cancel" + read -p "Enter your choice (1-3*): " user_choice case $user_choice in - 1) INSTALL_MODE="update" ;; - 2) INSTALL_MODE="remove" ;; - 3) INSTALL_MODE="cancel" ;; - *) print_error "Invalid choice."; INSTALL_MODE="error" ;; + 1*) INSTALL_MODE="update" ;; + 2*) INSTALL_MODE="remove" ;; + 3*) INSTALL_MODE="cancel" ;; + **) print_error "Invalid choice."; INSTALL_MODE="error" ;; esac fi else # Directory exists but isn't a git repository print_error "Directory $PULSE_DIR exists but does not appear to be a valid Pulse git repository." - print_error "Please remove this directory manually ($PULSE_DIR) or choose a different installation path and re-run the script." + print_error "Please remove this directory manually ($PULSE_DIR*) or choose a different installation path and re-run the script." INSTALL_MODE="error" fi else # Directory doesn't exist - Offer Install/Cancel print_info "Pulse is not currently installed." echo "Choose an action:" - echo " 1) Install Pulse" - echo " 2) Cancel" - read -p "Enter your choice (1-2): " user_choice + echo " 1*) Install Pulse" + echo " 2*) Cancel" + read -p "Enter your choice (1-2*): " user_choice case $user_choice in - 1) INSTALL_MODE="install" ;; - 2) INSTALL_MODE="cancel" ;; - *) print_error "Invalid choice."; INSTALL_MODE="error" ;; + 1*) INSTALL_MODE="install" ;; + 2*) INSTALL_MODE="cancel" ;; + **) print_error "Invalid choice."; INSTALL_MODE="error" ;; esac fi # We don't return here, INSTALL_MODE is now set globally for the main logic } -# --- System Setup Functions --- (apt_update_upgrade, install_dependencies, setup_node, create_pulse_user) -apt_update_upgrade() { +# --- System Setup Functions --- (apt_update_upgrade, install_dependencies, setup_node, create_pulse_user*) +apt_update_upgrade(*) { print_info "Updating package lists and upgrading packages..." if apt-get update > /dev/null && apt-get upgrade -y > /dev/null; then print_success "System packages updated and upgraded." @@ -148,8 +148,8 @@ apt_update_upgrade() { fi } -install_dependencies() { - print_info "Installing necessary dependencies (git, curl, sudo, gpg)..." +install_dependencies(*) { + print_info "Installing necessary dependencies (git, curl, sudo, gpg*)..." if apt-get install -y git curl sudo gpg > /dev/null; then print_success "Dependencies installed." else @@ -158,17 +158,17 @@ install_dependencies() { fi } -setup_node() { - print_info "Setting up Node.js repository (NodeSource)..." +setup_node(*) { + print_info "Setting up Node.js repository (NodeSource*)..." # Check if Node.js is already installed and meets version requirement if command -v node &> /dev/null; then - current_node_version=$(node -v 2>/dev/null) - current_major_version=$(echo "$current_node_version" | sed 's/v//' | cut -d. -f1) + current_node_version=$(node -v 2>/dev/null*) + current_major_version=$(echo "$current_node_version" | sed 's/v//' | cut -d. -f1*) if [[ -n "$current_major_version" ]] && [[ "$current_major_version" -ge "$NODE_MAJOR_VERSION" ]]; then - print_info "Node.js version ${current_node_version} already installed and meets requirement (>= v${NODE_MAJOR_VERSION}.x). Skipping setup." + print_info "Node.js version ${current_node_version} already installed and meets requirement (>= v${NODE_MAJOR_VERSION}.x*). Skipping setup." return 0 else - print_warning "Installed Node.js version ($current_node_version) does not meet requirement (>= v${NODE_MAJOR_VERSION}.x) or could not be determined. Proceeding with setup..." + print_warning "Installed Node.js version ($current_node_version*) does not meet requirement (>= v${NODE_MAJOR_VERSION}.x*) or could not be determined. Proceeding with setup..." fi else print_info "Node.js not found. Proceeding with setup..." @@ -176,7 +176,7 @@ setup_node() { # Check if curl is installed before using it if ! command -v curl &> /dev/null; then - print_error "curl is required but not found. Please install it first (apt-get install curl)." + print_error "curl is required but not found. Please install it first (apt-get install curl*)." exit 1 fi @@ -212,8 +212,8 @@ setup_node() { print_info "Installing Node.js ${NODE_MAJOR_VERSION}.x..." if apt-get install nodejs -y > /dev/null; then print_success "Node.js ${NODE_MAJOR_VERSION}.x installed successfully." - print_info "Node version: $(node -v)" - print_info "npm version: $(npm -v)" + print_info "Node version: $(node -v*)" + print_info "npm version: $(npm -v*)" else print_error "Failed to install Node.js." # Attempt cleanup @@ -222,12 +222,12 @@ setup_node() { fi } -create_pulse_user() { +create_pulse_user(*) { print_info "Creating dedicated user '$PULSE_USER'..." if id "$PULSE_USER" &>/dev/null; then print_warning "User '$PULSE_USER' already exists. Skipping creation." else - # Create a system user with no login shell and no home directory (or specify one if needed) + # Create a system user with no login shell and no home directory (or specify one if needed*) useradd -r -s /bin/false "$PULSE_USER" if [ $? -eq 0 ]; then print_success "User '$PULSE_USER' created successfully." @@ -240,15 +240,15 @@ create_pulse_user() { fi } -# --- Core Action Functions --- (perform_update, perform_remove) -perform_update() { +# --- Core Action Functions --- (perform_update, perform_remove*) +perform_update(*) { print_info "Attempting to update Pulse..." cd "$PULSE_DIR" || { print_error "Failed to change directory to $PULSE_DIR"; return 1; } # Add safe directory config for root user, just in case git config --global --add safe.directory "$PULSE_DIR" > /dev/null 2>&1 || print_warning "Could not configure safe.directory for root user." - print_info "Fetching latest changes from git (running as user $PULSE_USER)..." + print_info "Fetching latest changes from git (running as user $PULSE_USER*)..." # Add --force to allow overwriting local tags if they conflict with remote after amends/force-pushes if ! sudo -u "$PULSE_USER" git fetch origin --tags --force; then # Ensure tags are fetched print_error "Failed to fetch latest changes from git." @@ -266,19 +266,19 @@ perform_update() { # Get the latest tag pointing to the current HEAD local latest_tag - latest_tag=$(sudo -u "$PULSE_USER" git describe --tags --abbrev=0 HEAD 2>/dev/null) + latest_tag=$(sudo -u "$PULSE_USER" git describe --tags --abbrev=0 HEAD 2>/dev/null*) - print_info "Cleaning repository (removing untracked files)..." + print_info "Cleaning repository (removing untracked files*)..." # Remove untracked files and directories to ensure a clean state # Use -f for files, -d for directories. Do NOT use -x which removes ignored files like .env if ! sudo -u "$PULSE_USER" git clean -fd; then print_warning "Failed to clean untracked files from the repository." - # Continue anyway, as the core update (reset) succeeded + # Continue anyway, as the core update (reset*) succeeded fi # Ensure the script itself remains executable after update if [ -n "$SCRIPT_ABS_PATH" ] && [ -f "$SCRIPT_ABS_PATH" ]; then - print_info "Ensuring install script ($SCRIPT_ABS_PATH) is executable..." + print_info "Ensuring install script ($SCRIPT_ABS_PATH*) is executable..." if chmod +x "$SCRIPT_ABS_PATH"; then print_success "Install script executable permission set." else @@ -286,15 +286,15 @@ perform_update() { # Not necessarily fatal, continue update fi else - print_warning "Could not find script path ($SCRIPT_ABS_PATH) to ensure executable permission." + print_warning "Could not find script path ($SCRIPT_ABS_PATH*) to ensure executable permission." fi - print_info "Re-installing npm dependencies (root)..." + print_info "Re-installing npm dependencies (root*)..." # Keep --omit=dev here, we'll install cli separately # Use npm ci for faster, cleaner installs based on lock file if ! npm ci --unsafe-perm > /dev/null 2>&1; then print_warning "Failed to install root npm dependencies using npm ci. Trying npm install..." - # Fallback to npm install if ci fails (e.g., no lock file initially) + # Fallback to npm install if ci fails (e.g., no lock file initially*) if ! npm install --unsafe-perm > /dev/null 2>&1; then print_warning "Fallback npm install also failed for root dependencies. Continuing..." else @@ -335,21 +335,21 @@ perform_update() { set_permissions # Ensure permissions are correct after update and build # Ensure the systemd service is configured correctly before restarting - print_info "Ensuring systemd service ($SERVICE_NAME) is configured..." - if ! setup_systemd_service true; then # Pass true to indicate update mode (skip start/enable) + print_info "Ensuring systemd service ($SERVICE_NAME*) is configured..." + if ! setup_systemd_service true; then # Pass true to indicate update mode (skip start/enable*) print_error "Failed to configure systemd service during update." # Decide if this should be fatal, likely yes as restart will fail return 1 fi - print_info "===> Attempting to restart Pulse service ($SERVICE_NAME)..." + print_info "===> Attempting to restart Pulse service ($SERVICE_NAME*)..." systemctl restart "$SERVICE_NAME" local restart_exit_code=$? if [ $restart_exit_code -eq 0 ]; then - print_success "Pulse service restart command finished successfully (Exit code: $restart_exit_code)." + print_success "Pulse service restart command finished successfully (Exit code: $restart_exit_code*)." else - print_error "Pulse service restart command failed (Exit code: $restart_exit_code)." + print_error "Pulse service restart command failed (Exit code: $restart_exit_code*)." print_info "Attempting to display the last 20 lines of the service log:" # Use --no-pager to prevent blocking in script journalctl -u "$SERVICE_NAME" -n 20 --no-pager @@ -368,13 +368,13 @@ perform_update() { return 0 } -perform_remove() { - print_warning "This will stop and disable the Pulse service(s) and remove the installation directory ($PULSE_DIR)." +perform_remove(*) { + print_warning "This will stop and disable the Pulse service(s*) and remove the installation directory ($PULSE_DIR*)." # Allow non-interactive removal if called directly with logic before # For now, keep interactive confirmation here local remove_confirm="" if [ -t 0 ]; then # Check if stdin is a terminal for interactive prompt - read -p "Are you sure you want to remove Pulse? (y/N): " remove_confirm + read -p "Are you sure you want to remove Pulse? (y/N*): " remove_confirm if [[ ! "$remove_confirm" =~ ^[Yy]$ ]]; then print_info "Removal cancelled." return 1 # Indicate cancellation @@ -384,20 +384,20 @@ perform_remove() { fi # List of potential service names to remove - local potential_services=("pulse-monitor.service" "pulse-proxmox.service") + local potential_services=("pulse-monitor.service" "pulse-proxmox.service"*) local service_removed=false for service_name in "${potential_services[@]}"; do local service_file_path="/etc/systemd/system/$service_name" if systemctl list-units --full -all | grep -q "$service_name"; then - print_info "Stopping service ($service_name)..." + print_info "Stopping service ($service_name*)..." systemctl stop "$service_name" > /dev/null 2>&1 # Ignore errors if already stopped - print_info "Disabling service ($service_name)..." + print_info "Disabling service ($service_name*)..." systemctl disable "$service_name" > /dev/null 2>&1 # Ignore errors if already disabled if [ -f "$service_file_path" ]; then - print_info "Removing systemd service file ($service_file_path)..." + print_info "Removing systemd service file ($service_file_path*)..." rm -f "$service_file_path" if [ $? -eq 0 ]; then print_success "Service file $service_file_path removed." @@ -412,7 +412,7 @@ perform_remove() { print_info "Service $service_name not found, skipping stop/disable." # Also check if the file exists even if service isn't loaded if [ -f "$service_file_path" ]; then - print_info "Removing orphaned systemd service file ($service_file_path)..." + print_info "Removing orphaned systemd service file ($service_file_path*)..." rm -f "$service_file_path" if [ $? -eq 0 ]; then print_success "Orphaned service file $service_file_path removed." @@ -430,7 +430,7 @@ perform_remove() { systemctl daemon-reload fi - print_info "Removing Pulse installation directory ($PULSE_DIR)..." + print_info "Removing Pulse installation directory ($PULSE_DIR*)..." if rm -rf "$PULSE_DIR"; then print_success "Installation directory removed." else @@ -442,8 +442,8 @@ perform_remove() { return 0 } -# --- Installation Step Functions --- (install_npm_deps, set_permissions, configure_environment, setup_systemd_service) -install_npm_deps() { +# --- Installation Step Functions --- (install_npm_deps, set_permissions, configure_environment, setup_systemd_service*) +install_npm_deps(*) { print_info "Installing npm dependencies..." if [ ! -d "$PULSE_DIR" ]; then print_error "Pulse directory $PULSE_DIR not found. Cannot install dependencies." @@ -453,7 +453,7 @@ install_npm_deps() { cd "$PULSE_DIR" || { print_error "Failed to change directory to $PULSE_DIR"; return 1; } - print_info "Installing root dependencies (including dev)..." + print_info "Installing root dependencies (including dev*)..." # Use --unsafe-perm if running npm install as root, which might be necessary for some packages # REMOVED --omit=dev to ensure build tools like postcss/autoprefixer are present if npm install --unsafe-perm > /dev/null 2>&1; then @@ -463,7 +463,7 @@ install_npm_deps() { return 1 fi - print_info "Installing server dependencies (including dev)..." + print_info "Installing server dependencies (including dev*)..." cd server || { print_error "Failed to change directory to $PULSE_DIR/server"; cd ..; return 1; } # REMOVED --omit=dev if npm install --unsafe-perm > /dev/null 2>&1; then @@ -479,7 +479,7 @@ install_npm_deps() { return 0 } -set_permissions() { +set_permissions(*) { print_info "Setting permissions for $PULSE_DIR..." if chown -R "$PULSE_USER":"$PULSE_USER" "$PULSE_DIR"; then print_success "Permissions set correctly." @@ -495,14 +495,14 @@ set_permissions() { # --- Helper function to safely read .env files --- # Reads a .env file, ignoring comments and empty lines, populating an associative array. # Usage: declare -A env_vars; read_env_file "path/to/.env" env_vars -read_env_file() { +read_env_file(*) { local env_file="$1" local -n arr="$2" # Use nameref for the associative array - arr=() # Clear the array + arr=(*) # Clear the array if [ -f "$env_file" ]; then while IFS= read -r line || [[ -n "$line" ]]; do # Trim leading/trailing whitespace - line=$(echo "$line" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') + line=$(echo "$line" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'*) # Skip empty lines and comments if [[ -z "$line" || "$line" == \#* ]]; then continue @@ -510,8 +510,8 @@ read_env_file() { # Simple split on the first '=', allows values to contain '=' local key="${line%%=*}" local value="${line#*=}" - # Trim potential quotes from value (basic handling) - value=$(echo "$value" | sed -e 's/^"//' -e 's/"$/' -e "s/^'//" -e "s/'$//") + # Trim potential quotes from value (basic handling*) + value=$(echo "$value" | sed -e 's/^"//' -e 's/"$/' -e "s/^'//" -e "s/'$//"*) arr["$key"]="$value" done < "$env_file" fi @@ -519,7 +519,7 @@ read_env_file() { # --- Helper function to prompt with default --- # Usage: prompt_with_default VARIABLE_NAME PROMPT_TEXT [CURRENT_VALUE] -prompt_with_default() { +prompt_with_default(*) { local var_name="$1" local prompt_text="$2" local current_value="$3" # Optional current value @@ -542,10 +542,10 @@ prompt_with_default() { # --- Helper function to prompt for secret with default --- # Usage: prompt_secret_with_default VARIABLE_NAME PROMPT_TEXT [HAS_CURRENT_VALUE] -prompt_secret_with_default() { +prompt_secret_with_default(*) { local var_name="$1" local prompt_text="$2" - local has_current_value=$3 # Boolean (true/false) indicates if a value exists + local has_current_value=$3 # Boolean (true/false*) indicates if a value exists local user_input if [ "$has_current_value" = true ]; then @@ -556,7 +556,7 @@ prompt_secret_with_default() { echo # Assign the new value printf -v "$var_name" '%s' "$user_input" - # Set a flag or return value indicating it was changed (optional, handled by direct assignment here) + # Set a flag or return value indicating it was changed (optional, handled by direct assignment here*) else # Indicate value should be kept - assign a special value or handle upstream printf -v "$var_name" '%s' "__KEEP_SECRET__" # Special marker @@ -570,7 +570,7 @@ prompt_secret_with_default() { fi } -configure_environment() { +configure_environment(*) { print_info "Configuring Pulse environment..." local env_example_path="$PULSE_DIR/.env.example" local env_path="$PULSE_DIR/.env" @@ -589,7 +589,7 @@ configure_environment() { fi # Define the primary keys we need to configure - local config_keys=("PROXMOX_HOST" "PROXMOX_TOKEN_ID" "PROXMOX_TOKEN_SECRET" "PROXMOX_ALLOW_SELF_SIGNED_CERTS" "PORT") + local config_keys=("PROXMOX_HOST" "PROXMOX_TOKEN_ID" "PROXMOX_TOKEN_SECRET" "PROXMOX_ALLOW_SELF_SIGNED_CERTS" "PORT"*) # Variables to store collected values local proxmox_host="" @@ -618,16 +618,16 @@ configure_environment() { print_info "Using Proxmox Host URL: $proxmox_host" fi - # --- Display Token Generation Info --- (Only if Token ID or Secret is missing/being changed) + # --- Display Token Generation Info --- (Only if Token ID or Secret is missing/being changed*) if [ -z "${current_env_vars[PROXMOX_TOKEN_ID]}" ] || [ -z "${current_env_vars[PROXMOX_TOKEN_SECRET]}" ]; then echo "" print_info "You need a Proxmox API Token. You can create one via the Proxmox Web UI," print_info "or run the following commands on your Proxmox host shell:" echo "----------------------------------------------------------------------" - echo ' # 1. Create user 'pulse-monitor' (enter password when prompted):' + echo ' # 1. Create user 'pulse-monitor' (enter password when prompted*):' echo " pveum useradd pulse-monitor@pam -comment "API user for Pulse monitoring"" echo ' ' - echo ' # 2. Create API token 'pulse' for user (COPY THE SECRET VALUE!):' + echo ' # 2. Create API token 'pulse' for user (COPY THE SECRET VALUE!*):' echo " pveum user token add pulse-monitor@pam pulse --privsep=1" echo ' ' echo ' # 3. Assign PVEAuditor role to user:' @@ -661,10 +661,10 @@ configure_environment() { # --- Get Self-Signed Cert Preference --- local current_self_signed="${current_env_vars[PROXMOX_ALLOW_SELF_SIGNED_CERTS]}" - local self_signed_prompt="Allow self-signed certificates? (y/N)" + local self_signed_prompt="Allow self-signed certificates? (y/N*)" local self_signed_default_display="" if [ "$current_self_signed" = "true" ]; then - self_signed_prompt="Allow self-signed certificates? (Y/n)" + self_signed_prompt="Allow self-signed certificates? (Y/n*)" self_signed_default_display="Y" elif [ "$current_self_signed" = "false" ]; then self_signed_default_display="n" @@ -684,7 +684,7 @@ configure_environment() { fi # Handle case where current value was not 'true' or 'false' if [[ "$allow_self_signed" != "true" && "$allow_self_signed" != "false" ]]; then - print_warning "Invalid or missing current value for self-signed certs. Defaulting to 'true' (Yes)." + print_warning "Invalid or missing current value for self-signed certs. Defaulting to 'true' (Yes*)." allow_self_signed="true" # Default to true if invalid/missing fi @@ -693,7 +693,7 @@ configure_environment() { prompt_with_default pulse_port " -> Port for Pulse server" "$current_port" if [ -n "$pulse_port" ]; then if ! [[ "$pulse_port" =~ ^[0-9]+$ ]] || [ "$pulse_port" -lt 1 ] || [ "$pulse_port" -gt 65535 ]; then - print_warning "Invalid port number entered ($pulse_port). Using current/default: $current_port." + print_warning "Invalid port number entered ($pulse_port*). Using current/default: $current_port." pulse_port="$current_port" fi else @@ -705,11 +705,11 @@ configure_environment() { print_info "No existing configuration file found. Please provide details:" needs_update=true # Will create the file - # --- Gather Proxmox Details (Original Logic) --- - read -p " -> Proxmox Host URL (e.g., https://192.168.1.100:8006): " proxmox_host + # --- Gather Proxmox Details (Original Logic*) --- + read -p " -> Proxmox Host URL (e.g., https://192.168.1.100:8006*): " proxmox_host while [ -z "$proxmox_host" ]; do print_warning "Proxmox Host URL cannot be empty." - read -p " -> Proxmox Host URL (e.g., https://192.168.1.100:8006): " proxmox_host + read -p " -> Proxmox Host URL (e.g., https://192.168.1.100:8006*): " proxmox_host done if [[ ! "$proxmox_host" =~ ^https?:// ]]; then print_warning "URL does not start with http:// or https://. Prepending https://." @@ -734,7 +734,7 @@ configure_environment() { echo "Paste the Token ID and Secret Value below." echo "" - read -p " -> Proxmox API Token ID (e.g., user@pam!tokenid): " proxmox_token_id + read -p " -> Proxmox API Token ID (e.g., user@pam!tokenid*): " proxmox_token_id while [ -z "$proxmox_token_id" ]; do print_warning "Proxmox Token ID cannot be empty." read -p " -> Proxmox API Token ID: " proxmox_token_id @@ -750,7 +750,7 @@ configure_environment() { # --- Optional Settings --- local allow_self_signed_input="" - read -p " -> Allow self-signed certificates for Proxmox? (Y/n): " allow_self_signed_input + read -p " -> Allow self-signed certificates for Proxmox? (Y/n*): " allow_self_signed_input if [[ "$allow_self_signed_input" =~ ^[Nn]$ ]]; then allow_self_signed="false" else @@ -758,7 +758,7 @@ configure_environment() { fi local pulse_port_input="" - read -p " -> Port for Pulse server (leave blank for default 7655): " pulse_port_input + read -p " -> Port for Pulse server (leave blank for default 7655*): " pulse_port_input if [ -n "$pulse_port_input" ]; then if [[ "$pulse_port_input" =~ ^[0-9]+$ ]] && [ "$pulse_port_input" -ge 1 ] && [ "$pulse_port_input" -le 65535 ]; then pulse_port="$pulse_port_input" @@ -807,15 +807,15 @@ configure_environment() { for key in "${config_keys[@]}"; do local value="" case $key in - PROXMOX_HOST) value="$proxmox_host" ;; - PROXMOX_TOKEN_ID) value="$proxmox_token_id" ;; - PROXMOX_TOKEN_SECRET) value="$proxmox_token_secret" ;; - PROXMOX_ALLOW_SELF_SIGNED_CERTS) value="$allow_self_signed" ;; - PORT) value="$pulse_port" ;; + PROXMOX_HOST*) value="$proxmox_host" ;; + PROXMOX_TOKEN_ID*) value="$proxmox_token_id" ;; + PROXMOX_TOKEN_SECRET*) value="$proxmox_token_secret" ;; + PROXMOX_ALLOW_SELF_SIGNED_CERTS*) value="$allow_self_signed" ;; + PORT*) value="$pulse_port" ;; esac - # Escape sed replacement characters in the value (especially / and &) - local escaped_value=$(sed -e 's/[\\/&]/\\\\&/g' <<< "$value") + # Escape sed replacement characters in the value (especially / and &*) + local escaped_value=$(sed -e 's/[\\/&]/\\\\&/g' <<< "$value"*) # Check if key exists and update, otherwise append # Use a different delimiter for sed like '#' to avoid clashes with URL slashes @@ -842,28 +842,28 @@ configure_environment() { return 0 } -setup_systemd_service() { +setup_systemd_service(*) { # Add optional argument to skip start/enable during updates local update_mode=${1:-false} # Default to false if no argument passed - print_info "Setting up systemd service ($SERVICE_NAME)..." + print_info "Setting up systemd service ($SERVICE_NAME*)..." local service_file="/etc/systemd/system/$SERVICE_NAME" - # Find Node path (needed for systemd ExecStart) + # Find Node path (needed for systemd ExecStart*) local node_path - node_path=$(command -v node) + node_path=$(command -v node*) if [ -z "$node_path" ]; then print_error "Could not find Node.js executable path. Cannot create service." return 1 fi - # Find npm path (needed for systemd ExecStart) + # Find npm path (needed for systemd ExecStart*) local npm_path - npm_path=$(command -v npm) + npm_path=$(command -v npm*) if [ -z "$npm_path" ]; then print_warning "Could not find npm executable path. Service might require adjustment." # Try to find it relative to node? Often in ../lib/node_modules/npm/bin/npm-cli.js local node_dir - node_dir=$(dirname "$node_path") + node_dir=$(dirname "$node_path"*) # This is a common structure, adjust if needed npm_path="$node_dir/npm" # Adjust if npm is installed elsewhere if ! command -v "$npm_path" &> /dev/null; then @@ -897,7 +897,7 @@ ExecStart=$node_path $npm_path run start Restart=on-failure RestartSec=5 -# Environment (optional, if needed, but .env should handle this) +# Environment (optional, if needed, but .env should handle this*) # Environment="NODE_ENV=production" # Standard output/error logging @@ -921,7 +921,7 @@ EOF # Skip enable/start if in update mode if [ "$update_mode" = true ]; then - print_info "(Update mode: Skipping service enable/start)" + print_info "(Update mode: Skipping service enable/start*)" return 0 fi @@ -942,7 +942,7 @@ EOF if [ $start_exit_code -eq 0 ]; then print_success "Service started successfully." else - print_error "Failed to start systemd service (Exit code: $start_exit_code)." + print_error "Failed to start systemd service (Exit code: $start_exit_code*)." print_info "Attempting to display the last 20 lines of the service log:" # Use --no-pager to prevent blocking in script journalctl -u "$SERVICE_NAME" -n 20 --no-pager @@ -955,17 +955,17 @@ EOF return 0 } -# --- Final Steps Functions --- (setup_cron_update, disable_cron_update, prompt_for_cron_setup, final_instructions) +# --- Final Steps Functions --- (setup_cron_update, disable_cron_update, prompt_for_cron_setup, final_instructions*) # Function to specifically disable the cron job -disable_cron_update() { +disable_cron_update(*) { print_info "Disabling Pulse automatic update cron job..." - local cron_identifier="# Pulse-Auto-Update ($SCRIPT_NAME)" + local cron_identifier="# Pulse-Auto-Update ($SCRIPT_NAME*)" local escaped_cron_identifier - escaped_cron_identifier=$(sed 's/[/.*^$]/\\&/g' <<< "$cron_identifier") + escaped_cron_identifier=$(sed 's/[/.*^$]/\\&/g' <<< "$cron_identifier"*) # Get current crontab content or empty string if none exists - current_cron=$(crontab -l -u root 2>/dev/null || true) + current_cron=$(crontab -l -u root 2>/dev/null || true*) # Check if the job actually exists before trying to remove if ! echo "$current_cron" | grep -q "^${escaped_cron_identifier}$"; then @@ -974,7 +974,7 @@ disable_cron_update() { fi # Use sed to remove the identifier line and the line immediately following it. - filtered_cron=$(echo "$current_cron" | sed "/^${escaped_cron_identifier}$/{N;d;}") + filtered_cron=$(echo "$current_cron" | sed "/^${escaped_cron_identifier}$/{N;d;}"*) # Load the modified crontab content # Handle case where removing the job leaves the crontab empty @@ -993,12 +993,12 @@ disable_cron_update() { return 0 } -setup_cron_update() { +setup_cron_update(*) { local cron_schedule="" local cron_command="" local script_path="$SCRIPT_ABS_PATH" local escaped_script_path # For grep/sed patterns - local cron_identifier="# Pulse-Auto-Update ($SCRIPT_NAME)" # Identifier comment + local cron_identifier="# Pulse-Auto-Update ($SCRIPT_NAME*)" # Identifier comment local escaped_cron_identifier if [ -z "$script_path" ] || [ ! -f "$script_path" ]; then @@ -1006,21 +1006,21 @@ setup_cron_update() { return 1 fi # Escape necessary characters for sed pattern matching - escaped_cron_identifier=$(sed 's/[/.*^$]/\\&/g' <<< "$cron_identifier") + escaped_cron_identifier=$(sed 's/[/.*^$]/\\&/g' <<< "$cron_identifier"*) print_info "Choose update frequency:" - echo " 1) Daily" - echo " 2) Weekly" - echo " 3) Monthly" - echo " 4) Never (Cancel)" - read -p "Enter your choice (1-4): " freq_choice + echo " 1*) Daily" + echo " 2*) Weekly" + echo " 3*) Monthly" + echo " 4*) Never (Cancel*)" + read -p "Enter your choice (1-4*): " freq_choice case $freq_choice in - 1) cron_schedule="@daily" ;; - 2) cron_schedule="@weekly" ;; - 3) cron_schedule="@monthly" ;; - 4) print_info "Automatic updates setup cancelled."; return 0 ;; - *) print_error "Invalid choice. Skipping auto-update setup."; return 1 ;; + 1*) cron_schedule="@daily" ;; + 2*) cron_schedule="@weekly" ;; + 3*) cron_schedule="@monthly" ;; + 4*) print_info "Automatic updates setup cancelled."; return 0 ;; + **) print_error "Invalid choice. Skipping auto-update setup."; return 1 ;; esac # Construct the cron command @@ -1029,19 +1029,19 @@ setup_cron_update() { # --- Improved Cron Job Handling --- print_info "Checking/Updating cron job for Pulse automatic updates..." # Get current crontab content or empty string if none exists - current_cron=$(crontab -l -u root 2>/dev/null || true) + current_cron=$(crontab -l -u root 2>/dev/null || true*) # Use sed to remove the identifier line and the line immediately following it. - # The pattern looks for the exact identifier comment at the beginning of a line (^). - # If found, it reads the Next line (N) and Deletes both (d). - filtered_cron=$(echo "$current_cron" | sed "/^${escaped_cron_identifier}$/{N;d;}") + # The pattern looks for the exact identifier comment at the beginning of a line (^*). + # If found, it reads the Next line (N*) and Deletes both (d*). + filtered_cron=$(echo "$current_cron" | sed "/^${escaped_cron_identifier}$/{N;d;}"*) # Prepare the new crontab content # If filtered_cron is empty after removal, avoid leading newline. Otherwise, add newline before appending. if [ -z "$filtered_cron" ]; then - new_cron_content=$(printf "%s\n%s" "$cron_identifier" "$cron_command") + new_cron_content=$(printf "%s\n%s" "$cron_identifier" "$cron_command"*) else - new_cron_content=$(printf "%s\n%s\n%s" "$filtered_cron" "$cron_identifier" "$cron_command") + new_cron_content=$(printf "%s\n%s\n%s" "$filtered_cron" "$cron_identifier" "$cron_command"*) fi # Load the new crontab content @@ -1062,13 +1062,13 @@ setup_cron_update() { return 0 } -prompt_for_cron_setup() { +prompt_for_cron_setup(*) { # Only prompt if not running in update mode if [ "$MODE_UPDATE" = true ]; then return 0 fi - local cron_identifier="# Pulse-Auto-Update ($SCRIPT_NAME)" + local cron_identifier="# Pulse-Auto-Update ($SCRIPT_NAME*)" local cron_exists=false # Check if cron job exists for root user if crontab -l -u root 2>/dev/null | grep -q "$cron_identifier"; then @@ -1080,21 +1080,21 @@ prompt_for_cron_setup() { if [ "$cron_exists" = true ]; then print_info "Automatic updates for Pulse appear to be currently ENABLED." echo "Choose an action:" - echo " 1) Change update schedule" - echo " 2) Disable automatic updates" - echo " 3) Keep current schedule (Do nothing)" - read -p "Enter your choice (1-3): " cron_manage_choice + echo " 1*) Change update schedule" + echo " 2*) Disable automatic updates" + echo " 3*) Keep current schedule (Do nothing*)" + read -p "Enter your choice (1-3*): " cron_manage_choice case $cron_manage_choice in - 1) setup_cron_update ;; # Call function to prompt for new schedule and update - 2) disable_cron_update ;; # Call function to remove the job - 3) print_info "Keeping current automatic update schedule.";; - *) print_warning "Invalid choice. No changes made to automatic updates.";; + 1*) setup_cron_update ;; # Call function to prompt for new schedule and update + 2*) disable_cron_update ;; # Call function to remove the job + 3*) print_info "Keeping current automatic update schedule.";; + **) print_warning "Invalid choice. No changes made to automatic updates.";; esac else print_info "Automatic updates for Pulse appear to be currently DISABLED." - read -p "Do you want to set up automatic updates for Pulse? (Y/n): " setup_cron_confirm - if [[ ! "$setup_cron_confirm" =~ ^[Nn]$ ]]; then # Proceed if not 'N' or 'n' (Default Yes) + read -p "Do you want to set up automatic updates for Pulse? (Y/n*): " setup_cron_confirm + if [[ ! "$setup_cron_confirm" =~ ^[Nn]$ ]]; then # Proceed if not 'N' or 'n' (Default Yes*) setup_cron_update else print_info "Skipping automatic update setup." @@ -1102,15 +1102,15 @@ prompt_for_cron_setup() { fi } -final_instructions() { +final_instructions(*) { # Try to get the IP address of the container local ip_address - ip_address=$(hostname -I | awk '{print $1}') # Get the first IP address + ip_address=$(hostname -I | awk '{print $1}'*) # Get the first IP address local port_value # Read the port from the .env file, fallback to default if not found/readable local env_path="$PULSE_DIR/.env" if [ -f "$env_path" ] && grep -q '^PORT=' "$env_path"; then - port_value=$(grep '^PORT=' "$env_path" | cut -d'=' -f2) + port_value=$(grep '^PORT=' "$env_path" | cut -d'=' -f2*) else port_value="7655" # Default port fi @@ -1126,7 +1126,7 @@ final_instructions() { print_warning "Could not automatically determine the LXC IP address." fi echo "" - print_info "The Pulse service ($SERVICE_NAME) is running and enabled on boot." + print_info "The Pulse service ($SERVICE_NAME*) is running and enabled on boot." print_info "To check the status: sudo systemctl status $SERVICE_NAME" print_info "To view logs: sudo journalctl -u $SERVICE_NAME -f" print_info "Configuration file: $PULSE_DIR/.env" @@ -1139,13 +1139,13 @@ check_root # Determine absolute path of the script early if command -v readlink &> /dev/null && readlink -f "$0" &> /dev/null; then - SCRIPT_ABS_PATH=$(readlink -f "$0") + SCRIPT_ABS_PATH=$(readlink -f "$0"*) else # Basic fallback if readlink -f is not available or fails if [[ "$0" == /* ]]; then SCRIPT_ABS_PATH="$0" else - SCRIPT_ABS_PATH="$(pwd)/$0" + SCRIPT_ABS_PATH="$(pwd*)/$0" fi # Verify the fallback path if [ ! -f "$SCRIPT_ABS_PATH" ]; then @@ -1159,21 +1159,21 @@ check_installation_status_and_determine_action # Sets the INSTALL_MODE variable # --- Execute Action Based on INSTALL_MODE --- case "$INSTALL_MODE" in - "remove") + "remove"*) print_info "Proceeding with removal..." perform_remove exit $? ;; - "cancel") + "cancel"*) print_info "Operation cancelled by user." exit 0 ;; - "error") + "error"*) # Error message already printed print_error "Exiting due to error." exit 1 ;; - "install" | "update") + "install" | "update"*) # Only install dependencies if installing or updating print_info "Proceeding with install/update. Installing prerequisites..." apt_update_upgrade || exit 1 @@ -1203,7 +1203,7 @@ case "$INSTALL_MODE" in exit 1 fi - install_npm_deps || exit 1 # Installs root and server (NOW INCLUDES DEV) + install_npm_deps || exit 1 # Installs root and server (NOW INCLUDES DEV*) # Build CSS after dependencies print_info "Building CSS assets..." @@ -1236,7 +1236,7 @@ case "$INSTALL_MODE" in fi fi ;; - *) + **) print_error "Internal script error: Unknown INSTALL_MODE '$INSTALL_MODE'" exit 1 ;;