Ich habe eine gepatchte Version von Last-Exit die manchmal hängen bleibt (ein bekannte aber noch ungelöstes Problem).
Damit ich nicht immer selber kontrollieren muss ob Last-Exit noch aufnimmt, es wenn es wieder stehen geblieben ist manuelle beenden und wieder dieser neu starten muss, wollte ich den ganzen Vorgang automatisieren.
Bei der Wahl zwischen einem Script und einem Programm habe ich mich für ein Programm und zwar in Python entschieden.
Ich dachte mir den Ablauf des Programms zunächst wie folgt:
last-exit starten Schleife: 1 Minute warten kontrollieren ob Last-Exit noch läuft: Nein: last-exit beenden; last-exit starten SchleifeEnde
Manchmal kommt es vor das sich Last-Exit einfach beendet. Ich weiß nicht ob es einen Fehlercode zurückgibt oder etwas in den Fehler- oder Ausgabekanal schreibt. Aber ich vermute mal das es das tut.
Darum meine zweite Version:
last-exit starten Schleife: Warten (z.B. 1 Minute) Wird Last-Exit noch ausgeführt? Nein: Ist last-exit abgestürzt? Nein: Programm beenden Ja: last-exit neu starten Ja: Nimmt Last-Exit noch auf? Nein: last-exit beenden; last-exit neu starten SchleifeEnde
Um zu kontrollieren ob Last-Exit noch aufnimmt habe ich folgendes ermittelt:
Last-Exit speichert den gerade aufgenommenen Titel in der Datei /tmp/lastexit-<Benutzername>.
Wenn das Änderungsdatum der Datei zu lange zurückliegt (z.B. mehr als 30 Sekunden) nimmt Last-Exit nicht mehr auf.
Wenn die Datei längere Zeit nicht existiert nimmt Last-Exit nicht mehr auf.
Darum meine dritte Version:
last-exit starten Schleife: 1 Minute warten Wird Last-Exit noch ausgeführt? Nein: Ist last-exit abgestürzt? Nein: Programm beenden Ja: last-exit neu starten Ja: Existiert die Temporäre-Datei? Ja: War die letzte Änderung vor mehr als 30 Sekunden? Ja: last-exit beenden; last-exit neu starten Nein: 10 Sekunden warten; Existiert die Temoräre-Datei? Nein: last-exit beenden; last-exit neu starten SchleifeEnde
Falls sich der Prozess beendet hat kontrolliere ob es einen Fehlercode zurückgegeben hat oder ob etwas in den Ausgaben im Fehler-oder Ausgabekanal auf einen Absturz hindeutet.
Falls es sich um einen Absturz handelt last-exit neu starten sonst ist die Aufgabe erledigt
Meine vierte Version ist mehr hypothetisch weil ich nicht genau weiß wie sich last-exit bei einem Absturz wirklich verhält:
last-exit starten Schleife: 1 Minute warten Wird Last-Exit noch ausgeführt? Nein: Gab es einen Fehlercode? Nein: Gab es einen Ausgabe die auf einen Absturz hindeutet? Nein: Programm beenden Ja: last-exit neu starten Ja: last-exit neu starten Ja: Existiert die Temporäre-Datei? Ja: War die letzte Änderung vor mehr als 30 Sekunden? Ja: last-exit beenden; last-exit neu starten Nein: 10 Sekunden warten; Existiert die Temoräre-Datei? Nein: last-exit beenden; last-exit neu starten SchleifeEnde
Zunächst hatte ich ein Pythonprogramm (Gutsy hat Python 2.5) geschrieben, um festzustellen ob die Methode mit der ich ermitteln will ob die Temporäre-Datei existiert und wann sie das letzte mal geändert wurde, auch funktioniert. Das Programm sieht chaotisch aus weil ich nach 20 Jahren Programmierabstinenz das Programmieren anscheinend ziemlich verlernt habe. Auch Python selber und die Entwicklungsumgebung DrPython bereiten mir Probleme. Da DrPython keinen Debugger hat, der es einem ermöglicht das Programm schrittweise auszuführen, habe ich zur Uralt-Methode mit print gegriffen, insbesondere nachdem verschiedene Versionen meines Testprogramms hängengebleiben sind und ich DrPython beenden und neu starten musste um weiterzumachen. Mittlerweile benutze ich Eric 3.9.5 (die Version 4 gibt es für Gutsy nicht) das zwar einen Debugger und Einzelschrittausführung hat, für meine Zwecke aber wohl zu groß und überladen ist.
Das Testprogramm in seiner Endversion:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #!/usr/bin/python # -*- coding: utf-8 -*- import os import time DateiNichtGefunden = 0 MaximaleZeitDifferenz = 0.0 MinimaleZeitDifferenz = 0.0 print "-1" print "Start" #Programm=Starte("last-exit "lastfm://artist/Dannii Minogue/similarartists"") print "0" while True: print "1" time.sleep(1) print "2" try: print "3" DateiZeit = os.path.getatime("/tmp/lastexit-michael") print "4" except OSError: print "5" if DateiNichtGefunden > 0: print "6" print "last-exit hängt weil die temporäre Datei mehr als 60 Sekunden lang nicht existiert" print "7" print "Systemzeit:", time.asctime(time.localtime(time.time())) print "8" #Beende(Programm) #Programm=Starte("last-exit "lastfm://artist/Dannii Minogue/similarartists"") #DateiNichtGefunden = 0 #continue break print "9" else: print "10" print "Datei nicht gefunden" print "11" DateiNichtGefunden = DateiNichtGefunden+1 print "12" continue print "13" else: print "14" SystemZeit = time.time() print "15" DateiNichtGefunden = 0 print "16" ZeitDifferenz = DateiZeit-SystemZeit print "17" if ZeitDifferenz < -60 : print "18" print "last-exit hängt weil in die temporäre Datei mehr als 60 Sekunden lang nichts geschrieben wurde" print "19" print "Dateizeit:", time.asctime(time.localtime(DateiZeit)), "; " , "Systemzeit:", time.asctime(time.localtime(SystemZeit)) print "20" #Beende(Programm) #Programm=Starte("last-exit "lastfm://artist/Dannii Minogue/similarartists") #continue break print "21" else: print "22" if ZeitDifferenz < MinimaleZeitDifferenz : print "23" MinimaleZeitDifferenz = ZeitDifferenz print "24" print "Minimale Zeitdifferenz: ", MinimaleZeitDifferenz print "25" if ZeitDifferenz > MaximaleZeitDifferenz : print "26" MaximaleZeitDifferenz = ZeitDifferenz print "27" print "Maximale Zeitdifferenz: ", MaximaleZeitDifferenz print "28" continue print "29" |
Nachdem ich einigermaßen sicher was das meine Erkennungsmethode grundsätzlich funktioniert habe ich versucht last-exit von Python aus aufzurufen und zu beenden. Das Programm sieht nach etlichen Verschlimmbesserungen noch chaotischer aus.
Das Überwachungsprogramm Last-ExitWatchdog (Stand ca. 2 Uhr Nachts an Neujahr):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | #!/usr/bin/python # -*- coding: utf-8 -*- import os import time import subprocess DateiNichtGefunden = 0 MaximaleZeitDifferenz = 0.0 MinimaleZeitDifferenz = 0.0 WarteZeit = 60 KommandoStartLastExit = ["/bin/sh","last-exit","lastfm://artist/Dannii Minogue/similarartists"] #KommandoStartLastExit = ["last-exit","lastfm://artist/Dannii Minogue/similarartists"] #LastExitURL = sys.argv[1] LastExit = subprocess.Popen(KommandoStartLastExit) KommandoTermLastExit = ["/bin/kill", "-TERM ", str(LastExit.pid)] KommandoKillLastExit = ["/bin/kill", "-KILL ", str(LastExit.pid)] while True: #time.sleep(WarteZeit) LastExitRueckgabewert = LastExit.poll if LastExit.returncode <> None: if LastExit.returncode == 0: break else: LastExit = subprocess.Popen(KommandoStartLastExit) KommandoTermLastExit = ["/bin/kill", "-TERM ", str(LastExit.pid)] KommandoKillLastExit = ["/bin/kill", "-KILL ", str(LastExit.pid)] DateiNichtGefunden = 0 continue else: try: DateiZeit = os.path.getatime("/tmp/lastexit-michael") except OSError: if DateiNichtGefunden > 0 : Kill = subprocess.Popen(KommandoTermLastExit) time.sleep(WarteZeit/10) if Kill.returncode <> None : if Kill.returncode == 0: LastExit = subprocess.Popen(KommandoStartLastExit) KommandoTermLastExit = ["/bin/kill", "-TERM ", str(LastExit.pid)] KommandoKillLastExit = ["/bin/kill", "-KILL ", str(LastExit.pid)] DateiNichtGefunden = 0 continue else: Kill = subprocess.Popen(KommandoKillLastExit) time.sleep(WarteZeit/10) if Kill.returncode <> None : if Kill.returncode == 0: LastExit = subprocess.Popen(KommandoStartLastExit) KommandoTermLastExit = ["/bin/kill", "-TERM ", str(LastExit.pid)] KommandoKillLastExit = ["/bin/kill", "-KILL ", str(LastExit.pid)] DateiNichtGefunden = 0 continue else: print("Last-Exit konnte nicht beendet werden.") break else: print("kill -KILL reagiert nicht") break else: print("kill -TERM reagiert nicht") break else: DateiNichtGefunden = DateiNichtGefunden+1 continue else: SystemZeit = time.time() DateiNichtGefunden = 0 ZeitDifferenz = DateiZeit-SystemZeit if ZeitDifferenz < -WarteZeit : Kill = subprocess.Popen(KommandoTermLastExit) time.sleep(WarteZeit/10) if Kill.returncode <> None : if Kill.returncode == 0: LastExit = subprocess.Popen(KommandoStartLastExit) KommandoTermLastExit = ["/bin/kill", "-TERM ", str(LastExit.pid)] KommandoKillLastExit = ["/bin/kill", "-KILL ", str(LastExit.pid)] DateiNichtGefunden = 0 continue else: Kill = subprocess.Popen(KommandoKillLastExit) time.sleep(WarteZeit/10) if Kill.returncode <> None : if Kill.returncode == 0: LastExit = subprocess.Popen(KommandoStartLastExit) KommandoTermLastExit = ["/bin/kill", "-TERM ", str(LastExit.pid)] KommandoKillLastExit = ["/bin/kill", "-KILL ", str(LastExit.pid)] DateiNichtGefunden = 0 continue else: print("Last-Exit konnte nicht beendet werden.") break else: print("kill -KILL reagiert nicht") break else: print("kill -TERM reagiert nicht") break else: continue |
Mal abgesehen von meinen mehr als bescheidenen Programmierungskünsten habe ich es bis jetzt nicht zustande gebracht last-exit so aufzurufen das es nach dem beenden einen returncode liefert.
Wenn ich last-exit manuell beende bleibt es (laut Systemüberwachung) als Zombie zurück und das Pythonprogramm erkennt nicht das es beendet wurde. Mein Versuch last-exit über die Shell aufzurufen führte nur zu einem neuen Prozess sh dem anscheinend keine Argumente übergeben wurden (laut Systemüberwachung). Dasselbe passiert bei dem Versuch kill aufzurufen (dabei musste ich erfahren das es zwei kill Befehle gibt. Den built-in Befehl der Shell und ein echtes Programm /bin/kill was mich zusätzlich verwirrt hat) um den vorher aufgerufenen Prozess zu beenden. Allerdings vermute ich das es eine Möglichkeit gibt den last-exit-Prozess direkt von Python aus zu beenden ohne externes Programm. Ich weiß nur nicht welche.
Die Dokumentationen sind leider alle in englisch und mit dieser Sprache stehe ich seit meiner Grundschulzeit auf Kriegsfuß. Ich habe zwar noch ein Buch "Python Referenz David M. Beazley (2001)" als PDF-Datei, aber das nutzt mir leider nichts da es gerade os, subprozess und popen nicht weiter erklärt.
Es ist mir auch nicht gelungen durch googlen etwas passendes im Internet zu finden. Das was ich gefunden und ausprobiert habe funktioniert leider alles nicht.
Was ich benötige wäre :
last-exit so aufzurufen wie es geschieht wenn ich es über "GNOME-Menü → Anwendung → Last-Exit" aufrufe nur zusätzlich mit dem Parameter für die Last-FM-URL.
Eine Möglichkeit festzustellen ob der Prozess noch läuft.
Falls nicht: Returncode und die Letzten Ausgaben des Prozesses.
Falls ja: Eine Möglichkeit ihn zu beenden. Manchmal ist Last-Exit hartnäckig und lässt sich nicht durch Schließen beenden sonder muss im nachfolgenden "Die Anwendung reagiert nicht mehr"-Dialog zwangsweise beendet werden.
last-exit in der Shell aufgerufen starte übrigends ein Script
/usr/bin/last-exit:
1 2 3 4 5 | #!/bin/bash export MONO_GAC_PREFIX=$MONO_GAC_PREFIX:/usr exec -a "last-exit" /usr/bin/mono /usr/lib/last-exit/last-exit.exe "$@" |
Grüße aus Berlin und allen Gesundheit, Glück und das alle Wünsche im neuen Jahr in Erfüllung gehen