systemd 서비스가 Python 스크립트를 실행하지 않습니다.

systemd 서비스가 Python 스크립트를 실행하지 않습니다.

내 라즈베리 파이3용 배터리 알리미 스크립트를 만들고 있습니다. 내가 할 때 스크립트가 실행 중입니다.

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

답변1

추가하려면 수정하세요.: 프로그램이 사용자의 그래픽 데스크탑( pi)에 액세스하려고 시도하지만 systemd에 의해 자체적으로 실행됩니다. 즉, 기본적으로 user가 아닌 root로 실행됩니다 pi. 또한 시작 시 그래픽 데스크탑이 없을 수도 있습니다.

따라서 다음과 같은 몇 가지 경로를 선택할 수 있습니다.

  • systemd를 통해 프로그램을 시작하는 대신, 로그인한 사용자가 그래픽 데스크탑을 시작할 때 프로그램이 시작됩니다. 따라서 프로그램 시작을 파일 ~/.xinitrc이나 ~/.xprofile.see 에 넣어야 합니다 .자동 시작에 대한 Arch Wiki
  • User=pi시스템 서비스에 한 줄을 추가하세요. 이것은 원래 게시물의 댓글에서 언급한 솔루션입니다.
  • 사용자가 로그인할 때 시스템 모드가 아닌 사용자 모드에서 실행되도록 systemd를 구성할 수 있습니다. 이런 식으로 서비스를 시작할 수 있습니다. 바라보다systemd/User에 관한 Arch Wiki

원래 답변:

바라보다이 문제. 함수 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=...이 쉘과 모든 하위 쉘에 대한 환경 변수를 설정합니다(이것이 수행 되는 작업입니다 export).

      그것이 무엇을 할 수 있는지아니요: 머신의 모든 쉘에 대한 변수를 설정하십시오!

    • 셸을 닫습니다. 이제 DBUS_SESSION_BUS_ADRESS다시 그 가치를 잃었습니다.
  • subprocess.Popen(['notify-send',...], shell=True)
    • 셸 시작
    • 이전 쉘의 호출은 export두 쉘이 완전히 관련되어 있지 않으므로 여기서는 효과가 없습니다.
    • notify-send원래 질문에 따라 시작하십시오.

따라서 환경 변수 설정은 여기서 아무런 영향을 미치지 않습니다.

관련 정보