Вопрос или проблема
КОНТЕКСТ
-
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'
-
Почему модуль paho не найден?
-
Какие шаги по диагностике можно предпринять?
Я озадачен тем, что 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
), либо он находится в виртуальном окружении, которое не активировано при запуске скрипта через сервис.
Применение
-
Установите модуль глобально: Убедитесь, что
paho-mqtt
доступен всей системе. Запустите:sudo pip3 install paho-mqtt
Однако, использование
pip
сsudo
может привести к потенциальным проблемам, связанных с совместимостью версий и конфликтами. Рекомендуется использовать системные пакеты, если это возможно. -
Используйте виртуальное окружение: Если вы предпочитаете изолированное окружение для работы с 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
-
Проверка переменных среды: Иногда проблема может заключаться в отсутствии необходимых переменных среды, когда скрипт запускается от имени
systemd
. Вы можете создать скрипт для вывода всех переменных среды и сравнить их между двумя сценариями — при запуске вручную и черезsystemd
.# environment-check.sh #!/bin/bash echo "=== id ==="; id echo "=== env ==="; env | sort
Запустите этот скрипт в обоих случаях и сравните вывод для поиска различий.
-
Настройте права доступа и сеансы: Убедитесь, что у
systemd
есть все права для выполнения вашего скрипта и что все необоходимые зависимости правильно установлены для доступа из системного сеанса. -
Переустановка пакетов: Если проблема продолжает возникать, попробуйте удалить и переустановить модули. Убедитесь, что все зависимости актуальны и корректно запустите установку:
pip uninstall paho-mqtt sudo pip3 install paho-mqtt
-
Отладка ошибок
systemd
: Используйте команды для детальной отладки и отображения журналов сервисов:journalctl -u mqtt2log.service
Если вы выполните все шаги выше и проблема не будет решена, возможно, стоит рассмотреть дополнительную диагностику и консультации с сообществом, где можно будет предоставить больше контекста и специфики вашего окружения.