Shell Befehl stoppen/beenden

  • Ich arbeite an einem Projekt, welches an einem bestimmten Punkt ein Shell-Command ausführen soll.
    Das ganze funktioniert auch, allerdings läuft das Programm dann permanent durch und lässt sich nicht stoppen.
    Ist es möglich, dass Python permanent einen Taster überwacht und ich dadurch einen neuen Befehl ausführen bzw. die ausgeführte Shell beenden kann?

    Der erste Shell-Befehl startet FBI. Nach drücken des Tasters soll er es beenden und mein Script weiterlaufen lassen

  • Hallo Gintonik,
    um eine Programm-Logik abzubilden, die in die von Dir angestrebte Richtung geht, wird oft eine "Finite State Machine" ( -> endlicher Automat, Zustandsmaschine <- ) verwendet.
    Wenn Du Dir den oben verlinkten Artikel verinnerlicht hast, dann, glaube ich, hast Du auch die Lösung ...

    bye,
    -ds-

  • Hallo DS,

    ich verstehe nur Bahnhof,

    Wobei:

    Ich glaube, ich drücke mich umständlich aus!

    Im Prinzip möchte ich doch nur folgendes:

    Wenn ich meinen Taster (GPIO.23) drücke, soll er denselben Effekt auf dem PI auslösen, als wenn man die ESC-Taste gedrückt hätte.
    Diese würde FBI sauber beenden und in mein Python-Script zurückkehren.

    Ich habe ingesamt 3 Bücher gekauft, anscheinend die falschen!
    Wenn alles nichts hilft, dann zerlege ich eine Tastatur, löte zwei Drähte an die ESC Taste und verwende die anstatt meinem Taster auf GPIO....

  • Tja ... dann verstehe ich jetzt nicht, womit Du Schwierigkeiten hast :s

    Eine Taste auf der Tastatur ist auch nur ein Taster ... der Unterschied ist, dass Python die Tastatur-Abfragen für Dich erledigt.
    Dein Ansatz ist, soweit ich das beurteilen kann ( weil ich nix mit Python zu haben will :fies: ), schon richtig.
    Den Taster per pullup anzuschliessen und dann (idealerweise per Interrupt/Event) abzufragen ... dafür solltest Du hier tonnenweise Beispiel finden. Sollte also auch nicht das Problem sein ...

    cu,
    -ds-

  • Hallo Gintonik,

    wenn Du von Deinem Python-Code ein Linux-Kommando oder eine andere Anwendung startest, uind diese über das gleiche Python-Programm wieder beenden / abbrechen möchtest, dann musst Du da ein wenig anders herangehen.

    Zunächst muss Dein Python-Programm das andere Linux-Kommando / Anwendung im Hintergrund starten (erreichst Du durch Anhängen von " &".

    Dann bekommt diese eine eigene Prozess-ID. Diese kannst Du mit dem Linux-Kommando

    Code
    pidof


    abfragen.
    Und wenn Dein Python-Programm der Ansicht ist, dass Du den Taster gedrückt hast, um das zuvor gestartete Programm abzubrechen, dann brauichst Du kein ESC oder ein sonstiges Zeichen, sonden ein

    Code
    kill


    gefolgt von der zuvor ermittelten Prozess-ID.

    Wenn Du in der Konsole /LXTerminal

    Code
    man

    gefolgt von den beiden Kommandos [font="Courier New"]pidof[/font] oder [font="Courier New"]kill[/font] eingibst, dann erfährst Du mehr über Funktionsweise und Parameter.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (22. April 2016 um 19:44)

  • Eine eigene PID kriegt der Befehl auch ohne "&", der entscheidende Unterschied ist allerdings das ohne "&" das Python Script blockiert wird, solange bis der Konsolen Befehl sich beendet. Hängt man ein "&" an hat das zwangsläufig zur Folge dass das Python Script weiter verarbeitet wird bis das Dateiende erreicht ist und sich das Script dann ebenfalls beendet. Deshalb muss man das Script daran hindern sich zu beenden - was durch die "while" erreicht wird.

    'os.system' ist aber nicht allzu ideal gerade für solch eine Vorgehensweise. Besser wäre 'subprocess' zu verwenden denn das bietet bereits eine Funktion um den Prozess sowohl in den Hintergrund zu schicken als auch wieder zu beenden - ganz ohne Konsolen Befehle.
    'os.system' gibt nur den Exit-Code zurück - alles über 0 bedeutet das ein Fehler bei der Ausführung aufgetreten ist...
    Problematisch ist nur das der Umgang mit subprocess etwas anders ist: Der Befehl mit mehreren Argumenten muss in eine Tuple gesetzt werden => Ein Argument für den Befehl 'fbi' ist jedes was durch ein Leerzeichen getrennt ist...
    Bedeutet für deinen Fall:
    [code=php]import time
    import subprocess

    proc = subprocess.Popen(['sudo', 'fbi', '-noverbose', '-u', '-a', '-t1', '/home/pi/pics/*.*'], shell=True)
    pid = proc.pid

    time.sleep(3)
    proc.terminate()
    #proc.kill()
    [/php]Der Unterschied zwischen proc.terminate() und proc.kill() ist: terminate sendet SIGTERM zu dem Prozess und überlässt es dem Prozess selbst sich zu beenden. kill zwingt den Prozess zum beenden.
    Siehe dazu auch https://docs.python.org/3/library/subp…Popen.terminate


    Was man zu deinem Script aber vielleicht auch noch sagen sollte:
    Jeder GPIO der als Eingang gesetzt wird kann seinen Zustand willkürlich ändern da bereits geringe Spannungen ausreichen damit der GPIO ein HIGH registriert und sobald ein Kabel angeschlossen wird dies als Antenne fungiert... Um das zu verhindern bedarf es einen Pull Up/Down Widerstand, entweder extern selbst angebracht oder den internen via Software aktivieren.

  • Hallo Meigrafd,

    ich bin durch deine Hilfe ein kleines Stückchen weiter gekommen. Ich habe mein Script wesentlich auf die Elemente reduziert, die mir Probleme bereiten.
    Allerdings bleiben zwei kleine Dinge offen:

    Du hattest geschrieben, dass der Code in Tuples gesetzt werden müsste. Das hat bei mir leider nicht funktioniert. Wenn ich den Befehl allerdings so geändert habe, wie im Code gezeigt, dann ging es.

    Das nächste ist:

    Starte ich FBI mittels deinem sub.process läuft er wunderbar. Kommt der kill-Befehl eine Zeile tiefer, ist auch schon wieder schluss. Allerdings, und wenn das gelöst werden könnte, dann hätte ich glaube ich alles zusammen:

    Kann der kill-Befehl nicht in der while-Schleife stehen und somit auf den Tastendruck (GPIO.23) hören?
    Denn an dieser Stelle hat er keine Funktion :(

    Einmal editiert, zuletzt von Gintonik (23. April 2016 um 19:42)

  • Mein Code da oben war nur ein Beispiel - deshalb auch das sleep und danach das beenden des Prozesses, nur zur Veranschaulichung dass das Script nicht vom ausführen blockiert wird sondern auch noch anderes abhanden kann... Selbstverständlich müsstest Du in Deinem Fall den Prozess erst dann beenden wenn der Taster gedrückt wurde, aber: ...irgendwie verabschieden sich bei dir ständig die Einrückungen - oder hast du tatsächlich keine Einrückungen? Die sind für python extrem wichtig


    PS: https://docs.python.org/2/library/subp…pen-constructor


  • Mein Code da oben war nur ein Beispiel - deshalb auch das sleep und danach das beenden des Prozesses, nur zur Veranschaulichung dass das Script nicht vom ausführen blockiert wird sondern auch noch anderes abhanden kann... Selbstverständlich müsstest Du in Deinem Fall den Prozess erst dann beenden wenn der Taster gedrückt wurde, aber: ...irgendwie verabschieden sich bei dir ständig die Einrückungen - oder hast du tatsächlich keine Einrückungen? Die sind für python extrem wichtig


    PS: https://docs.python.org/2/library/subp…pen-constructor

    Hallo Meigrafd,

    das mit den Einrückungen ist mir erst nach deinem Kommentar aufgefallen.
    Im Editor sind die natürlich korrekt, irgendwie passt das copy&paste nicht so wirklich hierhin.


    Ich habe eben noch ein bisschen rumgespielt.
    Generell würde dein Code wohl funktionieren, allerdings liegt es wohl an FBI:

    Wird der kill-Befehl sofort und ohne Pause hinterher geschickt, dann wird der Prozess beendet.
    Ist auch nur eine kleine time.sleep(1) dazwischen, ist es schon vorbei mit der Herrlichkeit.

    FBI lässt sich ab Werk mit der ESC bzw. q Taste beenden. Wenn ich diese drücke, wird FBI geschlossen und ich bin wieder in meinem Script.
    Es ist jetzt ein bischen blöd, dass ich wirklich eine Tastatur zerlegen muss und in dem Fall die "q" Taste umlöte.
    Aber anscheinend ist es ohne einen riesen Aufwand anders nicht möglich.

    Das bedeutet in meinem Fall aber auch, dass wenn FBI beendet wurde, ich mit einem Druck der Taste q meine while-Schleife starten muss, anstatt mit GPIO.23.

    Eine Optiion ist natürlich auch, dass der Taster GPIO.23 einen q-Interupt auslöst.
    Aber ich denke, dass die Tastatur die sinnigste Lösung ist, da diese überschaubar ist mit nur einer Taste.

    Jedenfalls werde ich meinen Fokus auf die Variante mit der Tastatur legen, da diese mir am einfachsten erscheint und dazu noch stabil.

    Dazu bitte ich noch um einen letzten kleinen Hinweis:

    Über welchen Befehl lässt sich ein einfacher Tastendruck für eine whil-Schleife am besten abfragen?
    Der raw.input kommt nicht in Frage, da er ja eine Bestätigung per Enter verlangt.
    Pygame vielleicht?


  • FBI lässt sich ab Werk mit der ESC bzw. q Taste beenden. Wenn ich diese drücke, wird FBI geschlossen und ich bin wieder in meinem Script.
    Es ist jetzt ein bischen blöd, dass ich wirklich eine Tastatur zerlegen muss und in dem Fall die "q" Taste umlöte.
    Aber anscheinend ist es ohne einen riesen Aufwand anders nicht möglich.

    Nein das glaub ich nicht.
    Leider scheinst du den unterschied zwischen proc.terminate() und proc.kill() nicht verstanden zu haben - du schreibst nur kill-Befehl aber den führst du ja gar nicht aus.
    Lies also bitte noch mal Beitrag#6 :fies:

    Das bedeutet in meinem Fall aber auch, dass wenn FBI beendet wurde, ich mit einem Druck der Taste q meine while-Schleife starten muss, anstatt mit GPIO.23.


    PS: Bitte nicht Beiträge vollständig quoten, vor allem wenn diese genau da drüber stehen.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!