CONTEXTO
Ubuntu 22.04 Desktop: servidor MQTT
Objetivo: executar script python (paho com logger) como um serviço
A rotina de registro .py testa conforme o esperado (não em um venv):
python3 mqtt2log.py
a linha 6 do script é:import paho.mqtt.client as mqtt
Um arquivo .service é copiado para /etc/system/system:
# run python script as service
# https://unix.stackexchange.com/a/634422/182280e
# copy this .service description to /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
OBSERVAÇÕES
ls -l /etc/systemd/system/mqtt2log.service
retorna:
-rwxrwxrwx 1 root root 314 Jan 11 17:41 /etc/systemd/system/mqtt2log.service
sudo systemctl status mqtt2log
retorna:
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'.
As mensagens de erro parecem indicar que o módulo paho não pode ser encontrado na linha 6:import paho.mqtt.client as mqtt
QUESTÕES
Erro retornado:ModuleNotFoundError: No module named 'paho'
Por que o módulo paho não foi encontrado?
Que medidas de diagnóstico podem ser tomadas?
Estou intrigado com o fato de que o script python roda a partir da linha de comando. Talvez isso seja de alguma forma um problema de permissões?
MQTT / Paho INSTALAR
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
O problema é
pip
. Sua dependência -paho-mqtt
- quando instalada viapip
só será instalada no seu espaço de usuário ou em umvenv
porque não pode gravar no sistema.No entanto, devido ao PEP 668 (e somente habilitado no Python 3.12 no Ubuntu 24.04 e posterior, ao que parece, atualmente),
pip
NÃO será instalado em um ambiente gerenciado externamente (também conhecido como Python do sistema em sistemas Ubuntu). Você pode se deparar com isso, nesse caso você deve criar um dedicadovenv
e então chamar o script Python com o caminho completo para ovenv
executável Python do para que ele saiba qualPYTHON_ROOT
usar (ovenv
define isso em tempo de execução)Minha sugestão seria criar um dedicado
venv
para seu aplicativo e, então, seu sistema chamar o executável Python e o arquivo diretamente com o caminho completo para o executável novenv
.Por exemplo, se o seu diretório de trabalho para o seu serviço for,
/opt/myservice/
você faria:... e então na sua linha de execução de serviço (assumindo SystemD), você teria:
e assim chamar diretamente os scripts do serviço, etc. do Python do venv.
Certifique-se de que a propriedade de todos os arquivos,
venv
etc., seja do usuário e grupo em que o serviço é executado!Se você realmente quiser ignorar o PEP 668 e introduzir os potenciais conflitos de sistema/módulo dos quais as proteções estão intencionalmente tentando protegê-lo , reconheça que você corre o risco de danificar seus pacotes de sistema, etc. ao seguir as próximas instruções. Você aceita todos os riscos em si mesmo ao fazer isso!
Em versões do Python anteriores à 3.12 no Ubuntu, você pode executar isto para instalar o módulo de sua escolha no nível do sistema:
No Python 3.12 e versões posteriores, você precisa fazer isto:
Observe que você assume todos os riscos de danificar o Python do seu sistema ou de introduzir conflitos com os pacotes instalados no seu sistema ao fazer isso.
Os trabalhos executados por meio de
cron
(ou scripts de inicialização, ousystemd
scripts), não são executados no mesmo ambiente de tempo de execução que você tem em seu desktop. Os scripts de inicialização são executados comoroot
. Nenhuma de suasPATH
alterações, ou outras configurações de variáveis de ambiente de~/.bashrc
são propagadas automaticamente para seucron
trabalho. Por exemplo, não há$DISPLAY
, então os programas de GUI precisam de tratamento especial (leiaman xhost
).É possível definir variáveis de ambiente para todos os
cron
trabalhos nocrontab
arquivo Readman 5 crontab
.Veja os resultados de
echo "=== id ===";id;echo "=== set ===";set;echo "=== env ===";env | sort;echo "=== alias ===";alias
em cada um dos seus ambientes.Uma maneira fácil é armazenar os comandos em um
bash
script e executá-lo a partir da sua sessão de terminal, salvando a saída, então, executar o script a partir do "outro" ambiente, salvando a saída. Compare as saídas salvas usandodiff
.Como a
command
parte dacrontab
linha é, por padrão, interpretada por/bin/sh
, que tem uma sintaxe mais simples que/bin/bash
, recomendo que hajacommand
uma chamada para umbash
script (executável, montado, que começa com#!/bin/bash
) que configura o ambiente e, em seguida, chama o programa desejado.