Systemd

systemd 服務未執行 python 腳本

  • July 18, 2017

我正在為我的樹莓派 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

shutdown.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.

編輯添加:您的程序嘗試訪問使用者的圖形桌面(pi),但是,它本身由 systemd 執行。也就是說,預設情況下它將以 root 身份執行,而不是以 user 身份執行pi。此外,在啟動時甚至可能還沒有圖形桌面。

因此,你可以走幾條路:

  • 不是通過 systemd 啟動程序,而是在登錄使用者啟動圖形桌面時啟動程序。因此,您需要將程序啟動放入文件~/.xinitrc~/.xprofile. 在 Autostart 上查看Arch Wiki
  • User=pi在您的 systemd 服務中添加一行。這是您在原始文章的評論中提到的解決方案
  • systemd 可以配置為在使用者登錄時以使用者模式(而不是系統模式)執行。您可以通過這種方式啟動您的服務。請參閱systemd/User 上的 Arch Wiki

原答案:

請參閱這個 SO 問題。函式中有一個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按照您原來的問題啟動

所以這裡環境變數的設置是沒有影響的。

引用自:https://unix.stackexchange.com/questions/378597