systemd服务不执行python脚本

systemd服务不执行python脚本

我正在为我的树莓派 pi3 制作一个电池通知程序脚本。当我这样做时脚本正在执行

/usr/bin/python /home/pi/Documents/shutdown.py

并显示弹出通知。但是该服务没有执行它或没有显示通知。如果我这样做,我可以看到 python 进程sudo systemctl status battery-notifier.service

电池通知程序服务

[Unit]
Description=Battery Notifier

[Service]
Type=simple
WorkingDirectory=/home/pi/Documents
ExecStart=/usr/bin/python /home/pi/Documents/shutdown.py

[Install]
WantedBy=multi-user.target

关机.py

import raspiupshat
import statistics
import subprocess
from time import sleep
raspiupshat.init()
while(True):
    voltagesList = []
    sleep(0.5)
    currentVoltage = raspiupshat.getv()
    voltagesList.append(currentVoltage)
    medianVoltage = statistics.median(voltagesList)
    if(medianVoltage>4):
        subprocess.Popen(["notify-send","Battery Full!"])

这是我执行此操作时服务的状态sudo systemctl status battery-notifier.service

● battery-notifier.service - Battery Notifier
   Loaded: loaded (/lib/systemd/system/battery-notifier.service; enabled)
   Active: active (running) since Sat 2017-07-15 04:05:18 UTC; 48min ago
 Main PID: 28384 (python)
   CGroup: /system.slice/battery-notifier.service
           └─28384 /usr/bin/python /home/pi/Documents/shutdown.py

Jul 15 04:05:18 raspberrypi systemd[1]: Started Battery Notifier.

答案1

编辑添加:您的程序尝试访问用户的图形桌面 ( pi),但是,它本身是由 systemd 执行的。也就是说,它将默认以 root 身份运行,而不是以 user 身份运行pi。此外,启动时甚至可能还没有图形桌面。

因此,你可以走几条路:

  • 不是通过 systemd 启动程序,而是在登录用户启动图形桌面时启动程序。因此,您需要将程序启动放入文件~/.xinitrc~/.xprofile.看Arch Wiki 关于自动启动的内容
  • User=pi向您的 systemd 服务添加一行。这是您在原始帖子的评论中提到的解决方案
  • systemd 可以配置为在用户登录时以用户模式(而不是系统模式)执行。您可以通过这种方式启动您的服务。看Arch Wiki 关于 systemd/User 的内容

原答案:

这个问题。函数env=中有一个subprocess.Popen(.)可以使用的参数。

或者,您可以使用以下功能:sh如果您在调用之前立即分配一个变量,则(仅)为该调用设置该变量:

myvar=world
# cannot use echo $myvar, because $myvar would be substituted before echo is launched
myvar=hello declare -x myvar 
echo $myvar

给出

declare -x myvar="hello"
world

链接到 POSIX 规范中的相应章节

所以对你来说:

subprocess.call("DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-goOEk5dZcK,‌​guid=9c1f14175e6be09‌​92b16e5155969b46c notify-send 'Battery full!'",s‌​hell=True)

您在问题评论中提到的调用不起作用,因为它会导致以下过程

  • subprocess.Popen('export DBUS_SESSION_BUS_ADRESS=..., shell = True)

    • 启动外壳
    • DBUS_SESSION_BUS_ADRESS=...设置此 shell 和所有子 shell 的环境变量(就是这样export做的)。

      它能做什么不是:为机器上的所有 shell 设置变量!

    • 关闭外壳。现在DBUS_SESSION_BUS_ADRESS又失去了价值。
  • subprocess.Popen(['notify-send',...], shell=True)
    • 启动外壳
    • 前一个 shell 的调用export在这里没有任何作用,因为这两个 shell 完全不相关
    • notify-send按照您原来的问题启动

所以环境变量的设置在这里不起作用。

相关内容