#!/usr/bin/env bash # ============================================== # Скрипт поэтапного обновления Astra Linux # ============================================== # Цвета RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' BOLD='\033[1m' RESET='\033[0m' # Иконки CHECK="✅" ERROR="❌" WARN="⚠️" ARROW="➜" ROCKET="🚀" # Путь к маркер-файлу MARKER_FILE="/opt/config/custom_update_status.info" VERSION_FILE="/etc/astra/build_version" TARGET_VERSION="1.7.10.72" # ============================================== # Функции работы с маркер-файлом # ============================================== init_marker() { mkdir -p "$(dirname "$MARKER_FILE")" 2>/dev/null # Если файла нет - создаем со статусом 5 if [[ ! -f "$MARKER_FILE" ]]; then echo "5" > "$MARKER_FILE" echo -e "${BLUE} Создан маркер-файл: ${MARKER_FILE}${RESET}" fi } get_status() { if [[ -f "$MARKER_FILE" ]]; then cat "$MARKER_FILE" | tr -d ' \t\n\r' else echo "5" fi } set_status() { echo "$1" > "$MARKER_FILE" echo -e "${BLUE} Статус обновления: ${BOLD}$1${RESET}" } show_status_info() { local status=$(get_status) echo -e "\n${BOLD}${CYAN}━━━ Статус обновления ━━━${RESET}" case $status in 1072) echo -e "${GREEN}${CHECK} Система актуальна (версия $CURRENT_VERSION)${RESET}" echo -e "${GREEN}${CHECK} Обновление не требуется${RESET}" ;; 1) echo -e "${YELLOW}${WARN} Статус: ${BOLD}1 этап завершен${RESET}" echo -e "${YELLOW}${WARN} Требуется продолжить обновление (2 этап)${RESET}" ;; 2) echo -e "${YELLOW}${WARN} Статус: ${BOLD}2 этап завершен${RESET}" echo -e "${YELLOW}${WARN} Требуется продолжить обновление (3 этап)${RESET}" ;; 5) echo -e "${GREEN}${CHECK} Система (версия $CURRENT_VERSION)${RESET}" echo -e "${GREEN}${CHECK} Обновление не утилитой не выполнялось${RESET}" ;; *) echo -e "${RED}${ERROR} Неизвестный статус: $status${RESET}" ;; esac echo "" } # ============================================== # Шаг 1: Проверяем права root # ============================================== check_root() { echo -e "\n${BOLD}${BLUE}════════════════════════════════════════${RESET}" echo -e "${BOLD}${CYAN} ПОЭТАПНОЕ ОБНОВЛЕНИЕ ASTRA LINUX${RESET}" echo -e "${BOLD}${BLUE}════════════════════════════════════════${RESET}\n" if [[ $EUID -ne 0 ]]; then echo -e "${RED}${ERROR} Ошибка: нужны права root!${RESET}" echo -e "${YELLOW} Используйте: sudo $0${RESET}\n" read -r -p "Нажмите Enter для завершения" exit 1 else echo -e "${GREEN}${CHECK} Права root: OK${RESET}" fi } # ============================================== # Шаг 2: Читаем версию # ============================================== get_current_version() { if [[ -f "$VERSION_FILE" ]]; then CURRENT_VERSION=$(cat "$VERSION_FILE" | tr -d ' \t\n\r') echo -e "${GREEN}${CHECK} Текущая версия: ${BOLD}${CYAN}$CURRENT_VERSION${RESET}" else echo -e "${RED}${ERROR} Файл версии не найден: $VERSION_FILE${RESET}" CURRENT_VERSION="unknown" read -r -p "Нажмите Enter для завершения" exit 1 fi } # ============================================== # Шаг 3: Проверяем статус и версию # ============================================== check_status_and_version() { local status status=$(get_status) echo "" # Если система уже обновлена до целевой версии if [[ "$CURRENT_VERSION" == "$TARGET_VERSION" ]]; then echo -e "${GREEN}${CHECK} ${BOLD}Система обновлена до версии $TARGET_VERSION${RESET}" # Если статус 0 - всё хорошо, выходим if [[ "$status" == "1072" ]]; then echo -e "${GREEN}${CHECK} Все этапы завершены${RESET}\n" read -r -p "Нажмите Enter для завершения" exit 0 fi # Если статус 1 - система обновлена, но защита не установлена if [[ "$status" == "1" ]]; then echo -e "${YELLOW}${WARN} Система обновлена, но защита не установлена${RESET}" echo -e "${CYAN}${ARROW} Продолжаем со 2 этапа${RESET}" STAGE=2 return fi # Если статус 2 - защита установлена, нужна чистка if [[ "$status" == "2" ]]; then echo -e "${YELLOW}${WARN} Защита установлена, требуется чистка${RESET}" echo -e "${CYAN}${ARROW} Продолжаем с 3 этапа${RESET}" STAGE=3 return fi fi # Если версия ниже целевой echo -e "${YELLOW}${WARN} Текущая версия ($CURRENT_VERSION) ниже целевой ($TARGET_VERSION)${RESET}" show_status_info # Определяем этап на основе статуса case $status in 5) echo -e "${CYAN}${ARROW} Начинаем обновление с 1 этапа${RESET}" STAGE=1 ;; 1) echo -e "${CYAN}${ARROW} Продолжаем со 2 этапа (установка защиты)${RESET}" STAGE=2 ;; 2) echo -e "${CYAN}${ARROW} Продолжаем с 3 этапа (чистка и исправление)${RESET}" STAGE=3 ;; *) echo -e "${RED}${ERROR} Неизвестный статус, сбрасываем на 5${RESET}" set_status 5 STAGE=1 ;; esac echo "" } # ============================================== # Шаг 4: Запрос на обновление # ============================================== ask_update() { local message="" case $STAGE in 1) message="Начать обновление системы до версии $TARGET_VERSION (1 этап)? После завершения потребуется перезагрузка" ;; 2) message="Установить корпоративную систему защиты (2 этап)? После завершения потребуется перезагрузка" ;; 3) message="Выполнить чистку системы и исправление багов (3 этап)?" ;; esac echo "" # shellcheck disable=SC2086 read -p "$(echo -e ${YELLOW}${message} [y/N]: ${RESET})" -n 1 -r echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then echo -e "\n${GREEN}${ROCKET} Запускаем этап $STAGE...${RESET}\n" return 0 else echo -e "\n${YELLOW}${WARN} Обновление отменено пользователем${RESET}\n" read -r -p "Нажмите Enter для завершения" exit 0 fi } # ============================================== # ЭТАП 1: Обновление системы до 1.7.10 # ============================================== stage1_update_system() { echo -e "${BOLD}${BLUE}━━━ ЭТАП 1: Обновление системы до $TARGET_VERSION ━━━${RESET}\n" mgmt_server=$(awk -F' *= *' '/^ *server *=/{print $2}' /etc/puppetlabs/puppet/puppet.conf) if [[ -z "$mgmt_server" ]]; then echo -e "${RED}${ERROR} Не удалось получить адрес сервера управления из puppet_conf ${RESET}" read -r -p "Нажмите Enter для завершения" exit 1 fi echo -e "${GREEN}${CHECK} Сервер управления: ${BOLD}${CYAN}$mgmt_server${RESET}" echo -e "\n${BLUE} Остановка и отключение службы Puppet...${RESET}" systemctl stop puppet.service 2>/dev/null systemctl disable puppet.service 2>/dev/null sleep 5 echo -e "\n${BLUE} Настройка репозиториев Astra...${RESET}" repo_file="/etc/apt/sources.list" cat > "$repo_file" << EOF # Astra Linux 1.7.10 репозитории # Сервер управления: ${mgmt_server} # Сгенерировано: $(date) deb http://${mgmt_server}/astra/1.7.10/repository-base/ 1.7_x86-64 contrib main non-free deb http://${mgmt_server}/astra/1.7.10/repository-update/ 1.7_x86-64 contrib main non-free deb http://${mgmt_server}/astra/1.7.10/repository-extended/ 1.7_x86-64 contrib main non-free deb [trusted=yes] http://${mgmt_server}/astra/1.7/custom/ 1.7_x86-64 contrib main non-free EOF # shellcheck disable=SC2181 if [[ $? -eq 0 ]]; then echo -e "${GREEN}${CHECK} Репозитории настроены: $repo_file${RESET}" else echo -e "${RED}${ERROR} Ошибка настройки репозиториев${RESET}" read -r -p "Нажмите Enter для завершения" exit 1 fi echo -e "\n${BLUE} Очистка старых репозиториев...${RESET}" if ls /etc/apt/sources.list.d/*.list 2>/dev/null 1>/dev/null; then echo -e "${YELLOW}${WARN} Найдены файлы в /etc/apt/sources.list.d/${RESET}" echo -e "${BLUE} Файлы для удаления:${RESET}" ls -la /etc/apt/sources.list.d/*.list 2>/dev/null || echo " (нет .list файлов)" rm -f /etc/apt/sources.list.d/*.list 2>/dev/null echo -e "${GREEN}${CHECK} Все .list файлы удалены${RESET}" else echo -e "${GREEN}${CHECK} Папка /etc/apt/sources.list.d/ пуста${RESET}" fi echo -e "\n${BLUE} Обновление списка пакетов...${RESET}" apt update sleep 3 echo -e "\n${BLUE} Загрузка пакетов...${RESET}" apt dist-upgrade --download-only -y echo -e "\n${BLUE} Подготовка системы к обновлению...${RESET}" dpkg -s gk-kvm >/dev/null 2>&1 && { apt update && apt install --only-upgrade gk-kvm; } || true dpkg -s secretnet >/dev/null 2>&1 && { sudo apt purge -y secretnet; } || true dpkg -s sns >/dev/null 2>&1 && { sudo apt purge -y sns; } || true dpkg -s gk-kvm >/dev/null 2>&1 && { tarm_unlock; } || true echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor echo -e "${BLUE} Выполняется обновление...${RESET}" /usr/sbin/astra-update -A -r -T -K || { echo -e "${RED}${ERROR} Ошибка обновления пакетов${RESET}" read -r -p "Нажмите Enter для завершения" exit 1 } /usr/bin/apt -o Dpkg::Options::='--force-confold' install -y gk-eosdo xrdp astra-version --reinstall dpkg -s gk-kvm >/dev/null 2>&1 && { /usr/bin/apt -o Dpkg::Options::='--force-confold' install -y gk-kvm --reinstall; } || true dpkg -s gk-kvm >/dev/null 2>&1 && { tarm_lock; } || true if [[ -f "$VERSION_FILE" ]]; then NEW_VERSION=$(cat "$VERSION_FILE" | tr -d ' \t\n\r') if [[ "$NEW_VERSION" == "$TARGET_VERSION" ]]; then echo -e "${GREEN}${CHECK} ${BOLD}Система успешно обновлена до $TARGET_VERSION${RESET}" else echo -e "${RED}${ERROR} Версия системы: $NEW_VERSION (ожидалось $TARGET_VERSION)${RESET}" echo -e "${RED}${ERROR} Обновление прошло с ошибкой!${RESET}" read -r -p "Нажмите Enter для завершения" exit 1 fi fi # Устанавливаем статус 1 set_status 1 echo -e "\n${GREEN}${CHECK} ${BOLD}1 этап завершен! Система обновлена до $TARGET_VERSION${RESET}" echo -e "${YELLOW} Требуется перезагрузка для продолжения${RESET}" echo -e "${YELLOW} После перезагрузки запустите скрипт снова ${RESET}\n" ask_reboot } # ============================================== # ЭТАП 2: Установка корпоративной системы защиты # ============================================== stage2_install_security() { mgmt_server=$(awk -F' *= *' '/^ *server *=/{print $2}' /etc/puppetlabs/puppet/puppet.conf) if [[ -z "$mgmt_server" ]]; then echo -e "${RED}${ERROR} Не удалось получить адрес сервера управления из puppet_conf ${RESET}" read -r -p "Нажмите Enter для завершения" exit 1 fi echo -e "${BOLD}${BLUE}━━━ ЭТАП 2: Установка Secret Net ━━━${RESET}\n" if [[ -f "$VERSION_FILE" ]]; then CURRENT_VER=$(cat "$VERSION_FILE" | tr -d ' \t\n\r') if [[ "$CURRENT_VER" != "$TARGET_VERSION" ]]; then echo -e "${RED}${ERROR} Система не обновлена до $TARGET_VERSION (текущая: $CURRENT_VER)${RESET}" echo -e "${RED}${ERROR} Сначала выполните 1 этап обновления${RESET}" read -r -p "Нажмите Enter для завершения" exit 1 fi fi echo -e "${BLUE} Установка SecretNet...${RESET}" # shellcheck disable=SC2086 wget --output-file=/tmp/secretnet_1.12-4844.astra1.7_amd64.deb http://$mgmt_server/SN/secretnet_1.12-4844.astra1.7_amd64.deb apt install -y /tmp/secretnet_1.12-4844.astra1.7_amd64.deb echo -e "${BLUE} Установка SecretNet выполнена${RESET}" # Устанавливаем статус 2 set_status 2 echo -e "\n${GREEN}${CHECK} ${BOLD}2 этап завершен! Secretnet установлен${RESET}" echo -e "${YELLOW} Требуется перезагрузка для продолжения${RESET}" echo -e "${YELLOW} После перезагрузки запустите скрипт снова ${RESET}\n" ask_reboot } # ============================================== # ЭТАП 3: Чистка системы и исправление багов # ============================================== stage3_clean_and_fix() { echo -e "${BOLD}${BLUE}━━━ ЭТАП 3: Чистка системы и исправление багов ━━━${RESET}\n" echo -e "${BLUE} Запуск puppet...${RESET}" /opt/puppetlabs/bin/puppet agent -t; /opt/puppetlabs/bin/puppet agent -t; echo -e "${BLUE} Финальное обновление пакетов...${RESET}" /usr/sbin/astra-update -A -r -T echo -e "${BLUE} Исправление печати kerberos...${RESET}" rm /usr/lib/cups/backend/smb ln -s /usr/libexec/samba/smbspool_krb5_wrapper /usr/lib/cups/backend/smb chmod 700 /usr/lib/cups/backend/smb echo -e "${BLUE} Очистка старых ядер...${RESET}" base_kernel=$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/") kernels_to_remove=$(dpkg -l 'linux-*' | sed -n '/^ii/p' | \ sed "/$base_kernel/d" | \ sed 's/^[^ ]* [^ ]* \([^ ]*\).*/\1/' | \ sed -n '/[0-9]/p' | \ head -n -1) if [ -n "$kernels_to_remove" ]; then apt purge -y "$kernels_to_remove" fi echo -e "${BLUE} Очистка пакетов...${RESET}" apt clean apt autoclean apt autopurge -y aptitude purge ~c -y echo -e "${BLUE} Запуск puppet и возвращение в автозапуск...${RESET}" systemctl enable puppet --now echo -e "${GREEN}${CHECK} Чистка и исправление завершены${RESET}\n" set_status 1072 echo -e "\n${BOLD}${GREEN}════════════════════════════════════════${RESET}" echo -e "${BOLD}${GREEN} ✅ ОБНОВЛЕНИЕ УСПЕШНО ЗАВЕРШЕНО!${RESET}" echo -e "${BOLD}${GREEN}════════════════════════════════════════${RESET}" echo -e "${GREEN}${CHECK} Система: ${BOLD}$TARGET_VERSION${RESET}" echo -e "${GREEN}${SHIELD} Защита: ${BOLD}установлена${RESET}" echo -e "${GREEN}${CLEAN} Чистка: ${BOLD}выполнена${RESET}" echo -e "${BOLD}${GREEN}════════════════════════════════════════${RESET}\n" if [[ -f /var/run/reboot-required ]]; then echo -e "${YELLOW}${WARN} Рекомендуется перезагрузить систему${RESET}" ask_reboot fi } # ============================================== # Запрос перезагрузки # ============================================== ask_reboot() { # shellcheck disable=SC2086 read -p "$(echo -e ${YELLOW}Перезагрузить сейчас? [y/N]: ${RESET})" -n 1 -r echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then echo -e "${BLUE} Перезагрузка...${RESET}" reboot else echo -e "${YELLOW}${WARN} Перезагрузка отложена${RESET}" echo -e "${YELLOW}${WARN} Не забудьте перезагрузить систему вручную!${RESET}" echo -e "${YELLOW} Для продолжения обновления запустите: sudo $0${RESET}" fi } # ============================================== # MAIN # ============================================== main() { check_root init_marker get_current_version check_status_and_version ask_update case $STAGE in 1) stage1_update_system ;; 2) stage2_install_security ;; 3) stage3_clean_and_fix ;; *) echo -e "${RED}${ERROR} Неизвестный этап: $STAGE${RESET}" read -r -p "Нажмите Enter для завершения" exit 1 ;; esac } main "$@"