Вопрос или проблема
Я хочу запустить python-скрипт, который использует virtualenv, как сервис. Я уже немного исследовал этот вопрос, но не смог найти рабочее решение. Я вставил путь к виртуальной среде python в первую строку python. Сервис выглядит так:
[Unit]
Description=Telegram Bot Service
After=multi-user.target
[email protected]
[Service]
Type=simple
ExecStart=/usr/bin/python3.7 /home/pi/github/python/telegrambot.py
StandardInput=tty-force
[Install]
WantedBy=multi-user.target
Ошибка:
● telegrambot.service - Telegram Bot Service
Loaded: loaded (/lib/systemd/system/telegrambot.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Tue 2020-03-03 15:04:11 GMT; 3s ago
Process: 15090 ExecStart=/usr/bin/python3.7 /home/pi/github/python/telegrambot.py (code=ex
Main PID: 15090 (code=exited, status=1/FAILURE)
Mar 03 15:04:11 raspberrypi systemd[1]: Started Telegram Bot Service.
Mar 03 15:04:11 raspberrypi systemd[1]: telegrambot.service: Main process exited, code=exite
Mar 03 15:04:11 raspberrypi systemd[1]: telegrambot.service: Failed with result 'exit-code'.
Заранее благодарю за любую помощь!
Недавно я столкнулся с этой проблемой и хотел задокументировать её для других. Самый простой способ, который я нашёл, это запустить команду shell и активировать ваш virtualenv вместе со скриптом. Вы можете заменить .venv_path
на местоположение вашей виртуальной среды.
[Unit]
Description=Telegram Bot Service
After=multi-user.target
[email protected]
[Service]
Type=simple
ExecStart=/bin/sh -c ". .venv_path/bin/activate && /home/pi/github/python/telegrambot.py"
StandardInput=tty-force
[Install]
WantedBy=multi-user.target
Ответ или решение
Чтобы запустить Python-скрипт в виртуальной среде (virtualenv) в качестве службы на Linux, вам нужно учесть несколько ключевых моментов, связанных с настройкой unit-файлов systemd. Ниже приведено подробное объяснение, как настроить это правильно.
Теория
Когда вы запускаете Python-скрипт в virtualenv, это обеспечивает изоляцию зависимостей, что критически важно для предотвращения конфликтов с другими проектами. Стандартный подход — активировать среду перед выполнением скрипта. В контексте службы systemd, это требует корректной настройки ExecStart-команды, чтобы включить активацию virtualenv непосредственно перед запуском скрипта.
Пример
Ваша текущая настройка ExecStart вызывает ошибку, потому что она напрямую запускает Python-скрипт, игнорируя активацию virtualenv. Мы можем исправить это следующим образом:
- Откройте файл вашей службы (например,
telegrambot.service
) для редактирования. - Измените секцию
[Service]
следующим образом:
[Service]
Type=simple
ExecStart=/bin/bash -c 'source /path/to/venv/bin/activate && python /home/pi/github/python/telegrambot.py'
StandardInput=tty-force
Обратите внимание на следующее:
- Замените
/path/to/venv
на реальный путь до вашей virtualenv. - Используйте
/bin/bash -c
для выполнения нескольких команд. Это позволяет сначала активировать virtualenv и затем запустить скрипт в этом контексте.
Применение
После того, как вы внесли изменения, выполните следующие шаги:
- Перезагрузите конфигурацию systemd:
sudo systemctl daemon-reload
- Запустите или перезапустите службу:
sudo systemctl start telegrambot.service
Для уверенности, что ваша служба автоматически запускается при загрузке системы, убедитесь, что она включена:
sudo systemctl enable telegrambot.service
Проверка состояния службы поможет выявить возможные ошибки:
sudo systemctl status telegrambot.service
Эта конфигурация гарантирует, что при запуске службы будет использоваться необходимая виртуальная среда, что должно устранить любые ошибки, связанные с зависимостями. Убедитесь, что все зависимости вашего проекта действительно установлены в указанной virtualenv.