#!/bin/bash # Настройка цветов для вывода RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color show_help() { echo "Использование: $0 -t <домашняя команда> -r <релиз> [-l <лига>]" echo " -r Релиз (тег или ветка в git)" echo " -h Показать эту справку" echo "" echo "Пример: $0 -r Barabanov_TEST" echo "" exit 0 } # Функция для вывода цветных сообщений log_info() { echo -e "${GREEN}[INFO]${NC} $1" >&2 } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" >&2 } log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2 } # Функция проверки и установки пакетов install_packages() { log_info "Обновление списка пакетов..." apt-get update log_info "Установка необходимых пакетов..." apt-get install -y python3 python3-pip python3-venv git net-tools # Проверка установки if ! command -v python3 &> /dev/null; then log_error "Python3 не установлен!" exit 1 fi if ! command -v pip3 &> /dev/null; then log_error "pip3 не установлен!" exit 1 fi log_info "Версия Python: $(python3 --version)" log_info "Версия pip: $(pip3 --version)" } # Функция загрузки кода download_code() { local repo_url="https://git.tvstart.ru/ychernenko/KHL.git" local release="$1" local target_dir="/root/KHL" log_info "Создание рабочей директории $target_dir..." mkdir -p $target_dir if [ -d "$target_dir/.git" ]; then log_info "Обновление существующего репозитория..." cd $target_dir git fetch --all git checkout $release 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 fi log_info "Код успешно загружен (релиз: $release)" log_info "Текущая ветка: $(git branch --show-current)" log_info "Последний коммит: $(git log --oneline -1)" } # Функция настройки виртуального окружения setup_venv() { local target_dir="/root/KHL" cd $target_dir log_info "Создание виртуального окружения..." python3 -m venv .venv if [ ! -f ".venv/bin/activate" ]; then log_error "Не удалось создать виртуальное окружение" exit 1 fi log_info "Активация виртуального окружения и установка зависимостей..." source .venv/bin/activate # Обновление pip pip install --upgrade pip # Проверка наличия requirements.txt if [ -f "requirements.txt" ]; then log_info "Установка зависимостей из requirements.txt..." if pip install -r requirements.txt; then log_info "Все зависимости успешно установлены" else log_error "Ошибка при установке зависимостей из requirements.txt" log_warn "Попытка установки базовых зависимостей..." pip install requests pandas numpy fi else log_warn "Файл requirements.txt не найден, устанавливаем базовые зависимости..." pip install requests pandas numpy fi # Проверка основных пакетов log_info "Проверка установки основных пакетов..." python -c " try: import requests, pandas, numpy print('✓ Все основные пакеты успешно импортируются') except ImportError as e: print(f'✗ Ошибка импорта: {e}') exit(1) " log_info "Установленные пакеты:" pip list --format=columns } # Функция создания systemd сервиса create_systemd_service() { local team="$1" local league="$2" log_info "Создание systemd сервиса для команды: $team" if [ -n "$league" ]; then log_info "Лига: $league" fi # Останавливаем и отключаем старый сервис если он есть if systemctl is-active --quiet khl-data.service; then log_info "Остановка khl-data.service..." systemctl stop khl-data.service fi if systemctl is-enabled --quiet khl-data.service; then log_info "Отключение khl-data.service..." systemctl disable khl-data.service 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" log_info "Создание файла сервиса: $data_service_file" cat > "$data_service_file" << EOF [Unit] Description=khl Data Service After=network.target [Service] Type=simple User=root WorkingDirectory=/root/KHL Environment=PATH=/root/KHL/.venv/bin ExecStart=$data_command Restart=always RestartSec=30 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF # Настройка прав chmod 644 "$data_service_file" log_info "Перезагрузка systemd демона..." systemctl daemon-reload log_info "Включение сервиса khl-data.service..." systemctl enable khl-data.service } # Функция проверки файлов check_required_files() { local target_dir="/root/KHL" cd $target_dir local missing_files=() local required_files=("get_data.py") for file in "${required_files[@]}"; do if [ ! -f "$file" ]; then missing_files+=("$file") fi done if [ ${#missing_files[@]} -ne 0 ]; then log_error "Отсутствуют необходимые файлы: ${missing_files[*]}" log_error "Содержимое директории $target_dir:" ls -la exit 1 fi log_info "Все необходимые файлы присутствуют" # Дополнительная проверка на исполняемость Python файла if ! python3 -c "import ast; ast.parse(open('get_data.py').read())" 2>/dev/null; then log_warn "Файл get_data.py содержит синтаксические ошибки Python" 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" 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" fi } # Функция проверки порта check_port() { local port=8000 local occupied=false if command -v netstat &> /dev/null && netstat -tuln 2>/dev/null | grep ":$port " > /dev/null; then occupied=true elif command -v ss &> /dev/null && ss -tuln 2>/dev/null | grep ":$port " > /dev/null; then occupied=true fi if [ "$occupied" = true ]; then log_warn "Порт $port уже занят. Возможно, приложение уже запущено." return 1 fi return 0 } # Функция управления сервисами manage_services() { local action="$1" case $action in "start") log_info "Запуск сервиса khl-data.service..." systemctl start khl-data.service ;; "restart") log_info "Перезапуск сервиса khl-data.service..." systemctl restart khl-data.service ;; "stop") log_info "Остановка сервиса khl-data.service..." systemctl stop khl-data.service ;; esac # Даем время сервису на запуск/остановку sleep 3 } # Функция проверки статуса сервиса check_service_status() { log_info "Статус сервиса khl-data.service:" if systemctl is-active khl-data.service; then systemctl status khl-data.service --no-pager -l else log_warn "Сервис khl-data.service не запущен" fi } # Функция проверки системы check_system() { log_info "Проверка системы..." # Проверка дистрибутива if [ -f /etc/os-release ]; then source /etc/os-release log_info "Дистрибутив: $PRETTY_NAME" fi # Проверка свободного места local available_space=$(df /root --output=avail | tail -1) if [ "$available_space" -lt 1048576 ]; then # Меньше 1GB log_warn "Мало свободного места: $((available_space / 1024)) MB" else log_info "Свободное место: $((available_space / 1024 / 1024)) GB" fi # Проверка памяти local total_mem=$(grep MemTotal /proc/meminfo | awk '{print $2}') log_info "Оперативная память: $((total_mem / 1024)) MB" } # Основная функция main() { local team="" local release="main" # значение по умолчанию local league="" # переменная для лиги # Обработка аргументов командной строки while getopts "t:r:l: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" else log_info "Лига: не указана (будет использовано значение по умолчанию)" fi # Проверка прав root if [[ $EUID -ne 0 ]]; then log_error "Этот скрипт должен запускаться с правами root" exit 1 fi # Проверка системы check_system # Установка пакетов install_packages # Загрузка кода download_code "$release" # Проверка файлов check_required_files # Настройка виртуального окружения 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 # Проверка порта check_port # Создание systemd сервиса create_systemd_service "$final_team" "$league" log_info "Настройка завершена!" # Запуск сервиса manage_services "start" # Проверка статуса check_service_status # Получаем IP для вывода 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 "" log_info "Для просмотра логов:" log_info " journalctl -u khl-data.service -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 "" log_info "Проверка работы:" log_info " Проверить процессы: ps aux | grep get_data.py" log_info " Проверить логи: tail -f /root/KHL/logs/*.log 2>/dev/null || echo 'Директория логов не найдена'" log_info "==================================================" } # Обработка прерывания trap 'log_error "Прервано пользователем"; exit 1' INT TERM # Запуск основной функции main "$@"