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

Posted

技术标签:

【中文标题】Systemd 服务不会将 python 脚本写入文件,python 脚本在从 cli 执行时名义上运行【英文标题】:Systemd service does not write python script to file, python script runs nominally when executed from cli 【发布时间】:2019-03-26 16:25:43 【问题描述】:

使用树莓派零 w,设置一个脚本来监控 bme280 传感器,并将值写入文件。当脚本从命令行启动时,这非常有用,当脚本通过 systemd 启动时,文件不会被写入。请在下面找到脚本和 systemd 服务。

已将标准输出设置为绝对路径,但没有成功,python 脚本写入指令也设置为绝对路径。

系统服务:

[Unit]
Description=bme280 sensor log startup
After=network.target

[Service]
ExecStart=/usr/bin/python3 -u /home/pi/bme.py
WorkingDirectory=/home/pi
StandardOutput=file:/home/pi/senselog.csv
StandardError=inherit
Restart=always
User=pi

[Install]
WantedBy=multi-user.target

python 脚本:

import time
from time import strftime
import board
import busio
import adafruit_bme280

# Create library object using our Bus I2C port
i2c = busio.I2C(board.SCL, board.SDA)
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c,address=0x76)

# OR create library object using our Bus SPI port
#spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
#bme_cs = digitalio.DigitalInOut(board.D10)
#bme280 = adafruit_bme280.Adafruit_BME280_SPI(spi, bme_cs)

# change this to match the location's pressure (hPa) at sea level
bme280.sea_level_pressure = 1013.25

with open("/home/pi/senselog.csv", "a") as log:
    while True:

        temp_h = bme280.temperature
        humidity = bme280.humidity
        pressure = bme280.pressure
        log.write("0,1\n".format(strftime("%Y-%m-%d %H:%M:%S"),str([temp_h,humidity,pressure])))
        time.sleep(60)

如果我删除 senselog.csv 文件,然后在启动时 systemd 服务会创建新文件但没有数据,我们将不胜感激。

【问题讨论】:

应该是file:///home/pi/senselog.csv而不是file:/home/pi/senselog.csv,反正这不是问题,我想 你能检查一下journalctl -xe -f -u <your_service_name>吗? @hansolo 这里是 journalctl 的输出:``` journalctl -xe -f -u bme.service -- 日志从 2016 年 11 月 3 日星期四 10:16:44 PDT 开始。 -- 3 月 26 日 10:08:39 raspberrypi systemd[1]:启动 bme280 传感器日志启动。 -- 主题:单元 bme.service 已完成启动 -- 定义者:systemd -- 支持:debian.org/support -- -- 单元 bme.service 已完成启动。 -- -- 启动结果完成。 ``` 嘿,现在只有我注意到,您还没有定义服务的Type。考虑到您的脚本,您可以在[Service] 部分尝试Type=simple 吗? 将 Type=simple 添加到服务中,但行为没有变化。 【参考方案1】:

所以解决方案是在 python 脚本中对我们正在写入的文件实际调用 .close() ,然后 systemd 服务按预期工作。大声喊出这个帖子:https://askubuntu.com/questions/83549/python-script-wont-write-data-when-ran-from-cron 最后一个答案 = f.close()

和工作脚本文件:

from time import strftime
import board
import busio
import adafruit_bme280

# Create library object using our Bus I2C port
i2c = busio.I2C(board.SCL, board.SDA)
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c,address=0x76)

# OR create library object using our Bus SPI port
#spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
#bme_cs = digitalio.DigitalInOut(board.D10)
#bme280 = adafruit_bme280.Adafruit_BME280_SPI(spi, bme_cs)

# change this to match the location's pressure (hPa) at sea level
bme280.sea_level_pressure = 1013.25

with open("/home/pi/senselog.csv", "w") as log:
    while True:

        temp_h = bme280.temperature
        humidity = bme280.humidity
        pressure = bme280.pressure
        log.write("0,1\n".format(strftime("%Y-%m-%d %H:%M:%S"),str([temp_h,humidity,pressure])))
        log.close()
        time.sleep(60) ```

【讨论】:

【参考方案2】:

StandardOutputfile 属性仅在 systemd 版本 236 中可用。你有什么版本?

pi@wifi-relay:~ $ systemd --version

systemd 232
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN

如果版本低于 236 并且您不能/不想升级,您可以简单地将您的 ExecStart 行更新为:

/usr/bin/python3 -u /home/pi/bme.py >1 /home/pi/senselog.csv

...然后将StandardOutput 线恢复为默认值。

【讨论】:

感谢您的提醒,pi 版本为 233,因此我按照您的指示编辑了服务,文件写入行为没有改变。其他想法?

以上是关于Systemd 服务不会将 python 脚本写入文件,python 脚本在从 cli 执行时名义上运行的主要内容,如果未能解决你的问题,请参考以下文章

关于Journal Log

用户会话下方的 systemd 会话

如何将包含 SysV 初始化脚本的 RPM 包移植到 systemd?

Cron作业无法执行写入文本文件的python脚本

linux学习-将seafile启动脚本设置为开机启动服务

编写systemd下服务脚本