Utrzymanie przy życiu sypiących się usług na serwerach Windows

Zdarzyło mi się kilka usług działających na serwerach Windows, które zwyczajnie sypały się i to tak brzydko że systemowe ustawienia by restartowały się po padzie nie wystarczały. Usługa działała np. 3 godziny by potem się położyć, albo nigdy nie wstawała po starcie systemu – po prostu jakaś masakra. Zgłoszenia do producenta często wyglądały tak że w jego testowym środowisku błędu nie udaje się powtórzyć (i nic dziwnego bo nie sądzę by z ich konfiguracji korzystali rzeczywiści użytkownicy). Oczywiście można zaczekać aż ukaże się magiczna łata usuwająca błąd ale do tego czasu to na nas wszyscy będą “wieszać psy” za niedostępność usługi.

W najprostszym podejściu można napisać bat’cha, który będzie restartował usługę (kładł i startował, sprawdzał czy działa i tylko przy braku działania uruchamiał, itp) – taki skrypcik odpalamy co 5 minut i powinno to załatwić sprawę. Załatwi to najprostsze przypadki – ale nie będzie całkiem elastyczne.

Szukałem programu, który działałby jako usługa i “pilnował” innych usług systemowych i… można coś takiego kupić za 200$ (sic!). Postanowiłem poszukać na forum AutoIt’a – basciopodobnego języka skryptowego, który wielokrotnie pomagał mi zautomatyzować pewne zadania administracyjne – trafiłem na tego posta: http://www.autoitscript.com/forum/topic/80201-service-udf-v2-run-your-exe-as-service/

Z tego adresu pobieramy źródła – zmieniamy nazwę pliczku ServiceExample.au3 na np. ServiceKeeper.au3 i edytujemy (szukamy linijki region –> insert your running code here:

#region --> insert your running code here

Local $status = _Service_QueryStatus("shittyservice")
If $status[1] <> $SERVICE_RUNNING Then
  If $bDebug Then logprint("shittyservice  service not running!")

  If $status[1] == $SERVICE_PAUSED Then
    If _Service_Resume("shittyservice") == 1 Then
      If $bDebug Then logprint("shittyservice service resumed successfully")
    Else
      If $bDebug Then logprint("shittyservice service resume failded!")
      If _Service_Start("shittyservice") == 1 Then
        If $bDebug Then logprint("shittyservice service started successfully")
      EndIf
    EndIf
  EndIf

  If $status[1] == $SERVICE_STOPPED Then
    If _Service_Start("shittyservice") == 1 Then
      If $bDebug Then logprint("shittyservice service started successfully")
    Else
      If $bDebug Then logprint("shittyservice service start failded!")
    EndIf
  EndIf
EndIf

Sleep(60000) # jak czesto sprawdzac san uslug - czas w milisekundach
#endregion --> insert your running code here

Powyższy przykład sprawdza czy pewna “shittyusługa” działa, a jeśli nie to podejmuje różne próby jej uruchomienia. Przykład najprostszy z możliwych ale bardzo łatwo można zamiast sprawdzenia jedne usługi powielić ten kod dla kilku usług i sprawdzać je w pętli (w wolnej chwili może wrzucę taki kod).

Skrypcik dostosowujemy do swoich potrzeb, kompilujemy i wrzucamy na serwer potrzebujący “rozrusznika”. Usługę trzeba zainstalować przez odpalenie skryptu z parametrem -i, w naszym przypadku wyglądało by to tak:

ServiceKeeper.exe -i

Usługę można odinstalować przez uruchomienie z parametrem -u.

Dobrze ustawić tą usługę by startowała z opóźnieniem. Nie wydaje mi się sensowe sprawdzanie stanu usług częściej niż raz na minutę.

Zdarzało mi się że ta usługa sypała się przy jej zatrzymywaniu (jest o tym wzmianka na forum), ale to mnie akurat mało boli bo innych problemów nie miałem.

Leave a Reply

Your email address will not be published. Required fields are marked *