2012-12-19 12 views
5

Mam aplikację python, która musi wykonać zastrzeżoną aplikację (która rozbija się od czasu do czasu) około 20 000 razy dziennie.Jak uruchomić awaryjną (rzadko) aplikację w podprocesie

Problem jest, gdy awarie aplikacji, Windows automatycznie wyzwala WerFault który będzie na bieżąco programu powieszenie, co python's subprocess.call() będzie wiecznie czekać na wejście użytkownika (że aplikacja musi pracować w weekendy, święta, 24/7 ... tak to jest nie do przyjęcia).

Jeśli choć o użyciu sleep; poll; kill; terminate ale to oznaczałoby utratę możliwości korzystania communicate(), aplikacja może działać od kilku milisekund do 2 godzin, więc ustawienie ustalony limit czasu będzie nieskuteczna

Próbowałem też turning on automatic debugging (użyć skryptu który zrób zrzut awaryjny aplikacji i zamknij id), ale jakoś to howto nie działa na moim serwerze (WerFault wciąż pojawia się i czeka na wejście użytkownika).

Kilka innych samouczków, takich jak this, również nie przyniosło żadnego efektu.

Pytanie: czy istnieje sposób zapobiegania wyświetlaniu się WerFault (oczekiwanie na wprowadzenie danych przez użytkownika)? to bardziej Następnie system programowania pytanie w

pytanie Alternatywne: czy istnieje wdzięku sposób w Pythonie, jak wykryć awarię aplikacji (czy WerFault została wyświetlona)

+0

Możesz dodać aplikację powodującą awarię do listy wykluczeń, a następnie polegać na lokalnych zrzutach dla zrzutu awaryjnego. Zobacz http://msdn.microsoft.com/en-us/library/windows/desktop/bb513617%28v=vs.85%29.aspx – nanda

+0

czy widziałeś http://stackoverflow.com/questions/5069224/handling -subprocess-crash-in-windows – n611x007

Odpowiedz

2

Proste (i brzydki) odpowiedź monitorowania WerFault.exe przypadkach od czasu do czasu, szczególnie ta związana z PID stosowania naruszającego przepisy. I zabij to. Radzenie sobie z WerFault.exe jest skomplikowane, ale nie chcesz go wyłączyć - patrz serwis Windows Error Reporting.

  1. Wyświetl listę procesów według nazwy pasujących do WerFault.exe. Używam pakietu psutil. Zachowaj ostrożność przy psutil, ponieważ procesy są buforowane, użyj psutil.get_pid_list().
  2. Dekodowanie wiersza polecenia przy użyciu argparse. Może to być przesada, ale wykorzystuje istniejące biblioteki Pythona.
  3. Określ proces, w którym znajduje się aplikacja, zgodnie z PID.

Jest to prosta implementacja.

def kill_proc_kidnapper(self, child_pid, kidnapper_name='WerFault.exe'): 
    """ 
    Look among all instances of 'WerFault.exe' process for an specific one 
    that took control of another faulting process. 
    When 'WerFault.exe' is launched it is specified the PID using -p argument: 

    'C:\\Windows\\SysWOW64\\WerFault.exe -u -p 5012 -s 68' 
          |    | 
          +-> kidnapper +-> child_pid 

    Function uses `argparse` to properly decode process command line and get 
    PID. If PID matches `child_pid` then we have found the correct parent 
    process and can kill it. 
    """ 
    parser = argparse.ArgumentParser() 
    parser.add_argument('-u', action='store_false', help='User name') 
    parser.add_argument('-p', type=int, help='Process ID') 
    parser.add_argument('-s', help='??') 

    kidnapper_p = None 
    child_p = None 

    for proc in psutil.get_pid_list(): 
     if kidnapper_name in proc.name: 
      args, unknown_args = parser.parse_known_args(proc.cmdline) 
      print proc.name, proc.cmdline 

      if args.p == child_pid: 
       # We found the kidnapper, aim. 
       print 'kidnapper found: {0}'.format(proc.pid) 
       kidnapper_p = proc 

    if psutil.pid_exists(child_pid): 
     child_p = psutil.Process(child_pid) 

    if kidnapper_p and child_pid: 
     print 'Killing "{0}" ({1}) that kidnapped "{2}" ({3})'.format(
      kidnapper_p.name, kidnapper_p.pid, child_p.name, child_p.pid) 
     self.taskkill(kidnapper_p.pid) 
     return 1 
    else: 
     if not kidnapper_p: 
      print 'Kidnapper process "{0}" not found'.format(kidnapper_name) 
     if not child_p: 
      print 'Child process "({0})" not found'.format(child_pid) 

    return 0 

Teraz taskkill funkcja wywołuje taskkill commmand z prawidłowym PID.

def taskkill(self, pid): 
    """ 
    Kill task and entire process tree for this process 
    """ 
    print('Task kill for PID {0}'.format(pid)) 
    cmd = 'taskkill /f /t /pid {0}'.format(pid) 
    subprocess.call(cmd.split()) 
+1

Bardzo ładna pierwsza odpowiedź :) Zasadniczo robię już coś takiego, ale zamiast zabijać proces powiadamam administratorów przez nagios, aby mogli utworzyć zrzut awaryjny. – Vyktor

-2

widzę żadnego powodu, co do dlaczego twój program musi się zawiesić, znaleźć obraźliwy fragment kodu i umieścić go w instrukcji try.

http://docs.python.org/3.2/tutorial/errors.html#handling-exceptions

+0

Problem dotyczy aplikacji zastrzeżonej, która ulega awarii. Nie możemy nic z tym zrobić (słaba obsługa) :( – Vyktor

+0

Awaria aplikacji - to fakt, nawet jeśli jest to Twoja aplikacja i możesz naprawić awarię, często ma to sens w przypadku awarii - w tym przypadku jest to aplikacja innej firmy. które nie mogą być naprawione i tak –

Powiązane problemy