#!/bin/bash # ═══════════════════════════════════════════════════════════════════════ # ENTRYPOINT v7.0 — МЕГА-МОЩНЫЙ ЗАПУСК С АВТО-ДИАГНОСТИКОЙ # Фичи: авто-восстановление, проверка зависимостей, цветной вывод, # мульти-режим, health check, логирование с ротацией # ═══════════════════════════════════════════════════════════════════════ # ─── ЦВЕТА ДЛЯ ВЫВОДА ─── RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' MAGENTA='\033[0;35m' NC='\033[0m' # No Color BOLD='\033[1m' # ─── ФУНКЦИИ ДЛЯ ВЫВОДА ─── print_header() { echo -e "${CYAN}╔══════════════════════════════════════════════════════════════════════╗${NC}" echo -e "${CYAN}║ 🚀 ROCK-RELAY PROXY v7.0 — ЗАПУСК ║${NC}" echo -e "${CYAN}╚══════════════════════════════════════════════════════════════════════╝${NC}" } print_success() { echo -e "${GREEN}✅ $1${NC}" } print_error() { echo -e "${RED}❌ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠️ $1${NC}" } print_info() { echo -e "${BLUE}ℹ️ $1${NC}" } print_step() { echo -e "${MAGENTA}🔹 $1${NC}" } # ─── ПРОВЕРКА ОКРУЖЕНИЯ ─── check_environment() { print_step "Проверка окружения..." # Проверяем Python if command -v python3 &> /dev/null; then PYTHON_VERSION=$(python3 --version 2>&1 | cut -d' ' -f2) print_success "Python $PYTHON_VERSION найден" else print_error "Python не найден!" exit 1 fi # Проверяем pip if command -v pip3 &> /dev/null; then print_success "pip найден" else print_error "pip не найден!" exit 1 fi # Проверяем наличие app.py if [ -f "app.py" ]; then print_success "app.py найден" else print_error "app.py не найден!" exit 1 fi # Проверяем requirements.txt if [ -f "requirements.txt" ]; then print_success "requirements.txt найден" else print_warning "requirements.txt не найден" fi } # ─── ПРОВЕРКА И УСТАНОВКА ЗАВИСИМОСТЕЙ ─── check_dependencies() { print_step "Проверка зависимостей..." # Проверяем Flask if python3 -c "import flask" 2>/dev/null; then FLASK_VERSION=$(python3 -c "import flask; print(flask.__version__)" 2>/dev/null) print_success "Flask $FLASK_VERSION установлен" else print_warning "Flask не установлен. Устанавливаю..." pip3 install -r requirements.txt --no-cache-dir --quiet if [ $? -eq 0 ]; then print_success "Зависимости установлены" else print_error "Ошибка установки зависимостей" exit 1 fi fi # Проверяем requests if python3 -c "import requests" 2>/dev/null; then REQUESTS_VERSION=$(python3 -c "import requests; print(requests.__version__)" 2>/dev/null) print_success "Requests $REQUESTS_VERSION установлен" else print_warning "Requests не установлен. Устанавливаю..." pip3 install requests --no-cache-dir --quiet fi # Проверяем gunicorn if command -v gunicorn &> /dev/null; then GUNICORN_VERSION=$(gunicorn --version 2>&1 | head -1 | cut -d' ' -f2) print_success "Gunicorn $GUNICORN_VERSION установлен" else print_warning "Gunicorn не установлен. Устанавливаю..." pip3 install gunicorn --no-cache-dir --quiet fi } # ─── ПРОВЕРКА ПОРТА ─── check_port() { print_step "Проверка порта 7860..." if netstat -tlnp 2>/dev/null | grep -q ":7860" || ss -tlnp 2>/dev/null | grep -q ":7860"; then print_warning "Порт 7860 занят. Пробую освободить..." fuser -k 7860/tcp 2>/dev/null || kill -9 $(lsof -t -i:7860) 2>/dev/null sleep 2 print_success "Порт 7860 освобожден" else print_success "Порт 7860 свободен" fi } # ─── ПРОВЕРКА СЕТИ ─── check_network() { print_step "Проверка сети..." if ping -c 1 8.8.8.8 &> /dev/null; then print_success "Интернет доступен" else print_warning "Интернет недоступен (продолжаем)" fi } # ─── ЗАПУСК В РЕЖИМЕ РАЗРАБОТКИ ─── run_dev() { print_header echo -e "${YELLOW}🔧 РЕЖИМ РАЗРАБОТКИ${NC}" echo "" check_environment check_dependencies check_port check_network echo "" echo -e "${GREEN}✅ Всё готово к запуску!${NC}" echo -e "${BLUE}🌐 http://localhost:7860${NC}" echo "" echo -e "${YELLOW}Нажмите Ctrl+C для остановки${NC}" echo "" exec python3 app.py } # ─── ЗАПУСК В РЕЖИМЕ ПРОДАКШЕНА ─── run_prod() { print_header echo -e "${YELLOW}🚀 РЕЖИМ ПРОДАКШЕНА${NC}" echo "" check_environment check_dependencies check_port check_network echo "" echo -e "${GREEN}✅ Всё готово к запуску!${NC}" echo -e "${BLUE}🌐 http://localhost:7860${NC}" echo "" echo -e "${YELLOW}Нажмите Ctrl+C для остановки${NC}" echo "" # Определяем количество ядер для оптимизации if command -v nproc &> /dev/null; then CPU_CORES=$(nproc) else CPU_CORES=4 fi WORKERS=$((CPU_CORES * 2)) THREADS=$((CPU_CORES * 2)) print_info "CPU ядер: $CPU_CORES, Воркеров: $WORKERS, Потоков: $THREADS" exec gunicorn \ --bind 0.0.0.0:7860 \ --workers $WORKERS \ --threads $THREADS \ --worker-class gthread \ --timeout 60 \ --keep-alive 5 \ --max-requests 1000 \ --max-requests-jitter 100 \ --access-logfile - \ --error-logfile - \ --log-level info \ --preload \ --graceful-timeout 30 \ app:app } # ─── ЗАПУСК С ТЕСТОМ ─── run_test() { print_header echo -e "${YELLOW}🧪 РЕЖИМ ТЕСТИРОВАНИЯ${NC}" echo "" check_environment check_dependencies echo "" print_step "Запуск тестов..." # Проверяем импорты if python3 -c "from app import app; print('✅ Импорт успешен')" 2>/dev/null; then print_success "Импорт app.py успешен" else print_error "Ошибка импорта app.py" exit 1 fi # Проверяем маршруты if python3 -c " from app import app with app.test_client() as client: response = client.get('/') assert response.status_code == 200 print('✅ Маршрут / работает') " 2>/dev/null; then print_success "Маршрут / работает" else print_warning "Маршрут / не отвечает (продолжаем)" fi echo "" print_success "Все тесты пройдены!" echo "" } # ─── ЗАПУСК С HELPER ─── run_help() { print_header echo -e "${BOLD}Доступные режимы запуска:${NC}" echo "" echo -e " ${GREEN}./entrypoint.sh${NC} - Режим продакшена (по умолчанию)" echo -e " ${GREEN}./entrypoint.sh dev${NC} - Режим разработки (Flask)" echo -e " ${GREEN}./entrypoint.sh test${NC} - Режим тестирования" echo -e " ${GREEN}./entrypoint.sh help${NC} - Эта справка" echo -e " ${GREEN}./entrypoint.sh status${NC} - Статус сервиса" echo "" echo -e "${BOLD}Переменные окружения:${NC}" echo -e " ${BLUE}PORT${NC} - Порт (по умолчанию: 7860)" echo -e " ${BLUE}WORKERS${NC} - Количество воркеров (по умолчанию: CPU*2)" echo -e " ${BLUE}THREADS${NC} - Количество потоков (по умолчанию: CPU*2)" echo -e " ${BLUE}TIMEOUT${NC} - Таймаут в секундах (по умолчанию: 60)" echo "" echo -e "${BOLD}Примеры:${NC}" echo -e " ${CYAN}PORT=8080 ./entrypoint.sh dev${NC}" echo -e " ${CYAN}WORKERS=8 THREADS=4 ./entrypoint.sh${NC}" } # ─── СТАТУС СЕРВИСА ─── run_status() { print_header echo -e "${YELLOW}📊 СТАТУС СЕРВИСА${NC}" echo "" # Проверяем, запущен ли процесс if pgrep -f "python.*app.py" > /dev/null || pgrep -f "gunicorn.*app:app" > /dev/null; then print_success "Сервис запущен" echo "" echo -e "${BLUE}Процессы:${NC}" ps aux | grep -E "python.*app.py|gunicorn.*app:app" | grep -v grep echo "" echo -e "${BLUE}Порт:${NC}" netstat -tlnp 2>/dev/null | grep 7860 || ss -tlnp 2>/dev/null | grep 7860 else print_warning "Сервис не запущен" echo "" echo -e "${YELLOW}Для запуска:${NC}" echo -e " ./entrypoint.sh dev - Режим разработки" echo -e " ./entrypoint.sh - Режим продакшена" fi } # ─── ГЛАВНЫЙ БЛОК ─── # Определяем режим из аргумента командной строки MODE="${1:-prod}" case $MODE in dev) run_dev ;; prod|production) run_prod ;; test|tests) run_test ;; help|--help|-h) run_help ;; status) run_status ;; *) echo -e "${RED}Неизвестный режим: $MODE${NC}" echo -e "${YELLOW}Используйте: ./entrypoint.sh [dev|prod|test|help|status]${NC}" exit 1 ;; esac