3126944905
This reverts commit e5979a501e.
331 lines
9.0 KiB
Bash
Executable File
331 lines
9.0 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
#############################################################################
|
|
# Common Functions Library
|
|
# Shared utilities for all Server Management Toolkit modules
|
|
#############################################################################
|
|
|
|
#############################################################################
|
|
# Professional Color Scheme
|
|
# - Uses ONLY basic ANSI colors (works on ANY terminal)
|
|
# - High contrast for readability
|
|
# - No emojis (terminal-agnostic)
|
|
# - Industry standard: Red=error, Yellow=warning, Green=success, Blue=info
|
|
#
|
|
# To disable colors completely: export TOOLKIT_NO_COLOR=1
|
|
#############################################################################
|
|
|
|
# Detect if colors should be disabled or adjusted
|
|
if [ "${TOOLKIT_NO_COLOR:-0}" = "1" ] || [ ! -t 1 ]; then
|
|
# No color mode (monochrome terminals, piped output, etc.)
|
|
export RED=''
|
|
export YELLOW=''
|
|
export GREEN=''
|
|
export BLUE=''
|
|
export CYAN=''
|
|
export WHITE=''
|
|
export BOLD=''
|
|
export DIM=''
|
|
export NC=''
|
|
elif [ "${TOOLKIT_HIGH_CONTRAST:-0}" = "1" ]; then
|
|
# High contrast mode - BOLD colors for light backgrounds
|
|
# These work well on BOTH light and dark backgrounds
|
|
export RED='\033[1;31m' # Errors, critical alerts (BOLD RED)
|
|
export YELLOW='\033[1;33m' # Warnings, caution (BOLD YELLOW)
|
|
export GREEN='\033[1;32m' # Success, completed (BOLD GREEN)
|
|
export BLUE='\033[1;34m' # Info, neutral status (BOLD BLUE)
|
|
export CYAN='\033[1;36m' # Headers, sections (BOLD CYAN)
|
|
export WHITE='\033[1;37m' # Emphasis, highlights (BOLD WHITE)
|
|
export BOLD='\033[1m' # Important text
|
|
export DIM='\033[2m' # Secondary/less important
|
|
export NC='\033[0m' # Reset/No Color
|
|
else
|
|
# Normal color mode (default - optimized for dark backgrounds)
|
|
export RED='\033[0;31m' # Errors, critical alerts
|
|
export YELLOW='\033[0;33m' # Warnings, caution
|
|
export GREEN='\033[0;32m' # Success, completed
|
|
export BLUE='\033[0;34m' # Info, neutral status
|
|
export CYAN='\033[0;36m' # Headers, sections
|
|
export WHITE='\033[1;37m' # Emphasis, highlights
|
|
export BOLD='\033[1m' # Important text
|
|
export DIM='\033[2m' # Secondary/less important
|
|
export NC='\033[0m' # Reset/No Color
|
|
fi
|
|
|
|
# Print functions - professional, no emojis
|
|
print_banner() {
|
|
local title="$1"
|
|
echo ""
|
|
echo "==============================================================================="
|
|
echo " $title"
|
|
echo "==============================================================================="
|
|
echo ""
|
|
}
|
|
|
|
print_section() {
|
|
local title="$1"
|
|
echo ""
|
|
echo -e "${BOLD}$title${NC}"
|
|
echo "───────────────────────────────────────────────────────────────────────────────"
|
|
}
|
|
|
|
print_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
print_success() {
|
|
echo -e "${GREEN}[OK]${NC} $1"
|
|
}
|
|
|
|
print_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
print_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
print_critical() {
|
|
echo -e "${RED}${BOLD}[CRITICAL]${NC} $1"
|
|
}
|
|
|
|
print_alert() {
|
|
echo -e "${RED}[ALERT]${NC} $1"
|
|
}
|
|
|
|
print_header() {
|
|
echo -e "${CYAN}${BOLD}$1${NC}"
|
|
}
|
|
|
|
#############################################################################
|
|
# Color Echo Helper - ALWAYS use this when printing colored text
|
|
#
|
|
# PROBLEM: Using 'echo' without -e flag doesn't interpret escape sequences
|
|
# BAD: echo " ${BOLD}1${NC} - Menu option" → Shows: \033[1m1\033[0m
|
|
# GOOD: cecho " ${BOLD}1${NC} - Menu option" → Shows: 1 (bold)
|
|
#
|
|
# USAGE:
|
|
# cecho "Normal text with ${RED}colored${NC} parts"
|
|
# cecho "${BOLD}Bold text${NC}"
|
|
#
|
|
# WHY: Prevents common bug where color codes show as literal text
|
|
#############################################################################
|
|
cecho() {
|
|
echo -e "$@"
|
|
}
|
|
|
|
# Wait for user input
|
|
press_enter() {
|
|
echo ""
|
|
read -p "Press Enter to continue..." _
|
|
}
|
|
|
|
# Show banner (wrapper for print_banner for compatibility)
|
|
show_banner() {
|
|
if [ -n "$1" ]; then
|
|
print_banner "$1"
|
|
else
|
|
print_banner "Server Toolkit"
|
|
fi
|
|
}
|
|
|
|
# Progress indicator - terminal safe (no fancy characters)
|
|
show_progress() {
|
|
local current=$1
|
|
local total=$2
|
|
local message="$3"
|
|
|
|
# Avoid division by zero
|
|
if [ "$total" -eq 0 ]; then
|
|
printf "\r[INFO] Progress: [####################] 100%% - %s" "$message"
|
|
return
|
|
fi
|
|
|
|
local percent=$((current * 100 / total))
|
|
local bars=$((percent / 5)) # 20 chars wide
|
|
|
|
printf "\r[INFO] Progress: ["
|
|
printf "%${bars}s" | tr ' ' '#'
|
|
printf "%$((20-bars))s" | tr ' ' '-'
|
|
printf "] %3d%% - %s" "$percent" "$message"
|
|
}
|
|
|
|
# Finish progress line
|
|
finish_progress() {
|
|
echo ""
|
|
}
|
|
|
|
# Display terminal info (for debugging)
|
|
show_terminal_info() {
|
|
echo ""
|
|
echo "Terminal Information:"
|
|
echo " TERM: ${TERM:-not set}"
|
|
echo " Colors: $([ -t 1 ] && echo "enabled" || echo "disabled (not a tty)")"
|
|
echo " TOOLKIT_NO_COLOR: ${TOOLKIT_NO_COLOR:-0}"
|
|
echo " Columns: ${COLUMNS:-$(tput cols 2>/dev/null || echo "unknown")}"
|
|
echo ""
|
|
}
|
|
|
|
# Create temporary session directory
|
|
create_temp_session() {
|
|
export SESSION_ID=$$
|
|
export TEMP_SESSION_DIR=$(mktemp -d -t server-toolkit.XXXXXX)
|
|
|
|
# Cleanup on exit
|
|
trap '[ -n "$TEMP_SESSION_DIR" ] && rm -rf "$TEMP_SESSION_DIR" 2>/dev/null' EXIT INT TERM
|
|
}
|
|
|
|
# Ask user for confirmation
|
|
confirm() {
|
|
local prompt="$1"
|
|
local default="${2:-N}"
|
|
|
|
if [[ "$default" == "Y" ]]; then
|
|
read -p "$prompt [Y/n]: " -n 1 -r
|
|
else
|
|
read -p "$prompt [y/N]: " -n 1 -r
|
|
fi
|
|
echo
|
|
|
|
if [[ "$default" == "Y" ]]; then
|
|
[[ ! $REPLY =~ ^[Nn]$ ]]
|
|
else
|
|
[[ $REPLY =~ ^[Yy]$ ]]
|
|
fi
|
|
}
|
|
|
|
# Format bytes to human readable
|
|
format_bytes() {
|
|
local bytes=$1
|
|
if [ -z "$bytes" ] || [ "$bytes" -eq 0 ]; then
|
|
echo "0 B"
|
|
return
|
|
fi
|
|
|
|
local units=("B" "KB" "MB" "GB" "TB")
|
|
local unit=0
|
|
local size=$bytes
|
|
|
|
while [ "${size:-0}" -gt 1024 ] && [ "${unit:-0}" -lt 4 ]; do
|
|
size=$((size / 1024))
|
|
unit=$((unit + 1))
|
|
done
|
|
|
|
echo "${size} ${units[$unit]}"
|
|
}
|
|
|
|
# Format seconds to human readable time
|
|
format_duration() {
|
|
[ -z "$1" ] && return 1
|
|
local seconds=$1
|
|
local days=$((seconds / 86400))
|
|
local hours=$(((seconds % 86400) / 3600))
|
|
local minutes=$(((seconds % 3600) / 60))
|
|
local secs=$((seconds % 60))
|
|
|
|
if [ "${days:-0}" -gt 0 ]; then
|
|
echo "${days}d ${hours}h ${minutes}m"
|
|
elif [ "${hours:-0}" -gt 0 ]; then
|
|
echo "${hours}h ${minutes}m ${secs}s"
|
|
elif [ "${minutes:-0}" -gt 0 ]; then
|
|
echo "${minutes}m ${secs}s"
|
|
else
|
|
echo "${secs}s"
|
|
fi
|
|
}
|
|
|
|
# Check if command exists
|
|
command_exists() {
|
|
[ -z "$1" ] && return 1
|
|
command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
# Check if running as root
|
|
require_root() {
|
|
if [ "$EUID" -ne 0 ]; then
|
|
print_error "This script must be run as root"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Safe file append (creates backup)
|
|
safe_append() {
|
|
local file="$1"
|
|
local content="$2"
|
|
|
|
if [ -f "$file" ]; then
|
|
cp "$file" "${file}.bak.$(date +%s)"
|
|
fi
|
|
|
|
echo "$content" >> "$file"
|
|
}
|
|
|
|
# Log message to file
|
|
log_message() {
|
|
local level="$1"
|
|
local message="$2"
|
|
local log_file="${3:-/var/log/server-toolkit.log}"
|
|
|
|
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
echo "[$timestamp] [$level] $message" >> "$log_file"
|
|
}
|
|
|
|
# Get script directory (works even when sourced)
|
|
get_script_dir() {
|
|
local source="${BASH_SOURCE[0]}"
|
|
while [ -h "$source" ]; do
|
|
local dir="$(cd -P "$(dirname "$source")" && pwd)"
|
|
source="$(readlink "$source")"
|
|
[[ $source != /* ]] && source="$dir/$source"
|
|
done
|
|
echo "$(cd -P "$(dirname "$source")" && pwd)"
|
|
}
|
|
|
|
# Detect toolkit base directory
|
|
get_toolkit_dir() {
|
|
local script_dir=$(get_script_dir)
|
|
echo "$(cd "$script_dir/.." && pwd)"
|
|
}
|
|
|
|
# Export toolkit directories
|
|
export TOOLKIT_BASE_DIR=$(get_toolkit_dir)
|
|
export TOOLKIT_LIB_DIR="${TOOLKIT_BASE_DIR}/lib"
|
|
export TOOLKIT_MODULES_DIR="${TOOLKIT_BASE_DIR}/modules"
|
|
export TOOLKIT_CONFIG_DIR="${TOOLKIT_BASE_DIR}/config"
|
|
|
|
# Load configuration if exists
|
|
load_config() {
|
|
local config_file="${TOOLKIT_CONFIG_DIR}/settings.conf"
|
|
if [ -f "$config_file" ]; then
|
|
source "$config_file"
|
|
fi
|
|
}
|
|
|
|
# Export all functions for use in subshells and sourced scripts
|
|
export -f print_banner
|
|
export -f print_section
|
|
export -f print_info
|
|
export -f print_success
|
|
export -f print_warning
|
|
export -f print_error
|
|
export -f print_critical
|
|
export -f print_alert
|
|
export -f print_header
|
|
export -f cecho
|
|
export -f press_enter
|
|
export -f show_banner
|
|
export -f show_progress
|
|
export -f finish_progress
|
|
export -f show_terminal_info
|
|
export -f create_temp_session
|
|
export -f confirm
|
|
export -f format_bytes
|
|
export -f format_duration
|
|
export -f command_exists
|
|
export -f require_root
|
|
export -f safe_append
|
|
export -f log_message
|
|
export -f get_script_dir
|
|
export -f get_toolkit_dir
|
|
export -f load_config
|