Wie erfährt init von Power-Ereignissen?

8

Ich habe ein Pi Model B Rev 2.0 (glaube ich) und beabsichtige, es für ein Hausautomationssystem zu verwenden. Da ich einen Vorauszahlungszähler an meiner Stromversorgung habe, gehen mir gelegentlich die Elektronen aus, um die Netzversorgung meines Hauses zu umgehen!

Um Probleme zu vermeiden, habe ich eine USV in Form eines UPis Basic von PiModules erhalten . Ich habe es so konfiguriert, dass ich die Versorgungsspannungen über die serielle Schnittstelle des Pi abfragen kann (nicht die Standardkonfiguration, sondern eine im Handbuch dokumentierte unterstützte Einrichtung ).

Gegenwärtig wird ein dedizierter GPIO-Pin verwendet (Pin 13 im Header, GPIO27, glaube ich), und der eingebaute Mikrocontroller verwendet diesen und ein Python-Skript, das von rc.local ausgeführt wird, um dem Pi mitzuteilen, shutdown -h nowwann der Pin niedrig genommen wird. Dies geschieht, wenn die Taste "Shutdown" der USV gedrückt wird oder wenn die Batterieversorgung bei einem Ausfall der Hauptversorgung zu niedrig wird. Für die Aufzeichnung lautet das Skript:

#!/usr/bin/python

# import the  libraries to use time delays, send os commands and access GPIO pins
import PRi.GPIO as GPIO
import time
import os

GPIO.setmode(GPIO.BCM) # Set pin numbering to board numbering
GPIO.setup(27, GPIO.IN, pull_up_don=GPIO.PUD_UP) # Setup pin 27 as an input
while True: # Setup a whille loopto wait for a button press
    if(GPIO.input(27)==0): # Setup an if loop to run a shutdown command when button press sensed
        os.system("sudo shutdown -h now") # Send shutdown command to os
        break
    time.sleep(1) # Allow a sleep time of 1 second to reduce CPU usage

Dies scheint mir ein wenig unelegant zu sein, da inites die eingebaute Fähigkeit hat, Energieereignisse zu verarbeiten. Ich möchte wiederholen , dass ich verwende sysvinit auf Raspbian Jessie nicht die Standard systemd für diese Version (für persönliche Präferenz und Vertrautheit Gründen).

Ich möchte zunächst das obige Skript durch etwas ersetzen, das init anweist, es zu tun, powerfailnowwenn der Pin niedrig wird - und ein, powerokwaitwenn es anschließend hoch zurückgibt. Schließlich auch die serielle Schnittstelle abzufragen ich will , und halte ein Auge auf den Antworten auf @rpi, @batund @upswelche Rück die aktuellen Spannungen an dem 5V - Schiene von Pi, der LiPo - Akku und die Upis besitzen microUSB Eingang bzw. - so dass das Pi kann eine Warnung geben auf powerfailIch behandle einen Stromausfall (dies sollte zu einer Initiierungsaktion führen und den Pi den Stromausfallstatus an mich, den Benutzer, melden lassen - vorausgesetzt, ich habe es noch nicht bemerkt!)

Ich habe jedoch Schwierigkeiten herauszufinden, wie Linux-USV-Geräte signalisieren, initdass die in definierten powerfail\ powerwait\ powerfailnow\ powerokwaitBefehle ausgeführt \etc\inittabwerden sollen.

Kann mir zum Beispiel jemand raten, wie "erwachsene" USV einem Linux-Kernel auf einem normalen PC mitteilt, dass "Power" -Ereignisse auftreten, und wie ich dasselbe in diesem System auf einem Pi reproduzieren könnte?

SlySven
quelle
Vielen Dank an @ Jacobm001, dass Sie das Fehlen des Tags für den Python-ähnlichen Teil dieser Frage entdeckt haben. In den letzten Stunden habe ich einen Crashkurs in der Sprache absolviert (ich mache Fortschritte), aber vor kurzem wollte ich nicht Ich habe meinen Asp nicht von meinem Ellbogen
gekannt
Ich bin auch neugierig, wie der Pi (oder Init) über Power-Ereignisse Bescheid weiß. Hoffentlich antwortet bald jemand.
PNDA
Ich würde mich mit Acpid befassen und vielleicht können Sie Ihr Skript ändern, um zu reagieren, wenn sich etwas ändert (Pin hoch -> niedrig), anstatt den Wert jede Sekunde abzufragen?
Diederik de Haas
2
@ PandaLion98 Die Pi-Hardware hat keine Energieereignisse, daher ist nichts über sie bekannt. Wenn einige implementiert sind, würde init nur dann davon erfahren, wenn dies entweder vom Kernel (aufgrund eines Treiberereignisses, das im Fall des pi vermutlich ein Treiber für zusätzliche Hardware wäre) oder über eine Benutzerlandanwendung mitgeteilt wird.
Goldlöckchen

Antworten:

5

Ah, ha! Einige Absätze in den Manpages für init(8)beziehen sich auf die veraltete Schnittstelle zum Schreiben eines Ein-Buchstaben-Werts an /etc/powerstatus(jetzt ersetzt durch /var/run/powerstatus) und anschließendes Senden initeines SIGPWRSignals. Der Brief sollte einer der folgenden sein:

  • F ‘ angeschlagene Leistung: [Hauptstrom ausgefallen ist und die] UPS ist die Kraft bereitstellt, die auszuführen powerwaitund powerfailEinträge.
  • Power ' O ' kay: [main] power wurde wiederhergestellt, führen Sie den powerokwaitEintrag aus.
  • ' L ' ow power: Die Stromversorgung fällt aus und die USV hat eine [kritisch] schwache Batterie. Führen Sie die powerfailnowEingabe aus.
Wenn die angegebene Datei nicht existiert oder enthält nichts anderes als die Buchstaben F, Ooder Lwird init als verhalten , wenn er den Brief gelesen hat F.

Darunter befindet sich der Hinweis:

Die Verwendung von SIGPWRund /etc/powerstatuswird nicht empfohlen. Jemand, der mit ihm interagieren möchte, initsollte den /run/initctlSteuerkanal verwenden. sysvinitWeitere Dokumentation hierzu finden Sie im Quellcode des Pakets.

Dies ist zwar eine Antwort , aber nicht die Antwort. Als Nächstes muss ich mir den Quellcode ansehen, der als Nicht-GNU-Projekt auf der Hosting-Site der GNU gehostet wird .

SlySven
quelle
1

Ich denke, der sauberste Ansatz wäre, einen Kernel-Gerätetreiber GPIO27 verwalten zu lassen und so einzurichten, dass er einen Interrupt empfängt, wenn er niedrig wird. Der Interrupt-Handler würde init benachrichtigen. Die Seite http://elinux.org/RPi_Low-level_peripherals besagt, dass Raspbian Wheezy GPIO-Interrupts unterstützt.

Ich entschuldige mich für die minderwertige Antwort. Ich habe mir die GPIO-Treiber von Linux und deren Erweiterung / Verbesserung nicht angesehen. Ich habe auch die derzeit genehmigte Methode zum Benachrichtigen von init in einem Interrupt-Handler nicht nachgeschlagen. Hoffentlich wird dieser Beitrag zu besseren Antworten führen.

Chad Farmer
quelle
Ja, eine Unterbrechung scheint besser zu sein als eine Umfrage - Diederik de Haas hat das oben erwähnt. Der Schwerpunkt meiner Untersuchung liegt derzeit jedoch auf "Der Interrupt-Handler würde init benachrichtigen ...". Dieser Mechanismus ist rätselhaft. Das powerstatDatei- / SIGPWR-Signal sieht relativ einfach und unkompliziert aus, scheint jedoch veraltet zu sein. Ich versuche jetzt herauszufinden, wie die initctlPfeife im wirklichen Leben benutzt wird ...
SlySven
1

Durch das Durchsuchen des Quellcodes des SysV init, der auf dem Savannah-Server der Free Software Foundation verfügbar ist, konnte ich Anfragen an meine RPi senden, initindem ich eine ausfüllte, struct init_requestwie in der initreq.hHeader-Datei beschrieben. Insbesondere erforderte dies das magic, sleeptimeund für meine Zwecke der cmdFelder ausgefüllt werden, wobei letztere Satz nach einem der INIT_CMD_POWERFAIL, INIT_CMD_POWERFAILNOWoder INIT_CMD_POWEROK.

Mein Daemon / Programm, das als Benutzer mit der Berechtigung zum Schreiben in die Init-Steuerpipe ausgeführt werden muss (ursprünglich bei, /dev/initctrlaber auf Debian und damit auf Raspbian verschoben /run/initctrl), konnte dann diese Struktur senden, auf initdie dann entsprechend geantwortet wurde, indem auf die folgende Einträge in /etc/inittab:

# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop

Hinweis: Diese Schnittstelle - oder zumindest die Benachrichtigung über die Stromversorgung wurde vom neuen Fangled NICHT übernommen systemd- obwohl sie durch eine Art Frachtkultprogrammierung versucht, sicherzustellen, dass das initctrlRohr vorhanden ist. Auf der anderen Seite macht dies genau das, was ich auf meinem RPi-System möchte!

SlySven
quelle
Obwohl ich Ihr Engagement für Ihr Problem bewundere, kann ich nicht anders, als zu bemerken, dass Sie viel Zeit damit verbracht haben, eine Lösung zu implementieren, die funktional Ihrem ursprünglichen Skript entspricht und nicht einmal zukunftssicher ist.
Dmitry Grigoryev
Nun, obwohl es funktional dem ursprünglichen System entspricht, verwendet es die empfohlene bereitgestellte Schnittstelle anstelle der veralteten. In Bezug auf die Zukunftssicherheit liegt es nicht an den Personen, die das zukünftige System schreiben, die bekannte Schnittstelle des Systems zu implementieren, das sie ersetzen möchten, um die Abwärtskompatibilität nach Möglichkeit sicherzustellen .
SlySven
Schließlich ist es für ein System mit einer USV sehr wichtig, eine Benachrichtigung über einen Hauptstromausfall zu erhalten. Daher sollte ein halbwegs anständiger Prozess- / Systemmanager wissen, wie sein Vorgänger vorgegangen ist, und nach anderen Prozessen suchen, die diese API verwenden - eine Schnittstelle, die existiert, wird aber ignoriert, scheint ein bisschen kurzsichtig zu sein ... 8- / Laut Code unter: github.com/systemd/systemd/blob/master/src/initctl/initctl.c sagt eine USV, systemddass die Hauptstromversorgung ausgefallen ist Auf diese Weise wird die folgende Meldung protokolliert: "UPS / Power Initctl-Anforderung empfangen. Dies ist in systemd nicht implementiert. Aktualisieren Sie Ihren UPS-Daemon!"
SlySven
"Dies ist in systemd nicht implementiert. Aktualisieren Sie Ihren UPS-Daemon" - das ist alles, was Sie über die Abwärtskompatibilität unter Linux wissen müssen;)
Dmitry Grigoryev
Die initctlSchnittstelle zu van Smoorenburg init wurde bereits 2012 von einem der (damaligen) Programmbetreuer als privat und nicht für Dritte deklariert . Miquel van Smoorenburgs powerd, später Tom Websters genpowerd, verwendete den /etc/powerstatusMechanismus ursprünglich .
JdeBP