Files
ssh-monitor/update_ssh_monitor.sh
T
PapaTramp 3d20498515 Create update_ssh_monitor.sh
Скрипт проверки наличия обновлений основного скрипта
2026-05-14 12:57:55 +10:00

366 lines
18 KiB
Bash

#!/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