Daemon em execução envolvendo o GPIO no Pi

6

Eu tenho um daemon que monitora várias coisas usando as portas GPIO. Eu usei python para escrever o código para isso usando o módulo RPi.GPIO.

Gostaria de garantir que o daemon esteja sempre em execução, ou seja, reinicie-o após uma falha e inicie-o quando o sistema inicializar (crucialmente antes de qualquer usuário efetuar login - esse Pi é executado sem controle). Há um pequeno LED piscando que me diz que está funcionando, mas isso não é o ideal.

Eu li sobre o uso do MONIT para essa finalidade, mas estou tendo alguns problemas. Minhas tentativas até agora têm sido principalmente em torno desta solução:

link

Este é o meu arquivo wrapper bash, chamado /home/pi/UPSalarm/UPSalarm.bash

#!/bin/bash

PIDFILE=/var/run/UPSalarm.pid

case $1 in
    start)
        #source /home
        #Launch script
        sudo python /home/pi/UPSAlarm/UPSalarm.py 2>/dev/null &
        # store PID value
        echo $! > ${PIDFILE}
    ;;
    stop)
        kill 'cat ${PIDFILE}'
        # Proccess killed, now remove PID
        rm ${PIDFILE}
    ;;
    *)
        echo "usage: scraper {start|stop}" ;;
esac
exit 0'

Esta é minha regra de monitoramento

check process UPSalarm with pidfile /var/run/UPSalarm.pid
   start = "/home/pi/UPSalarm/UPSalarm start"
   stop = "/home/pi/UPSalarm/UPSalarm stop"

Eu tenho dois problemas: em primeiro lugar, recebo o número PID errado em UPSalarm.pid. Eu estou querendo saber se eu conseguir um número PID para o sudo? É por isso que publiquei a questão aqui; Eu preciso do sudo porque preciso acessar as portas do GPIO. Em segundo lugar, não funciona. Em terceiro lugar, não tenho certeza do que o source faz no arquivo bash?

Eu sei que o monit tem uma ótima documentação, mas um exemplo trabalhado para o python realmente seria útil, fiquei preso por uns bons dias.

Os seguintes sites também foram úteis: link (para configurar o monit) link

E essas duas perguntas estão relacionadas, mas não resolvem meu problema: link Como reiniciar o Script Python automaticamente se for morto ou morrer

    
por Aaron 27.07.2015 / 15:08

1 resposta

6

Esse invólucro shell se parece com um script de inicialização, mas aparentemente não é (portanto, você precisa usar sudo lá; os scripts executados pelo init não exigiriam isso).

Essa parece ser uma maneira muito desajeitada de fazer isso; o invólucro do shell não serve a nenhum propósito que não poderia ser melhor servido pelo próprio programa python. Livre-se disso; Se você quiser um script init especificamente, escreva um mínimo, mas sugiro que você mova a lógica de controlar o daemon do script init para o daemon ( UPSalarm.py ).

Como você deseja apenas uma instância, defina um arquivo pid que o processo deve usar. Quando UPSalarm.py start for executado, ele verificará a existência desse arquivo. Se não existir, ele grava seu próprio pid nesse arquivo e continua. Se existir, obtém o pid e depois verifica com o SO para ver se existe um processo com o pid e, em caso afirmativo, como é chamado. Isso provará que UPSalarm.py já está em execução ou não. Se estiver, saia com uma mensagem "Já está em execução".

Quando UPSalarm.py stop é executado, uma sequência semelhante está envolvida - verifique o arquivo pid, se ele existir, verifique o pid, se o pid é válido para um processo chamado UPSalarm.py , sinalize para parar, presumivelmente com %código%. SIGINT deve implementar um manipulador de sinal para UPSalarm.py , de modo que exclua o arquivo pid antes que ele saia.

Eu não sou um programador python e este não é um site de programação (para isso, veja Stack Overflow ), mas eu prometo que tudo isso é facilmente possível com python.

  • Para obter o pid do processo atual, use SIGINT .
  • Para mapear um pid a um nome de processo, leia os.getpid() e faça uma pesquisa por /proc/[pid]/cmdline (ou melhor ainda, o nome do processo como invocado, que seria UPSalarm.py , consulte here ).
  • Para o tratamento de sinal, inicie aqui e aqui .
  • Para enviar um sinal para outro processo, use sys.argv[0] .

Deve ser fácil configurar os.kill() para lidar com esse daemon. Você também tem a opção de usar apenas monit (ou seu próprio script) para chamar cron em intervalos, digamos, a cada 5-10 minutos.

    
por 27.07.2015 / 15:41