尝试使用 systemd 启动 python 脚本,但它在 Raspberry Pi 上不起作用

Posted

技术标签:

【中文标题】尝试使用 systemd 启动 python 脚本,但它在 Raspberry Pi 上不起作用【英文标题】:Trying to launch a python script with systemd but it doesnt work on Raspberry Pi 【发布时间】:2021-03-31 01:46:53 【问题描述】:

它在 Mu 中正常运行,但是当我尝试使用 systemd 运行它时(在 RPI 开启时运行)它不起作用。

这是来自终端的错误


● skateboard.service - skateboard
   Loaded: loaded (/etc/systemd/system/skateboard.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Tue 2021-03-30 21:38:19 EDT; 14s ago
  Process: 467 ExecStart=/usr/bin/python3 /home/pi/Desktop/PythonScripts/skateboard.py (code=exited, status=1/FAILURE)
 Main PID: 467 (code=exited, status=1/FAILURE)

Mar 30 21:38:19 raspberrypi python3[467]: serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?)
Mar 30 21:38:19 raspberrypi python3[467]: During handling of the above exception, another exception occurred:
Mar 30 21:38:19 raspberrypi python3[467]: Traceback (most recent call last):
Mar 30 21:38:19 raspberrypi python3[467]:   File "/home/pi/Desktop/PythonScripts/skateboard.py", line 11, in <module>
Mar 30 21:38:19 raspberrypi python3[467]:     lineString = ser.readline().decode('utf-8').rstrip()
Mar 30 21:38:19 raspberrypi python3[467]:   File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 509, in read
Mar 30 21:38:19 raspberrypi python3[467]:     raise SerialException('read failed: '.format(e))
Mar 30 21:38:19 raspberrypi python3[467]: serial.serialutil.SerialException: read failed: device reports readiness to read but returned no data (device disconnected or multiple access on port?)
Mar 30 21:38:19 raspberrypi systemd[1]: skateboard.service: Main process exited, code=exited, status=1/FAILURE
Mar 30 21:38:19 raspberrypi systemd[1]: skateboard.service: Failed with result 'exit-code'.

如果相关,这里是 python 脚本:

#!/usr/bin/python3.7
import serial

port = "/dev/ttyACM0"
ser = serial.Serial(port, 57600)
shock = 0

while 1:
    while ser.in_waiting:

        lineString = ser.readline().decode('utf-8').rstrip()



        lineInt = float(lineString)
        print(lineInt)

        if(lineInt >= .4):
            shock = 1

        if(shock == 1 and lineInt < 5):

            ser.write(b"Shock!\n")
            print("shock")
            shock = 0

这是 .service 文件

[Unit]
Description=skateboard
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/pi/skateboard.py
Restart=on-abort
User=pi
[Install]
WantedBy=multi-user.target

【问题讨论】:

您好 Alex,您是否禁用了该串行端口上的内核调试?您还可以尝试使您的代码对端口连接处理异常的故障更具弹性。 【参考方案1】:

正如我在上面的评论中所说,我认为问题可能是串行控制台未禁用,并且它吐出的消息干扰了您的程序。所以首先要做的是确保控制台被禁用。完整的过程在here 中进行了解释,但非常简单:只需运行sudo raspi-config 并在菜单上选择Interface Options,然后选择Serial Port。对第一个问题回答 No 以禁用控制台,然后回答 Yes 为您的目的启用端口,重新启动,您就完成了。

接下来您应该确保运行服务的用户 (pi) 是 dialup 组的成员,以便能够访问串行端口。为此,只需运行:

sudo usermod -a -G dialout pi

在命令行上。

取决于您的串行链路的可靠性(这取决于很多因素,例如布线距离、质量等),您可能需要使您的代码更可靠以捕获异常(也许您很幸运并且该端口可以正常工作一段时间,但在某些时候,您的设备可能无法发送数据并且您的服务将崩溃,因此在这种情况下添加异常处理不仅仅是一种好习惯)这样的事情应该可以解决问题:

#!/usr/bin/python3.7
import serial

port = "/dev/ttyACM0"
ser = serial.Serial(port, 57600)
shock = 0

while 1:
    while ser.in_waiting:
        #Handle exception, i.e. serial port not reading anything
        try: 
            lineString = ser.readline().decode('utf-8').rstrip()
            lineInt = float(lineString)
            print(lineInt)

            if(lineInt >= .4):
                shock = 1

            if(shock == 1 and lineInt < 5):

                ser.write(b"Shock!\n")
                print("shock")
                shock = 0

        except serial.serialutil.SerialException:
            print("Something went wrong, no data received!")

【讨论】:

我做了你建议的事情,但它们似乎没有用,但我尝试更改脚本,通过运行和不运行 try: except serial.serialutil.SerialException:,当该部分显示相同的错误不在代码中,所以您认为问题出在 python 脚本或其他方面吗?如果您愿意,我可以显示错误,还有一些可能很高兴知道的相关信息是 RPI 连接到连接到 GPS 模块和继电器的 arduino。所以当 RPI 发送命令时,arduino 会触发继电器。 添加try/except 后仍然显示相同的serial.serialutil.SerialException: device reports readiness to read but returned no data 错误?我认为中间有一个 Arduino 并不重要 嗯,是的,所以我只是在中间使用一个 arduino 来保存所有继电器和 gps 数据,以及 RPI 来读取和执行命令,我想我可以在 arduino 中完成这一切,但我想要学习 RPI

以上是关于尝试使用 systemd 启动 python 脚本,但它在 Raspberry Pi 上不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Systemd 服务不会将 python 脚本写入文件,python 脚本在从 cli 执行时名义上运行

如何在 systemd 启动期间最后运行并打印我的脚本输出?

Docker 容器在启用 systemd 脚本后重新启动后无法启动

如何在systemd中添加service

Centos7 之 Systemd

技术指南centos7下systemd服务管理全解