From e48a001d379b45414b6fe235987aa5b0edc50d4c Mon Sep 17 00:00:00 2001 From: PapaTramp <66860289+PTah@users.noreply.github.com> Date: Thu, 14 May 2026 12:57:55 +1000 Subject: [PATCH] Create update_ssh_monitor.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Скрипт проверки наличия обновлений основного скрипта --- update_ssh_monitor.sh | 365 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 update_ssh_monitor.sh diff --git a/update_ssh_monitor.sh b/update_ssh_monitor.sh new file mode 100644 index 0000000..591e914 --- /dev/null +++ b/update_ssh_monitor.sh @@ -0,0 +1,365 @@ +#!/bin/bash + +# === Конфигурация скрипта === +UPDATE_DIR="/opt/scripts/update" +SCRIPT_NAME="ssh-monitor" +REPO_URL="https://git.kalinamall.ru/PapaTramp/ssh-monitor.git" +LOCAL_SCRIPT_PATH="/usr/local/bin/ssh-monitor" +LOG_FILE="/var/log/update_script.log" + +# Режим отладки: 1 = включён, 0 = выключен +DEBUG=0 + +# === Список переменных, объявленных в скрипте (для логирования при DEBUG=1) === +SCRIPT_VARS=("UPDATE_DIR" "SCRIPT_NAME" "REPO_URL" "LOCAL_SCRIPT_PATH" "LOG_FILE" "DEBUG" "REMOTE_SCRIPT_PATH" "LOCAL_CHECKSUM" "REMOTE_CHECKSUM") + +# === Функции === + +# Основная функция логирования +log_message() { + local level="$1" + local message="$2" + local timestamp + timestamp="$(date '+%Y-%m-%d %H:%M:%S')" + + # Создаём лог-файл и директорию при необходимости + if [ ! -f "$LOG_FILE" ]; then + mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null + touch "$LOG_FILE" 2>/dev/null + fi + + if [ "$level" = "INFO" ]; then + echo "$timestamp INFO: $message" >> "$LOG_FILE" + elif [ "$level" = "DEBUG" ] && [ "$DEBUG" -eq 1 ]; then + echo "$timestamp DEBUG: $message" >> "$LOG_FILE" + elif [ "$level" = "ERROR" ]; then + echo "$timestamp ERROR: $message" >> "$LOG_FILE" + fi +} + +# Функция для логирования шагов с комментариями (работает только при DEBUG=1) +debug_step() { + if [ "$DEBUG" -eq 1 ]; then + log_message "DEBUG" "# $1" + fi +} + +# Функция для логирования только объявленных в скрипте переменных +log_script_vars() { + if [ "$DEBUG" -eq 1 ]; then + log_message "DEBUG" "=== Значения переменных скрипта ===" + for var_name in "${SCRIPT_VARS[@]}"; do + local var_value="${!var_name}" + log_message "DEBUG" "$var_name='$var_value'" + done + log_message "DEBUG" "=== Конец списка переменных ===" + fi +} + +# === КРИТИЧЕСКАЯ ФУНКЦИЯ: Проверка и установка ipset === +ensure_ipset_installed() { + debug_step "Проверяем наличие ipset в системе" + + # Проверяем, установлен ли ipset + if ! command -v ipset &>/dev/null; then + log_message "INFO" "ipset not found. Attempting silent installation..." + debug_step "ipset не обнаружен, начинаем установку в silent режиме" + + # Определяем пакетный менеджер и устанавливаем ipset + if command -v apt-get &>/dev/null || command -v apt &>/dev/null; then + debug_step "Обнаружен Debian/Ubuntu, используем apt" + log_message "INFO" "Detected apt package manager, installing ipset..." + + # Тихая установка через apt + if apt-get update -qq >/dev/null 2>&1 && apt-get install -y -qq ipset >/dev/null 2>&1; then + log_message "INFO" "ipset installed successfully via apt" + debug_step "ipset успешно установлен через apt" + else + log_message "ERROR" "Failed to install ipset via apt" + log_message "ERROR" "Работа обновленного скрипта невозможна без установленного ipset" + debug_step "КРИТИЧЕСКАЯ ОШИБКА: Не удалось установить ipset через apt" + return 1 + fi + + elif command -v yum &>/dev/null; then + debug_step "Обнаружен RHEL/CentOS, используем yum" + log_message "INFO" "Detected yum package manager, installing ipset..." + + if yum install -y -q ipset >/dev/null 2>&1; then + log_message "INFO" "ipset installed successfully via yum" + debug_step "ipset успешно установлен через yum" + else + log_message "ERROR" "Failed to install ipset via yum" + log_message "ERROR" "Работа обновленного скрипта невозможна без установленного ipset" + debug_step "КРИТИЧЕСКАЯ ОШИБКА: Не удалось установить ipset через yum" + return 1 + fi + + elif command -v dnf &>/dev/null; then + debug_step "Обнаружен Fedora/RHEL 8+, используем dnf" + log_message "INFO" "Detected dnf package manager, installing ipset..." + + if dnf install -y -q ipset >/dev/null 2>&1; then + log_message "INFO" "ipset installed successfully via dnf" + debug_step "ipset успешно установлен через dnf" + else + log_message "ERROR" "Failed to install ipset via dnf" + log_message "ERROR" "Работа обновленного скрипта невозможна без установленного ipset" + debug_step "КРИТИЧЕСКАЯ ОШИБКА: Не удалось установить ipset через dnf" + return 1 + fi + + elif command -v pacman &>/dev/null; then + debug_step "Обнаружен Arch Linux, используем pacman" + log_message "INFO" "Detected pacman package manager, installing ipset..." + + if pacman -S --noconfirm --quiet ipset >/dev/null 2>&1; then + log_message "INFO" "ipset installed successfully via pacman" + debug_step "ipset успешно установлен через pacman" + else + log_message "ERROR" "Failed to install ipset via pacman" + log_message "ERROR" "Работа обновленного скрипта невозможна без установленного ipset" + debug_step "КРИТИЧЕСКАЯ ОШИБКА: Не удалось установить ipset через pacman" + return 1 + fi + + elif command -v zypper &>/dev/null; then + debug_step "Обнаружен openSUSE, используем zypper" + log_message "INFO" "Detected zypper package manager, installing ipset..." + + if zypper --quiet --non-interactive install ipset >/dev/null 2>&1; then + log_message "INFO" "ipset installed successfully via zypper" + debug_step "ipset успешно установлен через zypper" + else + log_message "ERROR" "Failed to install ipset via zypper" + log_message "ERROR" "Работа обновленного скрипта невозможна без установленного ipset" + debug_step "КРИТИЧЕСКАЯ ОШИБКА: Не удалось установить ipset через zypper" + return 1 + fi + + else + log_message "ERROR" "Unsupported package manager. Cannot install ipset" + log_message "ERROR" "Работа обновленного скрипта невозможна без установленного ipset" + debug_step "КРИТИЧЕСКАЯ ОШИБКА: Пакетный менеджер не распознан" + return 1 + fi + + # Проверяем, что ipset действительно установился + if ! command -v ipset &>/dev/null; then + log_message "ERROR" "ipset installation verification failed" + log_message "ERROR" "Работа обновленного скрипта невозможна без установленного ipset" + debug_step "КРИТИЧЕСКАЯ ОШИБКА: ipset не обнаружен после установки" + return 1 + fi + + else + debug_step "ipset уже установлен в системе" + log_message "INFO" "ipset is already installed" + + # Проверяем версию ipset (информационно) + if [ "$DEBUG" -eq 1 ]; then + local ipset_version=$(ipset --version 2>&1) + log_message "DEBUG" "ipset version: $ipset_version" + fi + fi + + log_message "INFO" "ipset check/installation completed successfully" + return 0 +} + +# === Гарантированное создание директорий === +ensure_directories() { + debug_step "Проверяем и создаём необходимые директории" + + # Создаём UPDATE_DIR если не существует + if [ ! -d "$UPDATE_DIR" ]; then + log_message "INFO" "Creating directory: $UPDATE_DIR" + debug_step "Директория $UPDATE_DIR не существует, создаём" + if mkdir -p "$UPDATE_DIR" 2>/dev/null; then + log_message "INFO" "Directory created successfully" + else + log_message "INFO" "ERROR: Cannot create directory $UPDATE_DIR" + return 1 + fi + else + debug_step "Директория $UPDATE_DIR уже существует" + fi + + # Проверяем права на запись + if [ ! -w "$UPDATE_DIR" ]; then + log_message "INFO" "WARNING: Directory $UPDATE_DIR is not writable" + debug_step "ПРЕДУПРЕЖДЕНИЕ: Нет прав на запись в $UPDATE_DIR" + return 1 + fi + + return 0 +} + +# Функция для обновления скрипта +update_script() { + log_message "INFO" "Starting script update..." + debug_step "Запуск функции обновления скрипта" + + # Гарантируем наличие директории + debug_step "Гарантируем наличие директории для работы" + if ! ensure_directories; then + return 1 + fi + + # Переходим в директорию для клона репозитория + debug_step "Переходим в директорию для клона репозитория: $UPDATE_DIR" + if ! cd "$UPDATE_DIR" 2>/dev/null; then + log_message "INFO" "ERROR: Cannot cd to $UPDATE_DIR" + return 1 + fi + + # Клонируем или обновляем репозиторий + debug_step "Проверяем наличие репозитория и обновляем/клонируем" + if [ -d "$SCRIPT_NAME" ]; then + log_message "INFO" "Repository exists, pulling updates..." + debug_step "Выполняем git pull origin main" + if ! git -C "$SCRIPT_NAME" pull origin main >> "$LOG_FILE" 2>&1; then + log_message "INFO" "WARNING: git pull failed, continuing with existing local copy..." + fi + else + log_message "INFO" "Cloning repository from $REPO_URL" + debug_step "Выполняем git clone $REPO_URL $SCRIPT_NAME" + if ! git clone "$REPO_URL" "$SCRIPT_NAME" >> "$LOG_FILE" 2>&1; then + log_message "INFO" "ERROR: git clone failed" + return 1 + fi + fi + + # Формируем путь к скрипту в репозитории (основной и альтернативный) + REMOTE_SCRIPT_PATH="$UPDATE_DIR/$SCRIPT_NAME/src/branch/main/$SCRIPT_NAME" + ALT_REMOTE_PATH="$UPDATE_DIR/$SCRIPT_NAME/$SCRIPT_NAME" + + debug_step "Основной путь к скрипту: $REMOTE_SCRIPT_PATH" + debug_step "Альтернативный путь к скрипту: $ALT_REMOTE_PATH" + + # Определяем реальный путь к скрипту + local actual_script_path="" + if [ -f "$REMOTE_SCRIPT_PATH" ]; then + actual_script_path="$REMOTE_SCRIPT_PATH" + debug_step "Скрипт найден по основному пути" + elif [ -f "$ALT_REMOTE_PATH" ]; then + actual_script_path="$ALT_REMOTE_PATH" + log_message "INFO" "Script found at alternative path" + debug_step "Скрипт найден по альтернативному пути" + fi + + # Проверяем наличие файла скрипта в репозитории + if [ -n "$actual_script_path" ] && [ -f "$actual_script_path" ]; then + log_message "INFO" "Remote script found. Comparing checksums..." + debug_step "Проверяем наличие файла скрипта в репозитории" + + # Проверяем существование локального скрипта + if [ ! -f "$LOCAL_SCRIPT_PATH" ]; then + log_message "INFO" "Local script not found. Will install new one." + LOCAL_CHECKSUM="" + debug_step "Локальный скрипт отсутствует, будет установлен новый" + else + debug_step "Вычисляем контрольную сумму локального скрипта" + LOCAL_CHECKSUM=$(sha256sum "$LOCAL_SCRIPT_PATH" 2>/dev/null | awk '{print $1}') + fi + + debug_step "Вычисляем контрольную сумму удалённого скрипта" + REMOTE_CHECKSUM=$(sha256sum "$actual_script_path" 2>/dev/null | awk '{print $1}') + + # Сравниваем контрольные суммы + debug_step "Сравниваем контрольные суммы" + if [ "$LOCAL_CHECKSUM" != "$REMOTE_CHECKSUM" ]; then + log_message "INFO" "Checksums differ. Updating $LOCAL_SCRIPT_PATH..." + debug_step "Контрольные суммы различаются, начинаем обновление" + + # Создаем бекап текущего скрипта если он существует + if [ -f "$LOCAL_SCRIPT_PATH" ]; then + debug_step "Создаем резервную копию текущего скрипта" + cp "$LOCAL_SCRIPT_PATH" "${LOCAL_SCRIPT_PATH}.backup.$(date +%Y%m%d_%H%M%S)" 2>/dev/null + fi + + debug_step "Копируем новый скрипт в $LOCAL_SCRIPT_PATH" + if ! cp "$actual_script_path" "$LOCAL_SCRIPT_PATH"; then + log_message "INFO" "ERROR: Failed to copy script" + return 1 + fi + + debug_step "Делаем скрипт исполняемым" + chmod +x "$LOCAL_SCRIPT_PATH" + + log_message "INFO" "Script updated successfully." + debug_step "Скрипт успешно обновлен" + + # Перезапускаем сервис + debug_step "Перезапускаем сервис ssh-monitor.service" + if command -v systemctl &>/dev/null; then + if systemctl restart ssh-monitor.service 2>/dev/null; then + log_message "INFO" "Service restarted successfully." + debug_step "Сервис успешно перезапущен" + else + log_message "INFO" "WARNING: Failed to restart service (may not be running)" + debug_step "ПРЕДУПРЕЖДЕНИЕ: Не удалось перезапустить сервис" + fi + else + log_message "INFO" "systemctl not found, service not restarted" + debug_step "systemctl не найден, сервис не перезапущен" + fi + else + log_message "INFO" "Checksums match. No update needed." + debug_step "Контрольные суммы совпадают, обновление не требуется" + fi + else + log_message "INFO" "No remote script found. No update needed." + debug_step "Удаленный скрипт не найден ни по одному из путей" + + # Информация для отладки + if [ "$DEBUG" -eq 1 ]; then + debug_step "Содержимое директории репозитория:" + if [ -d "$UPDATE_DIR/$SCRIPT_NAME" ]; then + find "$UPDATE_DIR/$SCRIPT_NAME" -type f -name "$SCRIPT_NAME" 2>/dev/null | while read -r found_file; do + log_message "DEBUG" "Найден файл: $found_file" + done + fi + fi + fi + + # Логируем значения переменных скрипта при DEBUG=1 + log_script_vars + + return 0 +} + +# === Основной блок выполнения === + +log_message "INFO" "=== Script update started ===" +debug_step "Инициализация скрипта обновления" + +# 1. Гарантируем создание необходимых директорий +if ! ensure_directories; then + log_message "INFO" "ERROR: Failed to ensure directories. Exiting." + exit 1 +fi + +# 2. КРИТИЧЕСКИ ВАЖНО: Проверяем и устанавливаем ipset +debug_step "Начинаем проверку и установку ipset (КРИТИЧЕСКИЙ ШАГ)" +if ! ensure_ipset_installed; then + log_message "ERROR" "CRITICAL: ipset installation or verification failed" + log_message "ERROR" "Работа обновленного скрипта невозможна без установленного ipset" + echo "ERROR: Работа обновленного скрипта невозможна без установленного ipset" >&2 + exit 1 +fi + +# 3. Выполняем функцию обновления +update_script +exit_code=$? + +if [ $exit_code -eq 0 ]; then + log_message "INFO" "=== Script update completed successfully ===" + debug_step "Скрипт успешно завершил работу" +else + log_message "INFO" "=== Script update completed with errors (exit code: $exit_code) ===" + debug_step "Скрипт завершил работу с ошибками" +fi + +# Выход с кодом завершения +exit $exit_code