Программирование с ИИ
ENRU
5.8

Базовый деплой

чтобы работало без тебя и переживало перезагрузку

Что это

Деплой — вынести код туда, где он работает постоянно: на сервер, а не на твоём ноутбуке с открытым терминалом.

Статья даёт минимум, которого хватает для бота или небольшого сервиса. Не Kubernetes и не облачные платформы — простая схема, которую можно понять целиком и починить руками.

Как выглядит в коде

Что должно быть готово до переноса

ГотовоЗачем
requirements.txt актуаленчтобы поставить то же самое (статья 5.6)
Секреты из окружениячтобы не тащить .env в репозиторий (5.7)
.gitignore настроенчтобы не уехало лишнее
Код в gitчтобы обновлять git pull, а не копированием файлов
Логи через loggingиначе на сервере не узнаешь, что случилось (4.2)

Если хоть одного пункта нет, деплой превратится в отладку вслепую.

Перенос

git clone <адрес> /opt/weather-bot
cd /opt/weather-bot
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt

Секреты создаются на сервере отдельно, руками:

nano .env          # вписать BOT_TOKEN
chmod 600 .env     # читать может только владелец

Автозапуск

Запущенный в терминале процесс умрёт, когда ты закроешь ssh. Нужно, чтобы система запускала его сама — и перезапускала после падения и перезагрузки. В Linux для этого есть systemd.

Файл /etc/systemd/system/weather-bot.service:

[Unit]
Description=Weather bot
After=network.target

[Service]
WorkingDirectory=/opt/weather-bot
EnvironmentFile=/opt/weather-bot/.env
ExecStart=/opt/weather-bot/.venv/bin/python bot.py
Restart=always
RestartSec=5
User=botuser

[Install]
WantedBy=multi-user.target

Построчно:

  • WorkingDirectory — папка, из которой запускается; относительные пути в коде считаются отсюда;
  • EnvironmentFile — откуда взять переменные окружения, то есть секреты;
  • ExecStart — полный путь к Python из виртуального окружения, не системный;
  • Restart=always + RestartSec=5 — перезапускать при падении, с паузой в пять секунд;
  • User — от чьего имени работает; не root.

Команды:

sudo systemctl daemon-reload          # перечитать файлы служб
sudo systemctl enable weather-bot     # запускать при загрузке
sudo systemctl start weather-bot      # запустить сейчас
sudo systemctl status weather-bot     # как дела
sudo journalctl -u weather-bot -f     # смотреть логи вживую

Последняя команда — основная при отладке на сервере. Она и есть замена print на боевой машине.

Обновление

cd /opt/weather-bot
git pull
.venv/bin/pip install -r requirements.txt
sudo systemctl restart weather-bot
sudo journalctl -u weather-bot -n 50

Четыре команды плюс проверка логов. Последняя строка обязательна: обновление без проверки — это деплой вслепую.

Как сказать ИИ

Запрос
Составь systemd-юнит для этого проекта. Путь /opt/weather-bot,
запуск bot.py из .venv, секреты из .env, перезапуск при падении,
не от root. Объясни каждую строку.
Запрос
Бот перезапускается каждые несколько секунд. Вот вывод
journalctl за последнюю минуту. Что происходит?

<лог>
Запрос
Напиши скрипт обновления: git pull, зависимости, перезапуск,
показать последние 50 строк лога. Если git pull ничего
не подтянул — ничего не делать.

На что смотреть

.env на сервере отсутствует. Служба стартует и сразу падает. В логах — то самое понятное сообщение из статьи 5.7, если оно написано.

Системный Python вместо .venv. В ExecStart указан /usr/bin/python3 — библиотек проекта там нет.

Относительные пути. Код открывает data/bot.db, а служба запущена из другой папки. Отсюда WorkingDirectory.

Запуск от root. Ошибка в коде получает права на всю систему. Отдельный пользователь — пять минут работы.

Нет ротации логов. journalctl сам ограничивает размер, а вот логи в собственный файл растут бесконечно, пока не кончится диск.

Обновление копированием файлов. Через месяц на сервере не та версия, что в git, и никто не знает какая.

Шпаргалка

  • До переноса: requirements, секреты из окружения, .gitignore, git, логи.

  • Секреты создаются на сервере руками, chmod 600.

  • systemd: WorkingDirectory, EnvironmentFile, полный путь к .venv, Restart=always, не root.

  • Логи: journalctl -u <служба> -f.

  • Обновление: git pull → зависимости → restart → посмотреть логи.

  • Restart=always прячет падения: проверяй логи, а не наличие процесса.