коминт

This commit is contained in:
Alexey Barabanov
2025-11-13 17:26:15 +03:00
parent cf06adbfab
commit df995d6d09

271
deploy.sh
View File

@@ -4,8 +4,15 @@
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
# Конфигурация
REPO_URL="https://git.tvstart.ru/ychernenko/RFB.git"
TARGET_DIR="/root/RFB"
SERVICE_NAME="rfb-data.service"
TARGET_ENV="/mnt/rfb/.env"
show_help() { show_help() {
echo "Использование: $0 -t <домашняя команда> -r <релиз> [-l <лига>]" echo "Использование: $0 -t <домашняя команда> -r <релиз> [-l <лига>]"
echo " -t Домашняя команда" echo " -t Домашняя команда"
@@ -33,13 +40,41 @@ log_error() {
echo -e "${RED}[ERROR]${NC} $1" >&2 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() { install_packages() {
log_info "Обновление списка пакетов..." log_info "Обновление списка пакетов..."
apt-get update if ! apt-get update; then
log_error "Ошибка при обновлении списка пакетов"
exit 1
fi
log_info "Установка необходимых пакетов..." 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 if ! command -v python3 &> /dev/null; then
@@ -58,33 +93,37 @@ install_packages() {
# Функция загрузки кода # Функция загрузки кода
download_code() { download_code() {
local repo_url="https://git.tvstart.ru/ychernenko/RFB.git"
local release="$1" local release="$1"
local target_dir="/root/RFB" local target_dir="$TARGET_DIR"
log_info "Создание рабочей директории $target_dir..." log_info "Создание рабочей директории $target_dir..."
mkdir -p $target_dir mkdir -p "$target_dir"
if [ -d "$target_dir/.git" ]; then if [ -d "$target_dir/.git" ]; then
log_info "Обновление существующего репозитория..." log_info "Обновление существующего репозитория..."
cd $target_dir cd "$target_dir" || exit 1
git fetch --all git fetch --all
git checkout $release if ! git checkout "$release"; then
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 "Не удалось переключиться на релиз $release"
log_error "Доступные ветки:" log_info "Доступные ветки:"
git branch -r git branch -r
exit 1 exit 1
fi fi
git pull origin "$release"
else
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)" log_info "Код успешно загружен (релиз: $release)"
log_info "Текущая ветка: $(git branch --show-current)" log_info "Текущая ветка: $(git branch --show-current)"
@@ -93,11 +132,20 @@ download_code() {
# Функция настройки виртуального окружения # Функция настройки виртуального окружения
setup_venv() { setup_venv() {
local target_dir="/root/RFB" local target_dir="$TARGET_DIR"
cd $target_dir cd "$target_dir" || exit 1
# Удаляем существующее виртуальное окружение для чистоты
if [ -d ".venv" ]; then
log_info "Удаление существующего виртуального окружения..."
rm -rf .venv
fi
log_info "Создание виртуального окружения..." log_info "Создание виртуального окружения..."
python3 -m venv .venv if ! python3 -m venv .venv; then
log_error "Не удалось создать виртуальное окружение"
exit 1
fi
if [ ! -f ".venv/bin/activate" ]; then if [ ! -f ".venv/bin/activate" ]; then
log_error "Не удалось создать виртуальное окружение" log_error "Не удалось создать виртуальное окружение"
@@ -107,44 +155,63 @@ setup_venv() {
log_info "Активация виртуального окружения и установка зависимостей..." log_info "Активация виртуального окружения и установка зависимостей..."
source .venv/bin/activate source .venv/bin/activate
# Обновление pip # Обновление pip3
pip install --upgrade pip if ! pip3 install --upgrade pip3; then
log_warn "Не удалось обновить pip3"
fi
# Проверка наличия requirements.txt # Проверка наличия requirements.txt
if [ -f "requirements.txt" ]; then if [ -f "requirements.txt" ]; then
log_info "Установка зависимостей из requirements.txt..." log_info "Установка зависимостей из requirements.txt..."
if pip install -r requirements.txt; then if pip3 install -r requirements.txt; then
log_info "Все зависимости успешно установлены" log_info "Все зависимости успешно установлены"
else else
log_error "Ошибка при установке зависимостей из requirements.txt" log_error "Ошибка при установке зависимостей из requirements.txt"
log_warn "Попытка установки базовых зависимостей..." exit 1
pip install requests pandas numpy
fi fi
else else
log_warn "Файл requirements.txt не найден, устанавливаем базовые зависимости..." log_warn "Файл requirements.txt не найден, устанавливаем базовые зависимости..."
pip install requests pandas numpy if ! pip3 install requests pandas numpy fastapi uvicorn python-telegram-handler python-dotenv; then
log_error "Ошибка при установке базовых зависимостей"
exit 1
fi
fi fi
# Проверка основных пакетов # Проверка основных пакетов
log_info "Проверка установки основных пакетов..." log_info "Проверка установки основных пакетов..."
python -c " if ! python -c "
try: try:
import requests, pandas, numpy import requests, pandas, numpy
print('✓ Все основные пакеты успешно импортируются') print('✓ Все основные пакеты успешно импортируются')
except ImportError as e: except ImportError as e:
print(f'✗ Ошибка импорта: {e}') print(f'✗ Ошибка импорта: {e}')
exit(1) exit(1)
" "; then
log_error "Ошибка при проверке пакетов"
exit 1
fi
log_info "Установленные пакеты:" log_info "Установленные пакеты:"
pip list --format=columns pip3 list --format=columns
} }
# Функция создания systemd сервиса # Функция создания systemd сервиса
create_systemd_service() { create_systemd_service() {
log_info "Создание systemd сервиса"
local team="$1" local team="$1"
local league="$2" local league="$2"
# Останавливаем и отключаем старый сервис если он есть
if systemctl is-active --quiet "$SERVICE_NAME"; then
log_info "Остановка $SERVICE_NAME..."
systemctl stop "$SERVICE_NAME"
fi
if systemctl is-enabled --quiet "$SERVICE_NAME"; then
log_info "Отключение $SERVICE_NAME..."
systemctl disable "$SERVICE_NAME"
fi
log_info "Создание systemd сервиса для команды: $team" log_info "Создание systemd сервиса для команды: $team"
if [ -n "$league" ]; then if [ -n "$league" ]; then
log_info "Лига: $league" log_info "Лига: $league"
@@ -162,30 +229,45 @@ create_systemd_service() {
fi fi
# Формируем команду для data сервиса # Формируем команду для data сервиса
local data_command="/root/RFB/.venv/bin/python3 /root/RFB/get_data.py --team \"$team\"" local data_command="python3 $TARGET_DIR/get_data.py --team \"$team\""
if [ -n "$league" ]; then if [ -n "$league" ]; then
data_command="$data_command --league \"$league\"" data_command="$data_command --league \"$league\""
fi fi
# Создаем сервисный файл в правильной директории log_info "Создание файла сервиса: $SERVICE_NAME"
local data_service_file="/etc/systemd/system/rfb-data.service" # Формируем команду для data сервиса
local data_service_file="/etc/systemd/system/$SERVICE_NAME"
log_info "Создание файла сервиса: $data_service_file" log_info "Создание файла сервиса: $data_service_file"
cat > "$data_service_file" << EOF cat > "$data_service_file" << EOF
[Unit] [Unit]
Description=RFB Data Service Description=KHL Data Service
Documentation=https://git.tvstart.ru/ychernenko/RFB
After=network.target After=network.target
Wants=network.target
[Service] [Service]
Type=simple Type=simple
User=root User=root
WorkingDirectory=/root/RFB WorkingDirectory=$TARGET_DIR
Environment=PATH=/root/RFB/.venv/bin Environment=PATH=$TARGET_DIR/.venv/bin
EnvironmentFile=$TARGET_ENV
ExecStart=$data_command ExecStart=$data_command
Restart=always
RestartSec=30 # Лимиты ресурсов
MemoryMax=1G
CPUQuota=80%
# Логирование
StandardOutput=journal StandardOutput=journal
StandardError=journal StandardError=journal
SyslogIdentifier=RFB
# Поведение при перезапуске
Restart=always
RestartSec=10
StartLimitInterval=300
StartLimitBurst=5
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
@@ -195,38 +277,15 @@ EOF
chmod 644 "$data_service_file" chmod 644 "$data_service_file"
log_info "Перезагрузка systemd демона..." log_info "Перезагрузка systemd демона..."
systemctl daemon-reload if ! systemctl daemon-reload; then
log_error "Ошибка при перезагрузке systemd демона"
log_info "Включение сервиса rfb-data.service..."
systemctl enable rfb-data.service
}
# Функция проверки файлов
check_required_files() {
local target_dir="/root/RFB"
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 exit 1
fi fi
log_info "Все необходимые файлы присутствуют" log_info "Включение сервиса $SERVICE_NAME..."
if ! systemctl enable "$SERVICE_NAME"; then
# Дополнительная проверка на исполняемость Python файла log_error "Ошибка при включении сервиса"
if ! python3 -c "import ast; ast.parse(open('get_data.py').read())" 2>/dev/null; then exit 1
log_warn "Файл get_data.py содержит синтаксические ошибки Python"
fi fi
} }
@@ -325,30 +384,42 @@ manage_services() {
case $action in case $action in
"start") "start")
log_info "Запуск сервиса rfb-data.service..." log_info "Запуск сервиса $SERVICE_NAME..."
systemctl start rfb-data.service if ! systemctl start "$SERVICE_NAME"; then
log_error "Ошибка при запуске сервиса"
return 1
fi
;; ;;
"restart") "restart")
log_info "Перезапуск сервиса rfb-data.service..." log_info "Перезапуск сервиса $SERVICE_NAME..."
systemctl restart rfb-data.service if ! systemctl restart "$SERVICE_NAME"; then
log_error "Ошибка при перезапуске сервиса"
return 1
fi
;; ;;
"stop") "stop")
log_info "Остановка сервиса rfb-data.service..." log_info "Остановка сервиса $SERVICE_NAME..."
systemctl stop rfb-data.service if ! systemctl stop "$SERVICE_NAME"; then
log_error "Ошибка при остановке сервиса"
return 1
fi
;; ;;
esac esac
# Даем время сервису на запуск/остановку # Даем время сервису на запуск/остановку
sleep 3 sleep 3
return 0
} }
# Функция проверки статуса сервиса # Функция проверки статуса сервиса
check_service_status() { check_service_status() {
log_info "Статус сервиса rfb-data.service:" log_info "Статус сервиса $SERVICE_NAME:"
if systemctl is-active rfb-data.service; then if systemctl is-active "$SERVICE_NAME" &>/dev/null; then
systemctl status rfb-data.service --no-pager -l systemctl status "$SERVICE_NAME" --no-pager -l
return 0
else else
log_warn "Сервис rfb-data.service не запущен" log_warn "Сервис $SERVICE_NAME не запущен"
return 1
fi fi
} }
@@ -375,9 +446,20 @@ check_system() {
log_info "Оперативная память: $((total_mem / 1024)) MB" log_info "Оперативная память: $((total_mem / 1024)) MB"
} }
# Функция очистки при прерывании
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() { main() {
local team="" local team="" # переменная для команды
local release="main" # значение по умолчанию local release="main" # значение по умолчанию
local league="" # переменная для лиги local league="" # переменная для лиги
@@ -415,6 +497,9 @@ main() {
# Проверка системы # Проверка системы
check_system check_system
# Проверка зависимостей
check_dependencies
# Установка пакетов # Установка пакетов
install_packages install_packages
@@ -427,7 +512,7 @@ main() {
# Настройка виртуального окружения # Настройка виртуального окружения
setup_venv setup_venv
# Определение команды - ТЕПЕРЬ БЕЗ временного файла # Определение команды
final_team=$(detect_team "$team") final_team=$(detect_team "$team")
log_info "Финальная команда: '$final_team'" log_info "Финальная команда: '$final_team'"
@@ -449,7 +534,12 @@ main() {
log_info "Настройка завершена!" log_info "Настройка завершена!"
# Запуск сервиса # Запуск сервиса
manage_services "start" if manage_services "start"; then
log_info "Сервис успешно запущен"
else
log_error "Не удалось запустить сервис"
exit 1
fi
# Проверка статуса # Проверка статуса
check_service_status check_service_status
@@ -461,29 +551,28 @@ main() {
log_info "==================================================" log_info "=================================================="
log_info "Установка завершена успешно!" log_info "Установка завершена успешно!"
log_info "Релиз: $release"
log_info "Рабочая директория: $TARGET_DIR"
log_info "Команда: $final_team" log_info "Команда: $final_team"
if [ -n "$league" ]; then if [ -n "$league" ]; then
log_info "Лига: $league" log_info "Лига: $league"
fi fi
log_info "Режим: $release"
log_info "" log_info ""
log_info "Для просмотра логов:" log_info "Для просмотра логов:"
log_info " journalctl -u rfb-data.service -f" log_info " journalctl -u $SERVICE_NAME -f"
log_info " journalctl -t KHL -f"
log_info "" log_info ""
log_info "Управление сервисом:" log_info "Управление сервисом:"
log_info " Перезапуск: systemctl restart rfb-data.service" log_info " Перезапуск: systemctl restart $SERVICE_NAME"
log_info " Остановка: systemctl stop rfb-data.service" log_info " Остановка: systemctl stop $SERVICE_NAME"
log_info " Статус: systemctl status rfb-data.service" log_info " Статус: systemctl status $SERVICE_NAME"
log_info " Логи: journalctl -u rfb-data.service" log_info " Логи: journalctl -u $SERVICE_NAME"
log_info "" log_info ""
log_info "Проверка работы:" log_info "Проверка работы:"
log_info " Проверить процессы: ps aux | grep get_data.py" log_info " Проверить процессы: ps aux | grep get_data.py"
log_info " Проверить логи: tail -f /root/RFB/logs/*.log 2>/dev/null || echo 'Директория логов не найдена'" log_info " Проверить логи: tail -f $TARGET_DIR/logs/*.log 2>/dev/null || echo 'Директория логов не найдена'"
log_info "==================================================" log_info "=================================================="
} }
# Обработка прерывания
trap 'log_error "Прервано пользователем"; exit 1' INT TERM
# Запуск основной функции # Запуск основной функции
main "$@" main "$@"