Systemd
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
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 WikiUser=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
所以對你來說:
subprocess.call("DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-goOEk5dZcK,guid=9c1f14175e6be0992b16e5155969b46c notify-send 'Battery full!'",shell=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
按照您原來的問題啟動所以這裡環境變數的設置是沒有影響的。