From 6d1e83d6fea7ee9a4d5dc23960c48ffaa7d83e01 Mon Sep 17 00:00:00 2001 From: Alexey Barabanov Date: Mon, 10 Nov 2025 14:38:10 +0300 Subject: [PATCH] ver 1 --- .gitignore | 5 +- deploy.sh | 370 ++++++++++++++++++++++++++++------------------------- 2 files changed, 199 insertions(+), 176 deletions(-) mode change 100644 => 100755 deploy.sh diff --git a/.gitignore b/.gitignore index 2eea525..c48f48e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -.env \ No newline at end of file +.env +/.venv +/logs/* +/__pycache__ \ No newline at end of file diff --git a/deploy.sh b/deploy.sh old mode 100644 new mode 100755 index 4079e8b..0ac9095 --- a/deploy.sh +++ b/deploy.sh @@ -4,15 +4,20 @@ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' +BLUE='\033[0;34m' NC='\033[0m' # No Color +# Конфигурация +REPO_URL="https://git.tvstart.ru/ychernenko/KHL.git" +TARGET_DIR="/root/KHL" +SERVICE_NAME="khl-data.service" + show_help() { - echo "Использование: $0 -t <домашняя команда> -r <релиз> [-l <лига>]" + echo "Использование: $0 -r <релиз> [-h]" echo " -r Релиз (тег или ветка в git)" echo " -h Показать эту справку" echo "" echo "Пример: $0 -r Barabanov_TEST" - echo "" exit 0 } @@ -30,13 +35,41 @@ log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2 } +log_debug() { + echo -e "${BLUE}[DEBUG]${NC} $1" >&2 +} + +# Функция проверки зависимостей системы +check_dependencies() { + local deps=("git" "python3" "pip3" "netstat" "systemctl") + local missing=() + + for dep in "${deps[@]}"; do + if ! command -v "$dep" &> /dev/null; then + missing+=("$dep") + fi + done + + if [ ${#missing[@]} -ne 0 ]; then + log_warn "Отсутствуют некоторые команды: ${missing[*]}" + return 1 + fi + return 0 +} + # Функция проверки и установки пакетов install_packages() { log_info "Обновление списка пакетов..." - apt-get update + if ! apt-get update; then + log_error "Ошибка при обновлении списка пакетов" + exit 1 + fi log_info "Установка необходимых пакетов..." - apt-get install -y python3 python3-pip python3-venv git net-tools + if ! apt-get install -y python3 python3-pip python3-venv git net-tools; then + log_error "Ошибка при установке пакетов" + exit 1 + fi # Проверка установки if ! command -v python3 &> /dev/null; then @@ -55,32 +88,36 @@ install_packages() { # Функция загрузки кода download_code() { - local repo_url="https://git.tvstart.ru/ychernenko/KHL.git" local release="$1" - local target_dir="/root/KHL" + local target_dir="$TARGET_DIR" log_info "Создание рабочей директории $target_dir..." - mkdir -p $target_dir + mkdir -p "$target_dir" if [ -d "$target_dir/.git" ]; then log_info "Обновление существующего репозитория..." - cd $target_dir + cd "$target_dir" || exit 1 git fetch --all - git checkout $release - git pull origin $release + if ! git checkout "$release"; then + log_error "Не удалось переключиться на релиз $release" + log_info "Доступные ветки:" + git branch -r + exit 1 + fi + git pull origin "$release" else - log_info "Клонирование репозитория $repo_url..." - git clone $repo_url $target_dir - cd $target_dir - git checkout $release - fi - - # Проверка успешности checkout - if [ $? -ne 0 ]; then - log_error "Не удалось переключиться на релиз $release" - log_error "Доступные ветки:" - git branch -r - exit 1 + log_info "Клонирование репозитория $REPO_URL..." + if ! git clone "$REPO_URL" "$target_dir"; then + log_error "Ошибка при клонировании репозитория" + exit 1 + fi + cd "$target_dir" || exit 1 + if ! git checkout "$release"; then + log_error "Не удалось переключиться на релиз $release" + log_info "Доступные ветки:" + git branch -r + exit 1 + fi fi log_info "Код успешно загружен (релиз: $release)" @@ -90,11 +127,20 @@ download_code() { # Функция настройки виртуального окружения setup_venv() { - local target_dir="/root/KHL" - cd $target_dir + local target_dir="$TARGET_DIR" + cd "$target_dir" || exit 1 + + # Удаляем существующее виртуальное окружение для чистоты + if [ -d ".venv" ]; then + log_info "Удаление существующего виртуального окружения..." + rm -rf .venv + fi log_info "Создание виртуального окружения..." - python3 -m venv .venv + if ! python3 -m venv .venv; then + log_error "Не удалось создать виртуальное окружение" + exit 1 + fi if [ ! -f ".venv/bin/activate" ]; then log_error "Не удалось создать виртуальное окружение" @@ -105,7 +151,9 @@ setup_venv() { source .venv/bin/activate # Обновление pip - pip install --upgrade pip + if ! pip install --upgrade pip; then + log_warn "Не удалось обновить pip" + fi # Проверка наличия requirements.txt if [ -f "requirements.txt" ]; then @@ -114,24 +162,29 @@ setup_venv() { log_info "Все зависимости успешно установлены" else log_error "Ошибка при установке зависимостей из requirements.txt" - log_warn "Попытка установки базовых зависимостей..." - pip install requests pandas numpy + exit 1 fi else log_warn "Файл requirements.txt не найден, устанавливаем базовые зависимости..." - pip install requests pandas numpy + if ! pip install requests pandas numpy fastapi uvicorn python-telegram-handler python-dotenv; then + log_error "Ошибка при установке базовых зависимостей" + exit 1 + fi fi # Проверка основных пакетов log_info "Проверка установки основных пакетов..." - python -c " + if ! python -c " try: import requests, pandas, numpy print('✓ Все основные пакеты успешно импортируются') except ImportError as e: print(f'✗ Ошибка импорта: {e}') exit(1) -" +"; then + log_error "Ошибка при проверке пакетов" + exit 1 + fi log_info "Установленные пакеты:" pip list --format=columns @@ -139,45 +192,34 @@ except ImportError as e: # Функция создания systemd сервиса create_systemd_service() { - local team="$1" - local league="$2" - - log_info "Создание systemd сервиса для команды: $team" - if [ -n "$league" ]; then - log_info "Лига: $league" - fi + log_info "Создание systemd сервиса" # Останавливаем и отключаем старый сервис если он есть - if systemctl is-active --quiet khl-data.service; then - log_info "Остановка khl-data.service..." - systemctl stop khl-data.service + if systemctl is-active --quiet "$SERVICE_NAME"; then + log_info "Остановка $SERVICE_NAME..." + systemctl stop "$SERVICE_NAME" fi - if systemctl is-enabled --quiet khl-data.service; then - log_info "Отключение khl-data.service..." - systemctl disable khl-data.service + if systemctl is-enabled --quiet "$SERVICE_NAME"; then + log_info "Отключение $SERVICE_NAME..." + systemctl disable "$SERVICE_NAME" fi # Формируем команду для data сервиса - local data_command="/root/KHL/.venv/bin/python3 /root/KHL/get_data.py"" - if [ -n "$league" ]; then - data_command="$data_command --league \"$league\"" - fi - - # Создаем сервисный файл в правильной директории - local data_service_file="/etc/systemd/system/khl-data.service" + local data_command="$TARGET_DIR/.venv/bin/python3 $TARGET_DIR/get_data.py" + local data_service_file="/etc/systemd/system/$SERVICE_NAME" log_info "Создание файла сервиса: $data_service_file" cat > "$data_service_file" << EOF [Unit] -Description=khl Data Service +Description=KHL Data Service After=network.target [Service] Type=simple User=root -WorkingDirectory=/root/KHL -Environment=PATH=/root/KHL/.venv/bin +WorkingDirectory=$TARGET_DIR +Environment=PATH=$TARGET_DIR/.venv/bin ExecStart=$data_command Restart=always RestartSec=30 @@ -192,16 +234,22 @@ EOF chmod 644 "$data_service_file" log_info "Перезагрузка systemd демона..." - systemctl daemon-reload + if ! systemctl daemon-reload; then + log_error "Ошибка при перезагрузке systemd демона" + exit 1 + fi - log_info "Включение сервиса khl-data.service..." - systemctl enable khl-data.service + log_info "Включение сервиса $SERVICE_NAME..." + if ! systemctl enable "$SERVICE_NAME"; then + log_error "Ошибка при включении сервиса" + exit 1 + fi } # Функция проверки файлов check_required_files() { - local target_dir="/root/KHL" - cd $target_dir + local target_dir="$TARGET_DIR" + cd "$target_dir" || exit 1 local missing_files=() local required_files=("get_data.py") @@ -227,74 +275,26 @@ check_required_files() { fi } -# Функция определения IP и команды (исправленная) -detect_team() { - local team_arg="$1" - - # Определение IP адреса - if [[ "$(uname -s)" == "Linux" ]]; then - ip_address=$(ip route get 1 2>/dev/null | awk '{print $7; exit}' || - ip a 2>/dev/null | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | - grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -n1) - else - log_error "Скрипт работает только на Linux" - exit 1 - fi - - log_info "Определен IP адрес: $ip_address" - - # База данных хостов в виде пар IP-команда - declare -A hosts=( - ["10.10.35.21"]="cska" - ["10.10.35.22"]="Lokomotiv Kuban" - ["10.10.35.23"]="uralmash" - ["10.10.35.24"]="betcity parma" - ["10.10.35.25"]="avtodor" - ["10.10.35.26"]="zenit" - ["10.10.35.27"]="samara" - ["10.10.35.28"]="mba-mai" - ["10.10.35.29"]="Pari Nizhny Novgorod" - ["10.10.35.30"]="unics" - ) - - # Определение команды по IP - detected_team="${hosts[$ip_address]}" - - # Определение финальной команды (приоритет у аргумента, затем у автоопределения) - if [[ -n "$team_arg" ]]; then - final_team="$team_arg" - log_info "Используется команда из аргумента: $final_team" - elif [[ -n "$detected_team" ]]; then - final_team="$detected_team" - log_info "Используется автоопределенная команда: $final_team" - else - log_error "Не удалось определить команду. Укажите явно через -t" - echo "Доступные команды:" >&2 - for ip in "${!hosts[@]}"; do - echo " $ip: ${hosts[$ip]}" >&2 - done - exit 1 - fi - - # Возвращаем только чистую строку с названием команды (без цветовых кодов) - echo "$final_team" -} - # Функция настройки firewall setup_firewall() { log_info "Настройка firewall (открытие порта 8000)..." # Проверяем наличие ufw if command -v ufw &> /dev/null && systemctl is-active --quiet ufw; then - ufw allow 8000/tcp - log_info "Порт 8000 открыт в ufw" + if ufw allow 8000/tcp; then + log_info "Порт 8000 открыт в ufw" + else + log_warn "Не удалось открыть порт 8000 в ufw" + fi fi # Для firewalld (CentOS/RHEL) if command -v firewall-cmd &> /dev/null && systemctl is-active --quiet firewalld; then - firewall-cmd --permanent --add-port=8000/tcp - firewall-cmd --reload - log_info "Порт 8000 открыт в firewalld" + if firewall-cmd --permanent --add-port=8000/tcp && firewall-cmd --reload; then + log_info "Порт 8000 открыт в firewalld" + else + log_warn "Не удалось открыть порт 8000 в firewalld" + fi fi } @@ -303,9 +303,9 @@ check_port() { local port=8000 local occupied=false - if command -v netstat &> /dev/null && netstat -tuln 2>/dev/null | grep ":$port " > /dev/null; then + if command -v netstat &> /dev/null && netstat -tuln 2>/dev/null | grep -q ":$port "; then occupied=true - elif command -v ss &> /dev/null && ss -tuln 2>/dev/null | grep ":$port " > /dev/null; then + elif command -v ss &> /dev/null && ss -tuln 2>/dev/null | grep -q ":$port "; then occupied=true fi @@ -322,30 +322,42 @@ manage_services() { case $action in "start") - log_info "Запуск сервиса khl-data.service..." - systemctl start khl-data.service + log_info "Запуск сервиса $SERVICE_NAME..." + if ! systemctl start "$SERVICE_NAME"; then + log_error "Ошибка при запуске сервиса" + return 1 + fi ;; "restart") - log_info "Перезапуск сервиса khl-data.service..." - systemctl restart khl-data.service + log_info "Перезапуск сервиса $SERVICE_NAME..." + if ! systemctl restart "$SERVICE_NAME"; then + log_error "Ошибка при перезапуске сервиса" + return 1 + fi ;; "stop") - log_info "Остановка сервиса khl-data.service..." - systemctl stop khl-data.service + log_info "Остановка сервиса $SERVICE_NAME..." + if ! systemctl stop "$SERVICE_NAME"; then + log_error "Ошибка при остановке сервиса" + return 1 + fi ;; esac # Даем время сервису на запуск/остановку sleep 3 + return 0 } # Функция проверки статуса сервиса check_service_status() { - log_info "Статус сервиса khl-data.service:" - if systemctl is-active khl-data.service; then - systemctl status khl-data.service --no-pager -l + log_info "Статус сервиса $SERVICE_NAME:" + if systemctl is-active "$SERVICE_NAME" &>/dev/null; then + systemctl status "$SERVICE_NAME" --no-pager -l + return 0 else - log_warn "Сервис khl-data.service не запущен" + log_warn "Сервис $SERVICE_NAME не запущен" + return 1 fi } @@ -360,7 +372,12 @@ check_system() { fi # Проверка свободного места - local available_space=$(df /root --output=avail | tail -1) + local available_space + available_space=$(df "$TARGET_DIR" --output=avail 2>/dev/null | tail -1) + if [ -z "$available_space" ]; then + available_space=$(df / --output=avail | tail -1) + fi + if [ "$available_space" -lt 1048576 ]; then # Меньше 1GB log_warn "Мало свободного места: $((available_space / 1024)) MB" else @@ -368,39 +385,46 @@ check_system() { fi # Проверка памяти - local total_mem=$(grep MemTotal /proc/meminfo | awk '{print $2}') - log_info "Оперативная память: $((total_mem / 1024)) MB" + if [ -f /proc/meminfo ]; then + local total_mem + total_mem=$(grep MemTotal /proc/meminfo | awk '{print $2}') + log_info "Оперативная память: $((total_mem / 1024)) MB" + fi + + # Проверка архитектуры + log_info "Архитектура: $(uname -m)" +} + +# Функция очистки при прерывании +cleanup() { + log_info "Очистка..." + if [ -f "/etc/systemd/system/$SERVICE_NAME" ]; then + manage_services "stop" + systemctl disable "$SERVICE_NAME" 2>/dev/null || true + rm -f "/etc/systemd/system/$SERVICE_NAME" + systemctl daemon-reload + fi } # Основная функция main() { - local team="" local release="main" # значение по умолчанию - local league="" # переменная для лиги # Обработка аргументов командной строки - while getopts "t:r:l:h" opt; do + while getopts "r:h" opt; do case $opt in - t) team="$OPTARG" ;; r) release="$OPTARG" ;; - l) league="$OPTARG" ;; h) show_help ;; *) log_error "Неверный аргумент"; exit 1 ;; esac done - - # Проверка обязательных аргументов - if [ -z "$team" ] && [ -z "$release" ]; then - log_error "Необходимо указать команду (-t) и релиз (-r)" - show_help - fi - - log_info "Начало установки khl Data Service..." - log_info "Команда: $team, Релиз: $release" - if [ -n "$league" ]; then - log_info "Лига: $league" + + log_info "Начало установки KHL Data Service..." + if [ -n "$release" ]; then + log_info "Релиз: $release" else - log_info "Лига: не указана (будет использовано значение по умолчанию)" + log_info "Релиз: не указан (будет использовано значение по умолчанию: main)" + release="main" fi # Проверка прав root @@ -409,9 +433,15 @@ main() { exit 1 fi + # Установка обработчика прерывания + trap 'log_error "Прервано пользователем"; cleanup; exit 1' INT TERM + # Проверка системы check_system + # Проверка зависимостей + check_dependencies + # Установка пакетов install_packages @@ -424,16 +454,6 @@ main() { # Настройка виртуального окружения setup_venv - # Определение команды - ТЕПЕРЬ БЕЗ временного файла - final_team=$(detect_team "$team") - log_info "Финальная команда: '$final_team'" - - # Проверка что команда не пустая и не содержит спецсимволов - if [[ -z "$final_team" || "$final_team" =~ [^a-zA-Z0-9[:space:]-] ]]; then - log_error "Некорректное название команды: '$final_team'" - exit 1 - fi - # Настройка firewall setup_firewall @@ -441,46 +461,46 @@ main() { check_port # Создание systemd сервиса - create_systemd_service "$final_team" "$league" + create_systemd_service log_info "Настройка завершена!" # Запуск сервиса - manage_services "start" + if manage_services "start"; then + log_info "Сервис успешно запущен" + else + log_error "Не удалось запустить сервис" + exit 1 + fi # Проверка статуса check_service_status # Получаем IP для вывода + local ip_address ip_address=$(ip route get 1 2>/dev/null | awk '{print $7; exit}' || ip a 2>/dev/null | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -n1) log_info "==================================================" log_info "Установка завершена успешно!" - log_info "Команда: $final_team" - if [ -n "$league" ]; then - log_info "Лига: $league" - fi - log_info "Режим: $release" + log_info "Релиз: $release" + log_info "Рабочая директория: $TARGET_DIR" log_info "" log_info "Для просмотра логов:" - log_info " journalctl -u khl-data.service -f" + log_info " journalctl -u $SERVICE_NAME -f" log_info "" log_info "Управление сервисом:" - log_info " Перезапуск: systemctl restart khl-data.service" - log_info " Остановка: systemctl stop khl-data.service" - log_info " Статус: systemctl status khl-data.service" - log_info " Логи: journalctl -u khl-data.service" + log_info " Перезапуск: systemctl restart $SERVICE_NAME" + log_info " Остановка: systemctl stop $SERVICE_NAME" + log_info " Статус: systemctl status $SERVICE_NAME" + log_info " Логи: journalctl -u $SERVICE_NAME" log_info "" log_info "Проверка работы:" log_info " Проверить процессы: ps aux | grep get_data.py" - log_info " Проверить логи: tail -f /root/KHL/logs/*.log 2>/dev/null || echo 'Директория логов не найдена'" + log_info " Проверить логи: tail -f $TARGET_DIR/logs/*.log 2>/dev/null || echo 'Директория логов не найдена'" log_info "==================================================" } -# Обработка прерывания -trap 'log_error "Прервано пользователем"; exit 1' INT TERM - # Запуск основной функции main "$@" \ No newline at end of file