systemd service não executando o script python

0

Eu estava fazendo um script notificador de bateria para o meu raspberry pi3. O script está sendo executado quando eu faço

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

e mostrando as notificações pop-up. No entanto, o serviço não está executando ou não mostrando a notificação. Eu posso ver o processo python se eu fizer sudo systemctl status battery-notifier.service .

battery-notifer.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!"])

Este é o status do serviço quando eu faço 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.
    
por avistein 15.07.2017 / 06:58

1 resposta

0

Editado para adicionar : Seu programa tenta acessar a área de trabalho gráfica de um usuário ( pi ), no entanto, ele próprio é executado pelo systemd. Ou seja, ele será executado como raiz por padrão e não como o usuário pi . Além disso, pode até não haver uma área de trabalho gráfica no momento em que isso é iniciado.

Portanto, você pode seguir vários caminhos:

  • Inicia o programa não via systemd, mas quando o usuário logado inicia o área de trabalho gráfica. Portanto, você precisa colocar o início do programa no arquivo ~/.xinitrc ou ~/.xprofile . Veja o Arch Wiki no Autostart
  • Adicione uma linha User=pi ao seu serviço systemd. Esta é a solução que você mencionou no comentário para sua postagem original
  • O systemd pode ser configurado para ser executado em um modo de usuário (em oposição ao modo de sistema) quando o usuário faz o login. Você pode permitir que seu serviço seja iniciado dessa forma. Veja o Arch Wiki em systemd / User

Resposta original:

Veja esta questão da SO . Existe um parâmetro env= na função subprocess.Popen(.) que pode ser usada.

Como alternativa, você poderia usar o recurso de sh que, se você atribuir uma variável imediatamente antes de uma chamada, essa variável será definida (somente) para essa chamada:

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

Link para o capítulo correspondente na especificação POSIX

Então, para você:

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

A chamada mencionada no comentário à sua pergunta não funciona porque leva ao seguinte processo

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

    • Iniciar um shell
    • Defina a variável de ambiente DBUS_SESSION_BUS_ADRESS=... para esse shell e todas as sub-shells (é isso que o export faz).

      O que faz NOT : Defina a variável para todos os shells que existem na máquina!

    • Feche o shell. Agora, o valor de DBUS_SESSION_BUS_ADRESS é perdido novamente.
  • %código%
    • Iniciar um shell
    • A chamada subprocess.Popen(['notify-send',...], shell=True) do shell anterior não tem energia aqui porque esses dois shells não têm relação alguma
    • Inicie export como na sua pergunta original

Portanto, a configuração da variável de ambiente não tem efeito aqui.

    
por 15.07.2017 / 11:32