Create update_ssh_monitor.sh
Скрипт проверки наличия обновлений основного скрипта
This commit is contained in:
@@ -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
|
||||||
Reference in New Issue
Block a user