скрипт python не запускается в сервисе

Вопрос или проблема

КОНТЕКСТ

  • Ubuntu 22.04 Desktop: MQTT сервер

  • Цель: запуск python (paho с логгером) скрипта в качестве службы

  • Тесты логирования .py работают как ожидалось (не в venv):

python3 mqtt2log.py

строка 6 скрипта: import paho.mqtt.client as mqtt

Файл .service копируется в /etc/system/system:

# запуск python скрипта как службы
# https://unix.stackexchange.com/a/634422/182280e
# скопируйте это описание .service в /etc/systemd/system/myscript.service
# /home/user/mqtt2log.py

[Unit]
Description=mqtt2log.py

[Service]
ExecStart=/usr/bin/python3 /home/user/mqtt/mqtt2log.py

[Install]
WantedBy=multi-user.target

НАБЛЮДЕНИЯ

ls -l /etc/systemd/system/mqtt2log.service возвращает:

-rwxrwxrwx 1 root root 314 Jan 11 17:41 /etc/systemd/system/mqtt2log.service

sudo systemctl status mqtt2log возвращает:

Jan 31 13:01:30 mqtt systemd[1]: Started mqtt2log.py.
Jan 31 13:01:30 mqtt python3[158388]: Traceback (most recent call last):
Jan 31 13:01:30 mqtt python3[158388]:   File "/home/user/mqtt/mqtt2log.py", line 6, in <module>
Jan 31 13:01:30 mqtt python3[158388]:     import paho.mqtt.client as mqtt
Jan 31 13:01:30 mqtt python3[158388]: ModuleNotFoundError: No module named 'paho'
Jan 31 13:01:30 mqtt systemd[1]: mqtt2log.service: Main process exited, code=exited, status=1/FAILURE
Jan 31 13:01:30 mqtt systemd[1]: mqtt2log.service: Failed with result 'exit-code'.

Сообщения об ошибках, похоже, указывают на то, что модуль paho не может быть найден в строке 6: import paho.mqtt.client as mqtt

ВОПРОСЫ

Возвращаемая ошибка: ModuleNotFoundError: No module named 'paho'

  1. Почему модуль paho не найден?

  2. Какие шаги по диагностике можно предпринять?

Я озадачен тем, что python скрипт запускается из командной строки. Возможно, это как-то связано с правами доступа?

УСТАНОВКА MQTT / Paho

sudo apt update
sudo apt-get install mosquitto
sudo vi /etc/mosquitto/mosquitto.conf 
    allow_anonymous true
    listener 1883
sudo systemctl restart mosquitto
sudo apt install python3-pip
pip3 install paho-mqtt
sudo apt install -y mosquitto-clients

Задания, выполненные через cron (или скрипты запуска, или скрипты systemd), не выполняются в той же среде выполнения, которую вы используете на своем рабочем столе. Скрипты запускаются от имени root. Ни одна из ваших изменений PATH или других настроек переменных окружения из ~/.bashrc не распространяется автоматически на ваши задания cron. Например, нет $DISPLAY, поэтому программы с графическим интерфейсом требуют специального подхода (читайте man xhost).

Можно установить переменные окружения для всех своих заданий cron в файле crontab. Читайте man 5 crontab.

Посмотрите результаты команды echo "=== id ===";id;echo "=== set ===";set;echo "=== env ===";env | sort;echo "=== alias ===";alias в каждой из ваших сред.
Простой способ — сохранить команды в скрипте bash и выполнить его из сеанса терминала, сохраняя вывод, затем выполнить скрипт в «другой» среде, сохраняя вывод. Сравните сохраненные выводы, используя diff.

#!/bin/bash
echo "=== id ===";id
echo "=== set ===";set
echo "=== env ===";env | sort
echo "=== alias ===";alias`

Так как часть command строки crontab по умолчанию интерпретируется /bin/sh, который имеет более простую синтаксис по сравнению с /bin/bash, я рекомендую, чтобы command было вызовом скрипта bash (исполняемого, смонтированного, начинается с #!/bin/bash), который настраивает окружение, а затем вызывает нужную программу.

Проблема в pip. Ваша зависимость – paho-mqtt – при установке через pip будет установлена только в пользовательском пространстве или в venv, потому что она не может записать в систему.

Если вы намерены установить это на уровне всей системы, вам нужно выполнить sudo pip3 install paho-mqtt.

Однако, из-за PEP 668 (и это включено только в Python 3.12 в Ubuntu 24.04 и позже, по-видимому, в настоящее время), pip НЕ будет устанавливать в управляемую извне среду (т.е. системный Python в системах Ubuntu). Вы можете столкнуться с этой проблемой, в таком случае вам следует создать выделенный venv, а затем вызвать Python скрипт с полным путем к исполняемому файлу Python venv, чтобы знать, какой PYTHON_ROOT использовать (env устанавливает это во время выполнения).

Ответ или решение

Теория

В среде Linux для автоматизации задач и управления сервисами часто используют системный менеджер systemd. В вашем случае задача заключается в запуске Python-скрипта как сервиса на Ubuntu 22.04 Desktop, который выступает MQTT-сервером. Однако проблема, с которой вы столкнулись, связана с невозможностью загрузки модуля paho-mqtt, который отвечает за работу с MQTT в вашем скрипте.

Ошибки, подобные ModuleNotFoundError, обычно возникают из-за проблем с конфигурацией среды выполнения. Когда скрипт запускается напрямую из командной строки вашим пользователем, он использует специфическую для пользователя среду, включая пути к библиотекам и установленным модулям. Когда же скрипт запускается через systemd, он использует среду, настроенную для системного пользователя, в данном случае — root. Именно здесь и лежит корень проблемы.

Пример

Рассмотрим пример. Вы установили paho-mqtt с помощью pip, и данный модуль доступен, когда скрипт запускается напрямую из командной строки. Однако, при запуске через systemd модуль становится недоступным. Это может происходить, если модуль установлен в пользовательском пространстве (--user), либо он находится в виртуальном окружении, которое не активировано при запуске скрипта через сервис.

Применение

  1. Установите модуль глобально: Убедитесь, что paho-mqtt доступен всей системе. Запустите:

    sudo pip3 install paho-mqtt

    Однако, использование pip с sudo может привести к потенциальным проблемам, связанных с совместимостью версий и конфликтами. Рекомендуется использовать системные пакеты, если это возможно.

  2. Используйте виртуальное окружение: Если вы предпочитаете изолированное окружение для работы с Python, создайте виртуальное окружение и установите все необходимые модули в него.

    cd /home/user/mqtt
    python3 -m venv venv
    source venv/bin/activate
    pip install paho-mqtt

    Затем измените ваш .service файл, чтобы ExecStart указывал на Python из вашего виртуального окружения:

    [Service]
    ExecStart=/home/user/mqtt/venv/bin/python /home/user/mqtt/mqtt2log.py
  3. Проверка переменных среды: Иногда проблема может заключаться в отсутствии необходимых переменных среды, когда скрипт запускается от имени systemd. Вы можете создать скрипт для вывода всех переменных среды и сравнить их между двумя сценариями — при запуске вручную и через systemd.

    # environment-check.sh
    #!/bin/bash
    echo "=== id ==="; id
    echo "=== env ==="; env | sort

    Запустите этот скрипт в обоих случаях и сравните вывод для поиска различий.

  4. Настройте права доступа и сеансы: Убедитесь, что у systemd есть все права для выполнения вашего скрипта и что все необоходимые зависимости правильно установлены для доступа из системного сеанса.

  5. Переустановка пакетов: Если проблема продолжает возникать, попробуйте удалить и переустановить модули. Убедитесь, что все зависимости актуальны и корректно запустите установку:

    pip uninstall paho-mqtt
    sudo pip3 install paho-mqtt
  6. Отладка ошибок systemd: Используйте команды для детальной отладки и отображения журналов сервисов:

    journalctl -u mqtt2log.service

Если вы выполните все шаги выше и проблема не будет решена, возможно, стоит рассмотреть дополнительную диагностику и консультации с сообществом, где можно будет предоставить больше контекста и специфики вашего окружения.

Оцените материал
Добавить комментарий

Капча загружается...