语境
Ubuntu 22.04 桌面:MQTT 服务器
目标:将 python(paho with logger)脚本作为服务运行
.py 按预期记录常规测试(不在 venv 中):
python3 mqtt2log.py
脚本的第 6 行是:import paho.mqtt.client as mqtt
.service 文件被复制到 /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
观察
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'.
错误消息似乎表明在第 6 行找不到 paho 模块: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
问题是
pip
。您的依赖项 -paho-mqtt
- 在通过 安装时pip
只会安装在您的用户空间或安装到 中,venv
因为它无法写入系统。但是,由于PEP 668(目前似乎仅在 Ubuntu 24.04 及更高版本的 Python 3.12 上启用),
pip
将无法安装到外部管理环境中(即 Ubuntu 系统上的系统 Python)。您可能会遇到这种情况,在这种情况下,您应该创建一个专用的venv
,然后使用 Python 可执行文件的完整路径调用 Python 脚本,以便它知道要使用venv
哪个(在运行时设置它)PYTHON_ROOT
venv
我的建议是为
venv
您的应用程序制作一个专用的,然后您的系统直接使用可执行文件的完整路径调用 Python 可执行文件和文件venv
。例如,如果您的服务的工作目录是,
/opt/myservice/
您可以执行以下操作:...然后在您的服务执行行(假设是 SystemD)中,您将拥有:
从而直接从 venv 的 Python 调用服务的脚本等。
确保所有文件、
venv
等的所有权都属于您的服务运行的用户和组!如果您绝对想忽略 PEP 668,并引入保护措施有意试图保护您免受的潜在系统/模块冲突,请认识到,按照以下说明操作,您将面临损坏系统包等的风险。这样做意味着您接受所有风险!
在 Ubuntu 中 Python 3.12 之前的版本中,您可以运行以下命令在系统级别安装您选择的模块:
在 Python 3.12 及更高版本中,你必须执行以下操作:
请注意,这样做将导致您破坏系统 Python 或与系统已安装的软件包发生冲突的所有风险。
通过 运行的作业
cron
(或启动脚本或systemd
脚本)不会在桌面上的同一运行时环境中运行。启动脚本以 的形式运行root
。您的任何PATH
更改或其他环境变量设置~/.bashrc
都不会自动传播到您的cron
作业。例如,没有$DISPLAY
,因此 GUI 程序需要特殊处理(阅读man xhost
)。cron
人们可以在crontab
文件 Read中为所有工作设置环境变量man 5 crontab
。echo "=== id ===";id;echo "=== set ===";set;echo "=== env ===";env | sort;echo "=== alias ===";alias
查看每个环境中的结果 。一种简单的方法是将命令存储在
bash
脚本中,并从终端会话中执行该脚本,保存输出,然后从“其他”环境执行该脚本,保存输出。使用比较保存的输出diff
。由于
command
该行的一部分crontab
默认由 解释/bin/sh
,其语法比 更简单/bin/bash
,因此我建议调用command
一个bash
脚本(可执行、已安装、以 开头#!/bin/bash
)来设置环境,然后调用所需的程序。