feat: add bot control script to prevent multiple instances
Some checks reported errors
continuous-integration/drone/push Build encountered an error
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:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -57,4 +57,4 @@ venv.bak/
|
|||||||
|
|
||||||
# Системные файлы
|
# Системные файлы
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db.bot.pid
|
||||||
|
|||||||
151
BOT_MANAGEMENT.md
Normal file
151
BOT_MANAGEMENT.md
Normal 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
|
||||||
|
```
|
||||||
16
Makefile
16
Makefile
@@ -68,6 +68,22 @@ run:
|
|||||||
@echo "🚀 Запуск бота..."
|
@echo "🚀 Запуск бота..."
|
||||||
. .venv/bin/activate && python main.py
|
. .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:
|
migration:
|
||||||
@echo "📄 Создание новой миграции..."
|
@echo "📄 Создание новой миграции..."
|
||||||
|
|||||||
125
bot_control.sh
Executable file
125
bot_control.sh
Executable 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
|
||||||
Reference in New Issue
Block a user