Script terminiert nicht

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
lill
User
Beiträge: 8
Registriert: Mittwoch 8. Dezember 2010, 12:03

Hallo,

habe folgendes Problem.
Mein Vorgängerpraktikant sollte damals ein Backupscript schreiben. Ist alles ganz "toll" und so, nur terminiert es nicht.
Wenn ich es mittels "./clientbackup.py" aufrufe, terminiert es ohne Probleme.
Jedoch bei "python clientbackup.py", mag das Script nicht zu ende laufen.
Nach "tausenden" print-Ausgaben habe ich herausgefunden, dass es am os._exit(0) lag (mit dem ich die Kindsprozesse beenden wollte).
Nachdem ich os._exit(0) in os.EX_OK geändert habe, lief das Script ein Stück weiter und blieb bei sys.exit(0) hängen.

Grob aufgebaut ist das Script wie folgt:

Code: Alles auswählen

import os, sys
def main():
  try:
    ...
    pid = os.fork()
    if pid == 0:
      ...
      os.EX_OK
    else:
      ...
    ...
    print "bis hierher geht alles"
    sys.exit(0)
  except KeyError:
    ...
  except KeyboardInterrupt:
    ...
    sys.exit(1)

if __name__ == "__main__":
  main()
Folgendes habe ich noch ausprobiert:
* sys.exit(0) hinter die try-Anweisung -> kein Unterschied
* zusätzlich noch ein except SystemExit, e: sys.exit(e) -> kein Unterschied
* mit python -v ausgeführt -> cleanup main läuft durch
-> bei cleanup sys bleibt's hängen
# cleanup sys
# cleanup __builtin__
# cleanup ints: 39 unfreed ints in 4 out of 19 blocks
# cleanup floats: 30 unfreed floats in 1 out of 3 blocks

Weitere Infos:
python -V
Python 2.4.3
cat /etc/redhat-release
Red Hat Enterprise Linux Server release 5.6 (Tikanga)

Wäre echt nett, wenn mir jemand weiterhelfen könnte.

Grüße lill
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Bin mir nicht sicher, ob das jetzt auf die Beschreibung passt, aber du musst den Fork manuell terminieren (ein SIGTERM-Signal hinschicken oder zur Not SIGKILL), sollte er das nicht irgendwann selbst tun.
lunar

Zeige bitte ein minimalen, lauffähigen Quelltext, der das Problem reproduziert, ohne irgendwelche Auslassungen und Mutmaßungen darüber, wo der Fehler liegen könnte.
lill
User
Beiträge: 8
Registriert: Mittwoch 8. Dezember 2010, 12:03

@Dauerbaustelle
Sorry, da ich davon ausgegangen bin, dass das nicht das Problem sei, habe ich den Teil aus meinem "Codebeispiel" rausgelassen:

Code: Alles auswählen

def killAllChilds(childIDs):
  name=sys.argv[0].lstrip('./')
  name=name[0:15]
  proc_table=commands.getoutput('ps -a').split('\n')
  for childID in childIDs:
    for line in proc_table:
      if line.startswith(str(childID)) and line.count(name) > 0:
        os.kill(childID,signal.SIGKILL)
Viele Grüße lill
Benutzeravatar
ts7343
User
Beiträge: 69
Registriert: Mittwoch 5. Mai 2010, 13:48

ist vielleicht nicht besonders originell, aber wenn es keiner sonst merkt,
dann hold dir die process ids als STDOUT mit subprocess rein und kill sie dann,

ps -fu <user_name> | grep python

kill -9 <process_id>
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Das Problem liegt vermutlich eh woanders.
lill
User
Beiträge: 8
Registriert: Mittwoch 8. Dezember 2010, 12:03

So, ist nicht ganz so minimal geworden, aber das Problem ließ sich nicht so einfach "nachbauen".

http://pastebin.com/KuMDRNsh

Grüße lill
lill
User
Beiträge: 8
Registriert: Mittwoch 8. Dezember 2010, 12:03

hab das Problem gefunden. Endlosschleife.

Also, das Problem:
Aufruf über
./clientbackup.py -> funktioniert
python clientbackup.py -> funktioniert nicht

Begründung:
Wenn ich das Script mittels ./clientbackup.py aufrufe, heißt der Prozess clientbackup.
Wenn ich das Script mittels python clientbackup.py aufrufe, heißt der Prozess python.

Da ich nach dem Namen des Scripts in der Prozessliste suchen, wird beim oberen Aufruf der Eintrag in der Prozessliste gefunden und beendet.
Beim unteren dementsprechend nicht.

Danke für die Hilfe
Gruß lill
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Reicht ein einfaches 'os.wait()' am Ende des Elternprozesses nicht aus (Vorrausgesetzt deine fork's laufen nicht unendlich lang).

Alternativ tuts doch sowas:

Code: Alles auswählen

for child_id in child_ids: #gibt's wirklich mehr als ein 'child'?
    os.kill(child_id, signal.SIGKILL) # SIGTERM reicht nicht?
hth, Jörg

ps.: Wenn irgendwie möglich (nötig?!), steig auf das multiprocessing-modul um.
BlackJack

Also ich finde ja auch das diese Funktionen die ``ps`` aufrufen komisch und sehr zerbrechlich aussehen.

Ein `wait()` auf die PIDs wäre sauberer und einfacher und wenn man schon mit der Prozessliste hantieren muss, würde ich das `psutil`-Modul installieren. Das ist robuster als die Ausgabe von ``ps`` zu verarbeiten und ausserdem plattformunabhängiger.
lill
User
Beiträge: 8
Registriert: Mittwoch 8. Dezember 2010, 12:03

Momentan ist es nicht meine Aufgabe, das Script zu optimieren.
Ich sollte es lediglich zum Laufen bringen. Mein Praktikum endet bald und ich werden mit weiteren Aufgaben überhäuft.
Trotzdem danke für die Tipps, ich werde diese weitergeben.
Antworten