#!/bin/bash # Надграден скрипт за цялостен мониторинг на Proxmox # Включва допълнителни проверки и подобрени отчети # Автор: Федя Серафиев # Версия: 2.0 # Дата на последна промяна: 2023-11-15 # Конфигурация SCRIPT_DIR="/opt/proxmox-monitor" LOG_FILE="$SCRIPT_DIR/monitor.log" STATUS_FILE="$SCRIPT_DIR/last_status.json" CONFIG_FILE="$SCRIPT_DIR/config.conf" BACKUP_DIR="$SCRIPT_DIR/backups" MAX_LOG_FILES=30 MAX_BACKUP_FILES=10 # Стандартна конфигурация DEFAULT_TELEGRAM_BOT_TOKEN="" DEFAULT_TELEGRAM_CHAT_ID="" DEFAULT_CHECK_INTERVAL=60 DEFAULT_CPU_THRESHOLD=80 DEFAULT_MEMORY_THRESHOLD=85 DEFAULT_DISK_THRESHOLD=90 DEFAULT_LOAD_THRESHOLD=5.0 DEFAULT_NETWORK_THRESHOLD=80 DEFAULT_TEMP_THRESHOLD=70 DEFAULT_BACKUP_ENABLED=true DEFAULT_BACKUP_INTERVAL=86400 # 1 ден в секунди # Цветове за изход RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' MAGENTA='\033[0;35m' CYAN='\033[0;36m' NC='\033[0m' # Без цвят # Инициализация на скрипта init_script() { echo -e "${BLUE}Инициализиране на Proxmox Monitor...${NC}" # Създаване на директории mkdir -p "$SCRIPT_DIR" "$BACKUP_DIR" # Проверка за root потребител if [[ $EUID -ne 0 ]]; then echo -e "${RED}Грешка: Скриптът трябва да се изпълнява с root права${NC}" return 1 fi # Създаване на конфигурационен файл, ако не съществува if [[ ! -f "$CONFIG_FILE" ]]; then echo -e "${YELLOW}Създаване на нов конфигурационен файл...${NC}" cat > "$CONFIG_FILE" << EOF # Конфигурация на Proxmox Monitor TELEGRAM_BOT_TOKEN="$DEFAULT_TELEGRAM_BOT_TOKEN" TELEGRAM_CHAT_ID="$DEFAULT_TELEGRAM_CHAT_ID" CHECK_INTERVAL=$DEFAULT_CHECK_INTERVAL CPU_THRESHOLD=$DEFAULT_CPU_THRESHOLD MEMORY_THRESHOLD=$DEFAULT_MEMORY_THRESHOLD DISK_THRESHOLD=$DEFAULT_DISK_THRESHOLD LOAD_THRESHOLD=$DEFAULT_LOAD_THRESHOLD NETWORK_THRESHOLD=$DEFAULT_NETWORK_THRESHOLD TEMP_THRESHOLD=$DEFAULT_TEMP_THRESHOLD BACKUP_ENABLED=$DEFAULT_BACKUP_ENABLED BACKUP_INTERVAL=$DEFAULT_BACKUP_INTERVAL EOF echo -e "${YELLOW}Създаден е конфигурационен файл в $CONFIG_FILE${NC}" echo -e "${YELLOW}Моля, редактирайте конфигурационния файл с вашите данни${NC}" return 1 fi # Зареждане на конфигурацията source "$CONFIG_FILE" # Валидиране на конфигурацията if [[ -z "$TELEGRAM_BOT_TOKEN" || -z "$TELEGRAM_CHAT_ID" ]]; then echo -e "${RED}Грешка: Telegram данни не са конфигурирани${NC}" return 1 fi # Проверка за необходими пакети local required_packages=("curl" "bc" "jq" "lm-sensors") local missing_packages=() for pkg in "${required_packages[@]}"; do if ! dpkg -l | grep -q "^ii $pkg "; then missing_packages+=("$pkg") fi done if [[ ${#missing_packages[@]} -gt 0 ]]; then echo -e "${YELLOW}Инсталиране на липсващи пакети: ${missing_packages[*]}${NC}" apt-get update apt-get install -y "${missing_packages[@]}" fi # Ротация на логове manage_logs return 0 } # Управление на логове и архиви manage_logs() { # Ротация на логове if [[ -f "$LOG_FILE" ]]; then local log_size=$(du -k "$LOG_FILE" | cut -f1) if [[ $log_size -gt 1024 ]]; then # 1MB echo -e "${YELLOW}Ротация на логове...${NC}" gzip -c "$LOG_FILE" > "$LOG_FILE.$(date +%Y%m%d%H%M%S).gz" > "$LOG_FILE" # Изтриване на стари логове local old_logs=$(ls -t "$LOG_FILE".*.gz 2>/dev/null | tail -n +$((MAX_LOG_FILES+1))) for old_log in $old_logs; do rm -f "$old_log" done fi fi # Ротация на архиви if [[ "$BACKUP_ENABLED" == true ]]; then local old_backups=$(ls -t "$BACKUP_DIR"/status_*.json.gz 2>/dev/null | tail -n +$((MAX_BACKUP_FILES+1))) for old_backup in $old_backups; do rm -f "$old_backup" done fi } # Функция за логване log_message() { local level="$1" local message="$2" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo "$timestamp [$level] $message" >> "$LOG_FILE" # Допълнително извеждане за грешки и предупреждения case "$level" in "ERROR") echo -e "${RED}$timestamp [$level] $message${NC}" >&2 ;; "WARNING") echo -e "${YELLOW}$timestamp [$level] $message${NC}" >&2 ;; "INFO") echo -e "${BLUE}$timestamp [$level] $message${NC}" >&1 ;; *) echo "$timestamp [$level] $message" >&1 ;; esac } # Изпращане на Telegram известие send_telegram_notification() { local message="$1" local parse_mode="${2:-HTML}" # Ограничаване на дължината на съобщението (Telegram има лимит ~4096 символа) if [[ ${#message} -gt 4000 ]]; then message="${message:0:4000}... [съкратено]" fi local response=$(curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \ -d "chat_id=$TELEGRAM_CHAT_ID" \ -d "text=$message" \ -d "parse_mode=$parse_mode" \ -d "disable_web_page_preview=true" 2>&1) local result=$? if [[ $result -eq 0 ]]; then log_message "INFO" "Telegram известието е изпратено успешно" else log_message "ERROR" "Грешка при изпращане на Telegram известие: $response" fi return $result } # Вземане на системна информация get_system_info() { local hostname=$(hostname -f) local uptime=$(uptime -p | sed 's/up //') local kernel=$(uname -r) local pve_version=$(pveversion | grep -oP "pve-manager\/\K[0-9.]+") local cpu_model=$(grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2 | sed 's/^[ \t]*//') local cpu_cores=$(grep -c "^processor" /proc/cpuinfo) echo "hostname:$hostname" echo "uptime:$uptime" echo "kernel:$kernel" echo "pve_version:$pve_version" echo "cpu_model:$cpu_model" echo "cpu_cores:$cpu_cores" } # Вземане на CPU използване get_cpu_usage() { local cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}') echo "${cpu_usage%.*}" } # Вземане на памет get_memory_usage() { local mem_info=$(free -m | grep "Mem:") local total=$(echo $mem_info | awk '{print $2}') local used=$(echo $mem_info | awk '{print $3}') local buff_cache=$(echo $mem_info | awk '{print $6}') local available=$(free -m | grep "Mem:" | awk '{print $7}') local percentage=$(( (total - available) * 100 / total )) echo "$percentage" } # Вземане на дисково използване get_disk_usage() { local disk_usage=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//') echo "$disk_usage" } # Вземане на средно натоварване get_load_average() { local load=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//') echo "$load" } # Вземане на мрежова активност get_network_usage() { local interface=$(ip route | grep default | awk '{print $5}' | head -1) if [[ -z "$interface" ]]; then echo "0:0" return fi local rx1=$(cat /sys/class/net/$interface/statistics/rx_bytes) local tx1=$(cat /sys/class/net/$interface/statistics/tx_bytes) sleep 1 local rx2=$(cat /sys/class/net/$interface/statistics/rx_bytes) local tx2=$(cat /sys/class/net/$interface/statistics/tx_bytes) local rx=$(( (rx2 - rx1) / 1024 )) local tx=$(( (tx2 - tx1) / 1024 )) echo "$rx:$tx" } # Вземане на температура get_temperature() { local temp=$(sensors | grep -E "Package|Tdie" | awk '{print $4}' | sed 's/+//;s/°C//') echo "${temp%.*}" } # Проверка на ZFS пулове check_zfs_pools() { if ! command -v zpool &> /dev/null; then echo "NOT_AVAILABLE" return fi local pools=$(zpool list -H -o name,health 2>/dev/null) if [[ -z "$pools" ]]; then echo "NO_POOLS" return fi local issues=() while IFS= read -r line; do local pool=$(echo "$line" | awk '{print $1}') local health=$(echo "$line" | awk '{print $2}') if [[ "$health" != "ONLINE" ]]; then issues+=("$pool:$health") fi done <<< "$pools" if [[ ${#issues[@]} -gt 0 ]]; then echo "ISSUES:${issues[*]}" else echo "OK" fi } # Проверка на Proxmox услуги check_proxmox_services() { local services=("pveproxy" "pvedaemon" "pvestatd" "pve-cluster" "corosync" "pve-ha-crm" "pve-ha-lrm" "pve-firewall") local failed_services=() for service in "${services[@]}"; do if ! systemctl is-active --quiet "$service"; then failed_services+=("$service") fi done if [[ ${#failed_services[@]} -gt 0 ]]; then echo "FAILED:${failed_services[*]}" else echo "OK" fi } # Вземане на статус на контейнери/ВМ get_container_status() { local containers=() local vms=() # Вземане на LXC контейнери while IFS= read -r line; do if [[ -n "$line" ]]; then local vmid=$(echo "$line" | awk '{print $1}') local status=$(echo "$line" | awk '{print $2}') local name=$(echo "$line" | awk '{print $3}') local ip=$(pct config "$vmid" | grep "ip=" | cut -d'=' -f2 | cut -d'/' -f1 | head -1) containers+=("$vmid:$status:$name:LXC:$ip") fi done < <(pct list | tail -n +2) # Вземане на ВМ while IFS= read -r line; do if [[ -n "$line" ]]; then local vmid=$(echo "$line" | awk '{print $1}') local status=$(echo "$line" | awk '{print $3}') local name=$(echo "$line" | awk '{print $2}') local ip=$(qm guest exec "$vmid" -- ip route get 1 | awk '{print $7}' | head -1) vms+=("$vmid:$status:$name:VM:$ip") fi done < <(qm list | tail -n +2) # Комбиниране и връщане for item in "${containers[@]}" "${vms[@]}"; do echo "$item" done } # Проверка на използване на хранилище check_storage_usage() { local storage_issues=() while IFS= read -r line; do if [[ -n "$line" ]]; then local storage=$(echo "$line" | awk '{print $1}') local usage=$(echo "$line" | awk '{print $6}' | sed 's/%//') local total=$(echo "$line" | awk '{print $2}') local avail=$(echo "$line" | awk '{print $4}') if [[ "$usage" -gt "$DISK_THRESHOLD" ]]; then storage_issues+=("$storage:$usage% (Налично: $avail от $total)") fi fi done < <(pvesm status | tail -n +2) if [[ ${#storage_issues[@]} -gt 0 ]]; then echo "HIGH_USAGE:${storage_issues[*]}" else echo "OK" fi } # Проверка на състоянието на батерията (за UPS) check_ups_status() { if ! command -v upsc &> /dev/null; then echo "NOT_AVAILABLE" return fi local ups_list=$(upsc -l 2>/dev/null) if [[ -z "$ups_list" ]]; then echo "NO_UPS" return fi local ups_name=$(echo "$ups_list" | head -1) local status=$(upsc "$ups_name" 2>/dev/null | grep -E "battery.charge:|ups.status:") if [[ -z "$status" ]]; then echo "ERROR" return fi local battery_charge=$(echo "$status" | grep "battery.charge:" | cut -d' ' -f2) local ups_status=$(echo "$status" | grep "ups.status:" | cut -d' ' -f2) if [[ "$ups_status" != "OL" || "$battery_charge" -lt 90 ]]; then echo "ISSUE:$ups_status:$battery_charge%" else echo "OK:$ups_status:$battery_charge%" fi } # Проверка на състоянието на RAID check_raid_status() { if [[ -f "/proc/mdstat" ]]; then local mdstat=$(grep -A1 "md" /proc/mdstat | tail -1) if [[ "$mdstat" == *"UU"* ]]; then echo "OK" else echo "DEGRADED:$mdstat" fi elif command -v megacli &> /dev/null; then local raid_status=$(megacli -LDInfo -Lall -aAll | grep "State" | awk '{print $3}') if [[ "$raid_status" == "Optimal" ]]; then echo "OK" else echo "DEGRADED:$raid_status" fi else echo "NOT_AVAILABLE" fi } # Генериране на отчет за статус generate_status_report() { local report_type="$1" # ALERT, RECOVERY, SUMMARY, или DETAILED local issues="$2" local system_info=$(get_system_info) local hostname=$(echo "$system_info" | grep "hostname:" | cut -d: -f2) local uptime=$(echo "$system_info" | grep "uptime:" | cut -d: -f2-) local pve_version=$(echo "$system_info" | grep "pve_version:" | cut -d: -f2-) local cpu_model=$(echo "$system_info" | grep "cpu_model:" | cut -d: -f2-) local cpu_cores=$(echo "$system_info" | grep "cpu_cores:" | cut -d: -f2-) local cpu_usage=$(get_cpu_usage) local memory_usage=$(get_memory_usage) local disk_usage=$(get_disk_usage) local load_avg=$(get_load_average) local temperature=$(get_temperature) local network_usage=$(get_network_usage) local rx=$(echo "$network_usage" | cut -d: -f1) local tx=$(echo "$network_usage" | cut -d: -f2) local zfs_status=$(check_zfs_pools) local raid_status=$(check_raid_status) local ups_status=$(check_ups_status) local current_time=$(date '+%Y-%m-%d %H:%M:%S') case "$report_type" in "ALERT") local icon="🚨" local status="АВАРИЯ" ;; "RECOVERY") local icon="✅" local status="ВЪЗСТАНОВЯВАНЕ" ;; "SUMMARY") local icon="📊" local status="ОБЗОР" ;; "DETAILED") local icon="🔍" local status="ПОДРОБЕН" ;; *) local icon="ℹ️" local status="ИНФО" ;; esac local message="$icon Proxmox Monitor - $status $icon 🖥️ Системна информация: • Хост: $hostname • Време: $current_time • Uptime: $uptime • Версия: $pve_version • CPU: $cpu_model ($cpu_cores ядра) 📊 Системни ресурси: • CPU: $cpu_usage% (Температура: $temperature°C) • Памет: $memory_usage% • Диск: $disk_usage% • Натоварване: $load_avg • Мрежа: ⬇️ $rx KB/s ⬆️ $tx KB/s" # Добавяне на RAID статус case "$raid_status" in "OK") message="$message • RAID: Нормално" ;; "DEGRADED"*) local degraded_info=$(echo "$raid_status" | cut -d: -f2-) message="$message • RAID: Деградиран ($degraded_info)" ;; *) message="$message" ;; esac # Добавяне на ZFS статус case "$zfs_status" in "OK") message="$message • ZFS: Нормално" ;; "ISSUES"*) local zfs_issues=$(echo "$zfs_status" | cut -d: -f2- | tr '|' ', ') message="$message • ZFS: Проблеми ($zfs_issues)" ;; *) message="$message" ;; esac # Добавяне на UPS статус case "$ups_status" in "OK"*) local ups_info=$(echo "$ups_status" | cut -d: -f2-) message="$message • UPS: Нормално ($ups_info)" ;; "ISSUE"*) local ups_info=$(echo "$ups_status" | cut -d: -f2-) message="$message • UPS: Проблем ($ups_info)" ;; *) message="$message" ;; esac # Добавяне на статус на контейнери local container_status=$(get_container_status) local running_count=0 local stopped_count=0 local problem_containers=() while IFS= read -r line; do if [[ -n "$line" ]]; then local vmid=$(echo "$line" | cut -d: -f1) local status=$(echo "$line" | cut -d: -f2) local name=$(echo "$line" | cut -d: -f3) local type=$(echo "$line" | cut -d: -f4) local ip=$(echo "$line" | cut -d: -f5) if [[ "$status" == "running" ]]; then ((running_count++)) else ((stopped_count++)) problem_containers+=("$type $vmid ($name) [$ip]: $status") fi fi done <<< "$container_status" message="$message 🔧 Контейнери/ВМ: • Работят: $running_count • Спряни: $stopped_count" # Добавяне на проблеми, ако има if [[ -n "$issues" ]]; then message="$message ⚠️ Открити проблеми: $issues" fi # Добавяне на детайли за спрени контейнери if [[ ${#problem_containers[@]} -gt 0 ]]; then message="$message 🔴 Спрени контейнери/ВМ:" for container in "${problem_containers[@]}"; do message="$message • $container" done fi # Добавяне на подробна информация за хранилища if [[ "$report_type" == "DETAILED" ]]; then message="$message 💾 Хранилища:" while IFS= read -r line; do if [[ -n "$line" ]]; then local storage=$(echo "$line" | awk '{print $1}') local type=$(echo "$line" | awk '{print $2}') local status=$(echo "$line" | awk '{print $3}') local total=$(echo "$line" | awk '{print $4}') local used=$(echo "$line" | awk '{print $5}') local avail=$(echo "$line" | awk '{print $6}') message="$message • $storage ($type): $status | Използвано: $used от $total | Свободно: $avail" fi done < <(pvesm status | tail -n +2) fi echo "$message" } # Проверка на здравето на системата check_system_health() { local issues=() local current_status=() # Проверка на CPU local cpu_usage=$(get_cpu_usage) if [[ "$cpu_usage" -gt "$CPU_THRESHOLD" ]]; then issues+=("Високо CPU използване: ${cpu_usage}% (Лимит: ${CPU_THRESHOLD}%)") fi current_status+=("cpu:$cpu_usage") # Проверка на памет local memory_usage=$(get_memory_usage) if [[ "$memory_usage" -gt "$MEMORY_THRESHOLD" ]]; then issues+=("Високо използване на памет: ${memory_usage}% (Лимит: ${MEMORY_THRESHOLD}%)") fi current_status+=("memory:$memory_usage") # Проверка на диск local disk_usage=$(get_disk_usage) if [[ "$disk_usage" -gt "$DISK_THRESHOLD" ]]; then issues+=("Високо дисково използване: ${disk_usage}% (Лимит: ${DISK_THRESHOLD}%)") fi current_status+=("disk:$disk_usage") # Проверка на натоварване local load_avg=$(get_load_average) if (( $(echo "$load_avg > $LOAD_THRESHOLD" | bc -l) )); then issues+=("Високо средно натоварване: $load_avg (Лимит: $LOAD_THRESHOLD)") fi current_status+=("load:$load_avg") # Проверка на температура local temperature=$(get_temperature) if [[ "$temperature" -gt "$TEMP_THRESHOLD" ]]; then issues+=("Висока температура на CPU: ${temperature}°C (Лимит: ${TEMP_THRESHOLD}°C)") fi current_status+=("temp:$temperature") # Проверка на мрежа local network_usage=$(get_network_usage) local rx=$(echo "$network_usage" | cut -d: -f1) local tx=$(echo "$network_usage" | cut -d: -f2) if [[ "$rx" -gt "$NETWORK_THRESHOLD" ]]; then issues+=("Високо входящо мрежово натоварване: ${rx}KB/s (Лимит: ${NETWORK_THRESHOLD}KB/s)") fi if [[ "$tx" -gt "$NETWORK_THRESHOLD" ]]; then issues+=("Високо изходящо мрежово натоварване: ${tx}KB/s (Лимит: ${NETWORK_THRESHOLD}KB/s)") fi current_status+=("network_rx:$rx") current_status+=("network_tx:$tx") # Проверка на Proxmox услуги local service_status=$(check_proxmox_services) if [[ "$service_status" != "OK" ]]; then local failed_services=$(echo "$service_status" | cut -d: -f2 | tr '|' ', ') issues+=("Неуспешни услуги: $failed_services") fi current_status+=("services:$service_status") # Проверка на хранилище local storage_status=$(check_storage_usage) if [[ "$storage_status" != "OK" ]]; then local storage_issues=$(echo "$storage_status" | cut -d: -f2 | tr '|' ', ') issues+=("Проблеми с хранилище: $storage_issues") fi current_status+=("storage:$storage_status") # Проверка на ZFS local zfs_status=$(check_zfs_pools) if [[ "$zfs_status" == "ISSUES"* ]]; then local zfs_issues=$(echo "$zfs_status" | cut -d: -f2 | tr '|' ', ') issues+=("Проблеми с ZFS: $zfs_issues") fi current_status+=("zfs:$zfs_status") # Проверка на RAID local raid_status=$(check_raid_status) if [[ "$raid_status" == "DEGRADED"* ]]; then local raid_issues=$(echo "$raid_status" | cut -d: -f2) issues+=("Проблеми с RAID: $raid_issues") fi current_status+=("raid:$raid_status") # Проверка на UPS local ups_status=$(check_ups_status) if [[ "$ups_status" == "ISSUE"* ]]; then local ups_issues=$(echo "$ups_status" | cut -d: -f2-) issues+=("Проблеми с UPS: $ups_issues") fi current_status+=("ups:$ups_status") # Проверка на контейнери local container_status=$(get_container_status) local stopped_containers=() while IFS= read -r line; do if [[ -n "$line" ]]; then local vmid=$(echo "$line" | cut -d: -f1) local status=$(echo "$line" | cut -d: -f2) local name=$(echo "$line" | cut -d: -f3) local type=$(echo "$line" | cut -d: -f4) if [[ "$status" != "running" ]]; then stopped_containers+=("$type $vmid ($name)") fi fi done <<< "$container_status" if [[ ${#stopped_containers[@]} -gt 0 ]]; then issues+=("Спряни контейнери: ${stopped_containers[*]}") fi current_status+=("containers:${#stopped_containers[@]}_stopped") # Запазване на текущия статус printf '%s\n' "${current_status[@]}" > "$STATUS_FILE" # Архивиране на статуса if [[ "$BACKUP_ENABLED" == true ]]; then local last_backup=$(stat -c %Y "$STATUS_FILE" 2>/dev/null || echo 0) local current_time=$(date +%s) if (( current_time - last_backup > BACKUP_INTERVAL )); then gzip -c "$STATUS_FILE" > "$BACKUP_DIR/status_$(date +%Y%m%d%H%M%S).json.gz" fi fi # Връщане на проблеми if [[ ${#issues[@]} -gt 0 ]]; then printf '%s\n' "${issues[@]}" fi } # Главна функция за мониторинг monitor_system() { if ! init_script; then exit 1 fi local issues=$(check_system_health) local previous_issues="" # Зареждане на предишен статус if [[ -f "$STATUS_FILE.prev" ]]; then previous_issues=$(cat "$STATUS_FILE.prev" 2>/dev/null || echo "") fi # Текущи проблеми като стринг local current_issues_str="" if [[ -n "$issues" ]]; then current_issues_str=$(echo "$issues" | tr '\n' '|') fi # Проверка дали статуса е променен if [[ "$current_issues_str" != "$previous_issues" ]]; then if [[ -n "$issues" ]]; then # Открити са нови проблеми local formatted_issues="" while IFS= read -r issue; do formatted_issues="$formatted_issues• $issue\n" done <<< "$issues" local report=$(generate_status_report "ALERT" "$formatted_issues") send_telegram_notification "$report" log_message "ALERT" "Открити проблеми: $issues" elif [[ -n "$previous_issues" ]]; then # Проблемите са разрешени local report=$(generate_status_report "RECOVERY" "") send_telegram_notification "$report" log_message "INFO" "Проблемите са разрешени" fi # Запазване на текущия статус като предишен echo "$current_issues_str" > "$STATUS_FILE.prev" fi } # Функция за инсталация install_monitor() { echo -e "${BLUE}Инсталиране на Proxmox Monitor...${NC}" # Проверка за root потребител if [[ $EUID -ne 0 ]]; then echo -e "${RED}Грешка: Скриптът трябва да се изпълнява с root права${NC}" exit 1 fi # Инсталиране на зависимости log_message "INFO" "Инсталиране на зависимости..." apt-get update apt-get install -y curl bc jq lm-sensors megacli snmp nut # Инициализиране на скрипта if ! init_script; then echo -e "${RED}Инсталацията неуспешна. Моля, конфигурирайте скрипта.${NC}" exit 1 fi # Създаване на systemd услуга log_message "INFO" "Създаване на systemd услуга..." cat > /etc/systemd/system/proxmox-monitor.service << EOF [Unit] Description=Proxmox Comprehensive Monitor After=network.target [Service] Type=simple User=root ExecStart=$0 daemon Restart=always RestartSec=10 Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" [Install] WantedBy=multi-user.target EOF # Създаване на systemd таймер log_message "INFO" "Създаване на systemd таймер..." cat > /etc/systemd/system/proxmox-monitor.timer << EOF [Unit] Description=Proxmox Monitor Timer Requires=proxmox-monitor.service [Timer] OnBootSec=60 OnUnitActiveSec=${CHECK_INTERVAL}s AccuracySec=1s [Install] WantedBy=timers.target EOF # Активиране и стартиране на услугите log_message "INFO" "Активиране на услугите..." systemctl daemon-reload systemctl enable proxmox-monitor.timer systemctl start proxmox-monitor.timer # Проверка на състоянието sleep 2 local timer_status=$(systemctl is-active proxmox-monitor.timer) local service_status=$(systemctl is-active proxmox-monitor.service) if [[ "$timer_status" == "active" && "$service_status" == "active" ]]; then echo -e "${GREEN}✅ Proxmox Monitor е инсталиран и стартиран успешно!${NC}" echo -e "${YELLOW}Конфигурационен файл: $CONFIG_FILE${NC}" echo -e "${YELLOW}Лог файл: $LOG_FILE${NC}" echo -e "${YELLOW}Статус: systemctl status proxmox-monitor.timer${NC}" log_message "INFO" "Успешна инсталация на Proxmox Monitor" else echo -e "${RED}❌ Грешка при инсталацията${NC}" echo -e "${YELLOW}Състояние на таймера: $timer_status${NC}" echo -e "${YELLOW}Състояние на услугата: $service_status${NC}" log_message "ERROR" "Грешка при инсталация. Състояние на таймера: $timer_status, услугата: $service_status" exit 1 fi } # Показване на употреба usage() { echo "Употреба: $0 [команда]" echo "Команди:" echo " install - Инсталира и конфигурира монитора" echo " daemon - Стартира като демон (използва се от systemd)" echo " check - Извършва единична проверка" echo " status - Показва текущия статус" echo " summary - Изпраща обобщен отчет" echo " detailed - Изпраща подробен отчет" echo " test - Тества Telegram известието" echo " config - Показва конфигурацията" echo " logs - Показва последните логове" echo " backup - Създава ръчно архивиране на статуса" echo " help - Показва тази помощ" exit 1 } # Показване на текущия статус show_status() { if ! init_script; then exit 1 fi echo -e "${BLUE}=== Статус на Proxmox Monitor ===${NC}" echo local system_info=$(get_system_info) echo "$system_info" | while IFS=: read -r key value; do echo -e "${GREEN}$key:${NC} $value" done echo echo -e "${BLUE}=== Системни ресурси ===${NC}" echo -e "${GREEN}CPU използване:${NC} $(get_cpu_usage)%" echo -e "${GREEN}Използване на памет:${NC} $(get_memory_usage)%" echo -e "${GREEN}Дисково използване:${NC} $(get_disk_usage)%" echo -e "${GREEN}Средно натоварване:${NC} $(get_load_average)" echo -e "${GREEN}Температура на CPU:${NC} $(get_temperature)°C" local network_usage=$(get_network_usage) echo -e "${GREEN}Мрежова активност:${NC} ⬇️ $(echo "$network_usage" | cut -d: -f1) KB/s ⬆️ $(echo "$network_usage" | cut -d: -f2) KB/s" echo echo -e "${BLUE}=== Услуги ===${NC}" local service_status=$(check_proxmox_services) if [[ "$service_status" == "OK" ]]; then echo -e "${GREEN}Всички Proxmox услуги работят${NC}" else echo -e "${RED}Неуспешни услуги: $(echo "$service_status" | cut -d: -f2)${NC}" fi echo echo -e "${BLUE}=== ZFS ===${NC}" local zfs_status=$(check_zfs_pools) case "$zfs_status" in "OK") echo -e "${GREEN}Всички ZFS пулове са нормални${NC}" ;; "ISSUES"*) echo -e "${RED}Проблеми с ZFS: $(echo "$zfs_status" | cut -d: -f2)${NC}" ;; "NO_POOLS") echo -e "${YELLOW}Няма ZFS пулове${NC}" ;; *) echo -e "${YELLOW}ZFS статус: $zfs_status${NC}" ;; esac echo echo -e "${BLUE}=== RAID ===${NC}" local raid_status=$(check_raid_status) case "$raid_status" in "OK") echo -e "${GREEN}RAID масивът е нормален${NC}" ;; "DEGRADED"*) echo -e "${RED}Проблеми с RAID: $(echo "$raid_status" | cut -d: -f2)${NC}" ;; *) echo -e "${YELLOW}RAID статус: $raid_status${NC}" ;; esac echo echo -e "${BLUE}=== UPS ===${NC}" local ups_status=$(check_ups_status) case "$ups_status" in "OK"*) echo -e "${GREEN}UPS статус: $(echo "$ups_status" | cut -d: -f2-)${NC}" ;; "ISSUE"*) echo -e "${RED}Проблеми с UPS: $(echo "$ups_status" | cut -d: -f2-)${NC}" ;; "NO_UPS") echo -e "${YELLOW}Няма конфигуриран UPS${NC}" ;; *) echo -e "${YELLOW}UPS статус: $ups_status${NC}" ;; esac echo echo -e "${BLUE}=== Контейнери/ВМ ===${NC}" local container_status=$(get_container_status) local running=0 local stopped=0 while IFS= read -r line; do if [[ -n "$line" ]]; then local vmid=$(echo "$line" | cut -d: -f1) local status=$(echo "$line" | cut -d: -f2) local name=$(echo "$line" | cut -d: -f3) local type=$(echo "$line" | cut -d: -f4) local ip=$(echo "$line" | cut -d: -f5) if [[ "$status" == "running" ]]; then ((running++)) echo -e "${GREEN}✅ $type $vmid ($name) [$ip]: $status${NC}" else ((stopped++)) echo -e "${RED}❌ $type $vmid ($name) [$ip]: $status${NC}" fi fi done <<< "$container_status" echo echo -e "${BLUE}Обобщение: ${GREEN}$running работят${NC}, ${RED}$stopped спрени${NC}" } # Тестване на Telegram известие test_telegram() { if ! init_script; then exit 1 fi echo -e "${BLUE}Тестване на Telegram известие...${NC}" local test_message="🧪 Proxmox Monitor Тест Това е тестово съобщение от вашата Proxmox система за мониторинг. Система: $(hostname) Време: $(date) Статус: ✅ Тестът е успешен 📊 Системни ресурси: • CPU: $(get_cpu_usage)% • Памет: $(get_memory_usage)% • Диск: $(get_disk_usage)% • Натоварване: $(get_load_average)" if send_telegram_notification "$test_message"; then echo -e "${GREEN}✅ Тестовото известие е изпратено успешно!${NC}" log_message "INFO" "Успешен тест на Telegram известие" else echo -e "${RED}❌ Грешка при изпращане на тестово известие${NC}" echo -e "${YELLOW}Моля, проверете вашата Telegram конфигурация${NC}" log_message "ERROR" "Грешка при тест на Telegram известие" fi } # Създаване на ръчно архивиране create_backup() { if ! init_script; then exit 1 fi echo -e "${BLUE}Създаване на архивиране на статуса...${NC}" if [[ ! -f "$STATUS_FILE" ]]; then echo -e "${YELLOW}Няма данни за статус за архивиране${NC}" return fi local backup_file="$BACKUP_DIR/status_$(date +%Y%m%d%H%M%S).json.gz" gzip -c "$STATUS_FILE" > "$backup_file" if [[ $? -eq 0 ]]; then echo -e "${GREEN}✅ Успешно архивиране: $backup_file${NC}" log_message "INFO" "Успешно ръчно архивиране: $backup_file" else echo -e "${RED}❌ Грешка при архивиране${NC}" log_message "ERROR" "Грешка при ръчно архивиране" fi } # Главно изпълнение case "${1:-}" in "install") install_monitor ;; "daemon") while true; do monitor_system sleep "$CHECK_INTERVAL" done ;; "check") monitor_system ;; "status") show_status ;; "summary") if init_script; then report=$(generate_status_report "SUMMARY" "") send_telegram_notification "$report" echo -e "${GREEN}Обобщен отчет изпратен${NC}" fi ;; "detailed") if init_script; then report=$(generate_status_report "DETAILED" "") send_telegram_notification "$report" echo -e "${GREEN}Подробен отчет изпратен${NC}" fi ;; "test") test_telegram ;; "config") if [[ -f "$CONFIG_FILE" ]]; then echo -e "${BLUE}=== Конфигурация ===${NC}" cat "$CONFIG_FILE" else echo -e "${RED}Конфигурационен файл не е намерен${NC}" fi ;; "logs") if [[ -f "$LOG_FILE" ]]; then echo -e "${BLUE}=== Последни 20 лога ===${NC}" tail -20 "$LOG_FILE" echo -e "\n${BLUE}=== Обобщение на грешките ===${NC}" grep -i "error" "$LOG_FILE" | tail -10 else echo -e "${YELLOW}Няма намерени логове${NC}" fi ;; "backup") create_backup ;; "help"|*) usage ;; esac