feat: add bot control script to prevent multiple instances
Some checks reported errors
continuous-integration/drone/push Build encountered an error

- Add bot_control.sh script for safe bot management
- Prevent 'Conflict: terminated by other getUpdates' error
- Add Makefile commands: bot-start, bot-stop, bot-restart, bot-status, bot-logs
- Add BOT_MANAGEMENT.md with usage instructions
- Use PID file to track single bot instance
- Auto-stop all old processes before starting
- Add .bot.pid to .gitignore

Fixes issue where multiple bot instances cause command processing failures
This commit is contained in:
2025-11-17 06:44:43 +09:00
parent d3f9f2fb53
commit 72e95db811
4 changed files with 293 additions and 1 deletions

2
.gitignore vendored
View File

@@ -57,4 +57,4 @@ venv.bak/
# Системные файлы
.DS_Store
Thumbs.db
Thumbs.db.bot.pid

151
BOT_MANAGEMENT.md Normal file
View File

@@ -0,0 +1,151 @@
# 🤖 Управление ботом
## Проблема множественных экземпляров
Если бот перестал реагировать на команды и в логах появляются ошибки:
```
ERROR - TelegramConflictError: Conflict: terminated by other getUpdates request
```
Это означает, что запущено **несколько экземпляров бота одновременно**, и они конфликтуют друг с другом.
## Решение
Используйте скрипт `bot_control.sh` для управления ботом:
### Команды управления через Makefile
```bash
# Запустить бота (остановит все старые процессы)
make bot-start
# Остановить бота
make bot-stop
# Перезапустить бота
make bot-restart
# Проверить статус бота
make bot-status
# Показать логи бота в реальном времени
make bot-logs
```
### Прямое использование скрипта
```bash
# Запуск
./bot_control.sh start
# Остановка
./bot_control.sh stop
# Перезапуск
./bot_control.sh restart
# Статус
./bot_control.sh status
# Логи
./bot_control.sh logs
```
## Что делает скрипт?
1. **bot-start**:
- Проверяет, не запущен ли уже бот
- Останавливает все старые процессы `python main.py`
- Запускает ТОЛЬКО ОДИН экземпляр бота
- Создает PID-файл для отслеживания процесса
2. **bot-stop**:
- Корректно останавливает бот (SIGTERM, затем SIGKILL)
- Удаляет PID-файл
- Проверяет что все процессы остановлены
3. **bot-restart**:
- Останавливает бота
- Запускает заново
4. **bot-status**:
- Показывает состояние бота (работает/не работает)
- Показывает PID и использование ресурсов
- Проверяет логи на ошибки конфликта
- Предупреждает если найдено несколько процессов
5. **bot-logs**:
- Показывает логи бота в реальном времени
- Нажмите Ctrl+C для выхода
## Файлы
- **bot_control.sh** - скрипт управления ботом
- **.bot.pid** - файл с PID текущего процесса бота
- **/tmp/bot_single.log** - логи бота
## Диагностика проблем
### Проверить сколько процессов запущено:
```bash
ps aux | grep "python main.py" | grep -v grep
```
Должна быть **только одна строка**. Если больше - используйте `make bot-restart`.
### Проверить логи на ошибки:
```bash
tail -n 100 /tmp/bot_single.log | grep "ERROR"
```
### Остановить ВСЕ процессы бота вручную:
```bash
pkill -9 -f "python main.py"
```
Затем запустите через `make bot-start`.
## ⚠️ Важно
- **НЕ используйте** `make run` для продакшена - он не контролирует множественные запуски
- **ВСЕГДА используйте** `make bot-start` или `./bot_control.sh start`
- Перед запуском нового экземпляра **всегда проверяйте** статус: `make bot-status`
## Автозапуск при загрузке системы (опционально)
Если нужно автоматически запускать бота при загрузке сервера:
```bash
# Создать systemd service
sudo nano /etc/systemd/system/lottery-bot.service
```
Содержимое файла:
```ini
[Unit]
Description=Lottery Bot
After=network.target postgresql.service
[Service]
Type=simple
User=trevor
WorkingDirectory=/home/trevor/new_lottery_bot
ExecStart=/home/trevor/new_lottery_bot/bot_control.sh start
ExecStop=/home/trevor/new_lottery_bot/bot_control.sh stop
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
```
Активация:
```bash
sudo systemctl daemon-reload
sudo systemctl enable lottery-bot
sudo systemctl start lottery-bot
sudo systemctl status lottery-bot
```

View File

@@ -68,6 +68,22 @@ run:
@echo "🚀 Запуск бота..."
. .venv/bin/activate && python main.py
# Управление ботом через скрипт (безопасный запуск одного экземпляра)
bot-start:
@./bot_control.sh start
bot-stop:
@./bot_control.sh stop
bot-restart:
@./bot_control.sh restart
bot-status:
@./bot_control.sh status
bot-logs:
@./bot_control.sh logs
# Создание миграции
migration:
@echo "📄 Создание новой миграции..."

125
bot_control.sh Executable file
View File

@@ -0,0 +1,125 @@
#!/bin/bash
# Скрипт для управления ботом (запуск/остановка/перезапуск)
BOT_DIR="/home/trevor/new_lottery_bot"
LOG_FILE="/tmp/bot_single.log"
PID_FILE="$BOT_DIR/.bot.pid"
case "$1" in
start)
echo "🚀 Запуск бота..."
cd "$BOT_DIR"
# Проверяем не запущен ли уже
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if ps -p "$PID" > /dev/null 2>&1; then
echo "⚠️ Бот уже запущен (PID: $PID)"
exit 1
fi
fi
# Останавливаем все старые процессы
pkill -9 -f "python main.py" 2>/dev/null
sleep 2
# Запускаем бота
. .venv/bin/activate
nohup python main.py > "$LOG_FILE" 2>&1 &
NEW_PID=$!
echo $NEW_PID > "$PID_FILE"
sleep 3
if ps -p $NEW_PID > /dev/null; then
echo "✅ Бот запущен (PID: $NEW_PID)"
echo "📋 Логи: tail -f $LOG_FILE"
else
echo "❌ Не удалось запустить бота"
rm -f "$PID_FILE"
exit 1
fi
;;
stop)
echo "🛑 Остановка бота..."
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if ps -p "$PID" > /dev/null 2>&1; then
kill -15 "$PID"
sleep 2
if ps -p "$PID" > /dev/null 2>&1; then
kill -9 "$PID"
fi
echo "✅ Бот остановлен"
else
echo "⚠️ Процесс не найден"
fi
rm -f "$PID_FILE"
else
# Останавливаем все процессы python main.py на всякий случай
pkill -9 -f "python main.py" 2>/dev/null
echo "✅ Все процессы остановлены"
fi
;;
restart)
echo "🔄 Перезапуск бота..."
$0 stop
sleep 2
$0 start
;;
status)
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if ps -p "$PID" > /dev/null 2>&1; then
echo "✅ Бот работает (PID: $PID)"
echo "📊 Статистика процесса:"
ps aux | grep "$PID" | grep -v grep
# Проверяем последние ошибки
if grep -q "ERROR.*Conflict" "$LOG_FILE" 2>/dev/null; then
echo "⚠️ В логах обнаружены ошибки конфликта!"
echo "Последние ошибки:"
tail -n 100 "$LOG_FILE" | grep "ERROR.*Conflict" | tail -3
else
echo "✅ Ошибок конфликта не обнаружено"
fi
else
echo "❌ Бот не работает (PID файл существует, но процесс не найден)"
rm -f "$PID_FILE"
fi
else
# Проверяем запущенные процессы
COUNT=$(ps aux | grep "python main.py" | grep -v grep | wc -l)
if [ "$COUNT" -gt 0 ]; then
echo "⚠️ Найдено $COUNT процессов бота (без PID файла)"
ps aux | grep "python main.py" | grep -v grep
else
echo "❌ Бот не запущен"
fi
fi
;;
logs)
if [ -f "$LOG_FILE" ]; then
tail -f "$LOG_FILE"
else
echo "❌ Файл логов не найден: $LOG_FILE"
fi
;;
*)
echo "Использование: $0 {start|stop|restart|status|logs}"
echo ""
echo "Команды:"
echo " start - Запустить бота"
echo " stop - Остановить бота"
echo " restart - Перезапустить бота"
echo " status - Проверить статус бота"
echo " logs - Показать логи бота (Ctrl+C для выхода)"
exit 1
;;
esac
exit 0