Vraag:
Hoe een python-daemon schoon te verlaten?
EarlyEarl
2018-01-14 19:58:56 UTC
view on stackexchange narkive permalink

Ik wil dat een eenvoudig Python-script op de achtergrond wordt uitgevoerd, daarom heb ik daemon test.service geconfigureerd in / etc / systemd / system / .

  [Eenheid] Beschrijving = Test serviceAfter = multi-user.target [Service] Type = simpleExecStart = / usr / bin / python /home/pi/daemon.pyRestart=on-abort[Install[WantedBy=multi-user .target  

Mijn uitvoerende script daemon.py schakelt een LED aan die wordt bestuurd door een knop.

  #! / usr / bin / pythonimport RPi.GPIO als GPIOGPIO.setmode (GPIO.BCM) # Configureer knop pinGPIO.setup (14, GPIO.IN, pull_up_down = GPIO.PUD_UP) # Configureer LED pinGPIO.setup (18, GPIO.OUT) def-knop1 (kanaal ): print "Toogle LED!" GPIO.output (18, niet GPIO.input (18)) GPIO.add_event_detect (14, GPIO.FALLING, callback = button1, bouncetime = 300) probeer: while True: passfinally: print "cleanup () GPIO's" GPIO.cleanup ( )  

Nu kan ik mijn script als een service starten met systemctl start test.service en het op dezelfde manier stoppen. Maar voor een schoon script wil ik GPIO.cleanup () uitvoeren voordat het script wordt gesloten door systemctl stop test.service . Hoe kan ik dat bereiken? De eindelijk lijkt in dit geval niet te werken ...

Ten tweede, alle gedrukte berichten zoals "Toogle LED!" kan niet worden gezien als ik systemctl status test.service aanroep. Wordt de uitvoer ergens anders naar een ander bestand geschreven?

Bij voorbaat dank voor uw hulp!

Twee antwoorden:
Aurora0001
2018-01-14 20:32:22 UTC
view on stackexchange narkive permalink

Nu kan ik mijn script starten als een service met systemctl start test.service en het op dezelfde manier stoppen. Maar voor een schoon script wil ik GPIO.cleanup () uitvoeren voordat het script wordt gesloten door systemctl stop test.service. Hoe kan ik dat bereiken? Het lijkt in dit geval uiteindelijk niet te werken ...

Standaard stuurt systemd een SIGTERM en vervolgens SIGKILL naar uw service, tenzij u heeft gespecificeerd meer complexe logica. SIGTERM genereert geen uitzondering in Python, dus je eindelijk -blok wordt waarschijnlijk niet uitgevoerd.

Probeer toe te voegen:

  KillSignal = SIGINT  

Hieronder [Service] om systemd te vertellen een SIGINT te verzenden, die door Python wordt vertaald als een KeyboardInterrupt uitzondering. Dit zou dan uw elegante exit-logica moeten uitvoeren.

Ten tweede, alle gedrukte berichten zoals "Toogle LED!" kan niet worden gezien wanneer ik systemctl status test.service aanroep. Is de uitvoer ergens anders naar een ander bestand geschreven?

Ja, u zou moeten gebruiken:

  journalctl -u test.service  

Hiermee worden de systemische logboeken voor uw service gelezen. status geeft u slechts een korte samenvatting of uw service functioneert; het is niet het volledige logboek.

Bedankt voor je antwoord! Het werkt precies zoals het zou moeten. Maar trouwens: is dat de voorkeursmanier om een ​​script op de achtergrond te laten draaien of is het beter om een ​​python-daemon-klasse te gebruiken zoals [link] (https://gist.github.com/andreif/cbb71b0498589dac93cb). Wat is het verschil in beide benaderingen?
Als je het altijd via systemd gaat uitvoeren, hoef je het fork / setsid-ding niet zelf te doen (dat is wat daemonisatie is). Het kan echter zijn dat u de signaalverwerking wilt onderzoeken, zodat u een schone uitgang voor SIGTERM en andere dingen kunt doen.
Eerlijk gezegd denk ik dat een systeemservice veel beter is, @EarlyEarl. Systemd behandelt een groot deel van de complexiteit van het uitvoeren van een service zoals logboekregistratie, afhankelijkheidsbeheer, consistente opdrachtregelinterface, enz. Die code (uit 2007) werd geschreven voordat systemd bestond, en zal niet alle functies dekken die systemd doet. Ik zou altijd voorstellen * het wiel niet opnieuw uit te vinden * in deze situatie - systemd doet het werk goed, dus het is niet nodig om dingen te ingewikkeld te maken.
Perfect. Dan blijf ik bij deze oplossing. Dank je!
U kunt SIGTERM vastleggen, zie https://stackoverflow.com/questions/18499497/how-to-process-sigterm-signal-gracefully
user5365075
2019-02-11 19:39:35 UTC
view on stackexchange narkive permalink

Je kunt het ook doen met behulp van het signal native Python-pakket:

  def exit_gracefully (signum, frame): logging.info ('Exited') signaal. signal (signal.SIGTERM, exit_gracefully)  
Ik denk dat er een exit () ontbreekt in exit_gracefully (signum, frame)


Deze Q&A is automatisch vertaald vanuit de Engelse taal.De originele inhoud is beschikbaar op stackexchange, waarvoor we bedanken voor de cc by-sa 3.0-licentie waaronder het wordt gedistribueerd.
Loading...