Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2012.04.08;
Скачать: [xml.tar.bz2];

Вниз

Перезапуск службы после остановки системой   Найти похожие ветки 

 
И. Павел ©   (2011-12-16 09:37) [0]

Здравствуйте.

У меня есть служба. В администрирование->службы указал тип запуска: авто и перезапуск службы в случае ошибки. Но при остановке система не перезапускает службу.
Пробовал обернуть код в «main» функции в try/finally и назначать ExitCode := 1. Пробовал выводить исключение нуружу из OnExecute (в этом случае система пишет в журнал, что «service failure», но все равно ее не перезапускает).
Подскажите, пожалуйста, как сделать так, чтобы лыжи ехали?

Заранее спасибо.

PS: на всякий случай приведу код onExecute-метода:

procedure TSEDDeloMonitoringYITService2.ServiceExecute(Sender: TService);
var d: TDateTime;
begin
 try
   PrepareReg;

   CoInitialize(nil);
   DMQ.Connect("Provider=SQLOLEDB.1;Password=111;Persist Security Info=True;User ID=tm;Data Source=SQL-SERVER\DELO");

   MailThread := TMailThread.Create(false);

   while (not Terminated) do
   begin

     if MailThread.Finished then
       break;

     d := now;

     ShowPosDoc1;
     ReportStatus;
     ServiceThread.ProcessRequests(false);
     if Terminated then break;

     ShowPosDoc2;
     ReportStatus;
     ServiceThread.ProcessRequests(false);
     if Terminated then break;

     ShowPor;
     ReportStatus;
     ServiceThread.ProcessRequests(false);
     if Terminated then break;

     ShowNap;
     ReportStatus;
     ServiceThread.ProcessRequests(false);
     if Terminated then break;

     ShowOtch;
     ReportStatus;
     ServiceThread.ProcessRequests(false);
     if Terminated then break;

     ShowPosDoc8;
     ReportStatus;
     ServiceThread.ProcessRequests(false);
     if Terminated then break;

     SetEmailFlag;
     ReportStatus;
     ServiceThread.ProcessRequests(false);
     if Terminated then break;

     SetLastProcessing;
     ReportStatus;
     ServiceThread.ProcessRequests(false);
     if Terminated then break;

     d := now + (GetInterval — trunc((Now — d) * 24 * 60)) / 60 / 24;
     while (now < d) and (not Terminated) do
     begin
       sleep(1000);
       ReportStatus;
       ServiceThread.ProcessRequests(false);
     end;
   end;

   MailThread.Terminate;
   MailThread.WaitFor;

   CoUninitialize;
 except
   on e: Exception do
     ExceptHandler(e);
 end;
end;


 
sniknik ©   (2011-12-16 09:53) [1]

CoInitialize делается на поток... в показаном потоке сервиса что-то не видно работы с COM.
может оно конечно в Show... процедурах, но какое вообще шоу в сервисе?
работа в MailThread? (почему не освобождается кстати?)  тогда зачем ProcessRequests(false);? т.е. какой смысл возврата в основной цикл и какие то обработки, причем так часто, если "работаем" в MailThread?
не понятно, только куча лишнего кода.

> Но при остановке система не перезапускает службу.  
чтобы перезапустило, нужно чтобы служба "отвалилась", у тебя при ошибке/"зависе" в MailThread служба работает, не работает только твоя "работа".
перенеси код из дополнительного потока в основной,от службы. тогда от при сбое будет останавливаться и служба пере запускаться.


 
RWolf ©   (2011-12-16 10:15) [2]

> Но при остановке система не перезапускает службу.  

а оно вообще работает?
у меня вот служба Visual SVN Server не стартует при включении компьютера (не то, чтобы всегда — иногда и стартует). Прописываю в настройки службы перезапуск при сбое через 5 минут — всё то же самое. Приходится писать в автозагрузке net start.


 
sniknik ©   (2011-12-16 10:20) [3]

> не стартует при включении компьютера ... перезапуск при сбое через 5 минут — всё то же самое.
какой может быть перезапуск, если оно и раза то не запустилось...


 
RWolf ©   (2011-12-16 10:21) [4]


> sniknik ©   (16.12.11 10:20) [3]

а в чём принципиальная разница для пользователя? для него это тоже сбой.


 
И. Павел ©   (2011-12-16 10:25) [5]

> CoInitialize делается на поток... в показаном потоке сервиса
> что-то не видно работы с COM.

У меня в функциях &#151; по паре больших запросов к MS SQL SERVER. Выполняются примерно 1-2 сек, поэтому после этого решил обрабатывать события. Чтобы в случае чего поток откликался хотя бы 1 раз в 2 секунды.
В потоке &#151; свой CoInitialize. Поток выполняется долго, поэтому не хочу перемешивать его с основным кодом OnExecute, который выполняется быстрее но чаще.


> почему не освобождается кстати?)  

Спасибо, забыл Free сделать.

Просто хочу, чтобы система доходила до ExceptionHandler в случае чего.


> чтобы перезапустило, нужно чтобы служба &laquo;отвалилась&raquo;, у
> тебя при ошибке/&laquo;зависе&raquo; в MailThread служба работает, не
> работает только твоя &laquo;работа&raquo;.

Я пробовал в самом OnExecute генерировать исключение. И даже удалял блок except, чтобы это исключение прошло дальше. Все равно служба не перезапускается.
А если в MailThread возникает исключение, то информация о нем пишется, а потом поток останавливается. А главный поток проверяет: если дополнительный остановился, то останавливается и служба:
if MailThread.Finished then
      break;



> а оно вообще работает?
> у меня вот служба Visual SVN Server не стартует при включении
> компьютера (не то, чтобы всегда — иногда и стартует).

Служба работает. При запуске системы стартует.


> Приходится писать в автозагрузке net start.

А это идея: в крайнем случае тоже пропишу в свойствах сервиса в поле запуска программы при остановке службы команду для старта службы.


 
И. Павел ©   (2011-12-16 10:28) [6]

> Просто хочу, чтобы система доходила до ExceptionHandler
> в случае чего.

Это по поводу вопроса о том, почему я часто проверяю пришедшие события. В коде пока я этого не прописал, но в самом конце блока try еще добавлю сообщение о том, что служба собирается останавливается.


 
И. Павел ©   (2011-12-16 10:30) [7]

> [6] И. Павел ©   (16.12.11 10:28)

Т.е. если администратор или система начнут останавливать службу, хочу успеть подать об этом сигнал в журнал и на почту. Если долго не отвечать, боюсь, служба просто сбросится системой.


 
Anatoly Podgoretsky ©   (2011-12-16 10:36) [8]

> sniknik  (16.12.2011 09:53:01)  [1]

Сказал бы проще = переписать все нафиг


 
sniknik ©   (2011-12-16 10:53) [9]

> а потом поток останавливается.
именно что останавливается, в этом случае, даже по  
 except
   on e: Exception do
     ExceptHandler(e);
 end;
идет нормальное (с точки зрение менеджера служб) завершение, т.е. служба все свое сделала и остановилась.

или тоже
> в чём принципиальная разница для пользователя?
так? вы не свои принципы отстаиваете, вы пишете под мелкосовтские...

> Сказал бы проще = переписать все нафиг
как обычно, это по умолчанию. меняются только объяснения почему...


 
sniknik ©   (2011-12-16 10:55) [10]

if MailThread.Finished then
      break;

if MailThread.Finished then
      raise ....;


 
знайка   (2011-12-16 10:58) [11]

А отложенный запуск (Delayed Start) пробовали ставить?
Иногда не все еще стартонуло, и надо ждать. Например у нас так с базой, наш сервис пытается стартовать раньше, при запуске системы, поэтому включили отложенный запуск.


 
Anatoly Podgoretsky ©   (2011-12-16 11:42) [12]

> RWolf  (16.12.2011 10:15:02)  [2]

Видимо сеть или что то другое хочет, а этого еще нет


 
Сергей М. ©   (2011-12-16 12:34) [13]


> при остановке система не перезапускает службу


Она же шатно остановилась, а не упала аварийно ..
С чего бы системе ее перезапускать ?


 
И. Павел ©   (2011-12-16 12:39) [14]

> if MailThread.Finished then
>      break;
> if MailThread.Finished then
>      raise ....;


> Она же шатно остановилась, а не упала аварийно ..
> С чего бы системе ее перезапускать ?


Я делал через raise. При этом удалял блок except. Все равно не востанавливается.


> [11] знайка   (16.12.11 10:58)

Именно не перезапускается, т.е. даже если запустить вручную, нажав кнопку &laquo;запуск&raquo; в свойствах службы &#151; все равно не перезапускается после останова.


 
Сергей М. ©   (2011-12-16 12:58) [15]

> Я делал через raise

Этот raise не имеет отношения к необработанным исключениям ОСНОВНОГО треда сервис-приложения, которые могут привести к его аварийному падению и , соотв-но, к перезапуску приложения системой.


 
знайка   (2011-12-16 13:11) [16]


> Именно не перезапускается
Ну как уже говорили, при штатной остановке система ее не перезапустит.
А так у вас какая-то неправильная служба, если она не 24/7 то это и не служба вовсе. :)


 
И. Павел ©   (2011-12-16 14:45) [17]

> [16] знайка   (16.12.11 13:11)

Просто я пока только тестирую службу. Но, скорее всего, на перезапуск поставлю так, как вы сказали, т.к. должны запуститься как минимум драйверы MS SQL.


> [15] Сергей М. ©   (16.12.11 12:58)

raise после Application.Run тоже не помогает...

Я создал новый проект службы, после Application.Run добавил raise. В OnExecute единственной службы проекта написал простой код ожидания 1 минуту и завершения:

var i: integer;
begin
 for i := 1 to 60 do
 begin
   sleep(1000);
   ReportStatus;
 end;

 raise Exception.Create("Error Message");


Но эта служба, отработав 1 минуту и завершившись, не запускается снова через 1 мин, хоть в ее настройках я это указал...

Если у кого-нибудь есть пара свободных минут, попробуйте сделать такой-же проект. Перезапускается ли служба? Пока пишу на Delphi XE. Не думаю, что в Delphi 7 что-то изменится, но сейчас установлю его и попробую сделать то же самое. OC: Windows 7.

Вот архив с проектом простой службы для Delphi XE, о которой я говорил: http://ifolder.ru/27620988


 
Сергей М. ©   (2011-12-16 15:20) [18]


> отработав 1 минуту и завершившись, не запускается снова
> через 1 мин


Да с чего ей запускаться-то заново ?! С т.з. системы она завершилась вполне штатно, а не аварийно ! Какое системе дело до того что приложение завершило выполение в результате обработки им исключения пользовательского уровня ?
В приложении отработал глобальный (неподконтрольныйтебе) SEH вернего уровня, он штатно "погасил" твое исключение и завершил приложение - разве это авария ?


 
И. Павел ©   (2011-12-16 15:32) [19]

> [18] Сергей М. ©   (16.12.11 15:20)

Ясно.
А как сделать аварию? Чтобы Windows сам перезапустил службу?


 
Сергей М. ©   (2011-12-16 15:37) [20]


> как сделать аварию?


Зачем ее вообще делать ? Глупее затеи не выдумать)
Сделай высоконадежный сервис-гвардеец - и пусть он следит за жизнью основного сервиса и перезапускает его в случае нештатного останова.


 
И. Павел ©   (2011-12-16 15:50) [21]

> Зачем ее вообще делать ? Глупее затеи не выдумать)
> Сделай высоконадежный сервис-гвардеец &#151; и пусть он следит
> за жизнью основного сервиса и перезапускает его в случае
> нештатного останова.

Но за этим гвардейцем тоже нужно будет следить. Даже если он будет надежным, он все равно может дать сбой. А если и он не будет уведомлять систеу о том, что завершается с ошибкой (как и программа, за которой он следит), то он тоже может остановиться без перезапуска.

Подскажите, пожалуйста, можно ли как-нибудь написать надежный сервис, который информирует систему об ошибке или формирует ошибку при любом своем завершении, так чтобы его всегда перезапускали? Или может быть настроить сервис так, чтобы система перезапускала его даже в случае корректного завершения?


 
И. Павел ©   (2011-12-16 15:53) [22]

> [21] И. Павел ©   (16.12.11 15:50)

Просто я специально переписал программу в  службу, рассчитывая, что это позволит выполняться ей в режиме 24/7. А если что-то пойдет не так, система ее перезапустит.


 
Сергей М. ©   (2011-12-16 15:59) [23]


> это позволит выполняться ей в режиме 24/7


Зачем же ты тогда не гасишь исключение, сознательно выпуская его наружу ?
Не выпускай, обрабатывай - и будет он в режиме 24/7.
А если не будет, то это и есть авария - вот тогда SCM его перезапустит. Если он сам к этому моменту не труп)


 
И. Павел ©   (2011-12-16 16:08) [24]

> [23] Сергей М. ©   (16.12.11 15:59)

Просто это проблематично, т.к. для какого-то исключения нужно переподключаться к базе данных а другое просто пропустить и повторить действие в следующей итерации, третье может потребовать пересоздать какие-то объекты, сперва их удалив (что, в свою очередь, тоже может вызвать исключение) и т.д.

Тогда как лучше организовать процесс обработки исключений?
Организовывать в OnExecute цикл, внутри которого будет try/except? Или можно сделать этот цикл на уровне &laquo;main&raquo; файла программы? Скажем, постоянно вызывая Application.Run?

И еще: может все-таки можно как-нибудь средствами Delphi сказать системе, что сервер останавливается с ошибкой и его нужно перезапустить?


 
Сергей М. ©   (2011-12-16 16:10) [25]


> ак лучше организовать процесс обработки исключений?


Как всегда - анализируя объект-исключение.


 
Anatoly Podgoretsky ©   (2011-12-16 16:22) [26]

> И. Павел  (16.12.2011 15:53:22)  [22]

Но ты то хочешь после остановке системой, а этого не будет. Система может
перезагрузить только после краха


 
И. Павел ©   (2011-12-17 12:09) [27]


> Сергей М. ©   (16.12.11 16:10) [25]
> Anatoly Podgoretsky ©   (16.12.11 16:22) [26]

Теперь понимаю. Должно быть не exception а что-то посерьезнее. И сказать системе, что сервис Delphi завершился крахом не получится... А вручную устраивать крах (например, stack overflow с помощью рекурсии) ради того, чтобы перезагрузить сервис, это не дело... (хотя - как запасной вариант может и сгодится :)

Но может быть можно как-нибудь упростить рестарт сервиса после ошибки? Например, внутри проекта-сервиса? Как-то хитро написать main-функцию. Или все же единственный выход: делать все вручную? Ведь если не перезапускать сервис, нужно будет волноваться о том, что не все ресурсы освободились...

Если восстанавливать сервис после сбоя вручную, то пока что единственное, что мне приходит в голову, это организовать обработчик OnExecute сервиса следующим образом:

procedure TSEDDeloMonitoringYITService2.ServiceExecute(Sender: TService);
begin
 while true do
 begin
   <всем ресурсам сервиса (потокам и т.д.) присваиваю nil>
   try
     try
       <инициализирую ресурсы сервиса (например - создаю и запускаю потоки и т.д.)>
       while not Terminated do
       begin
         <тут происходит основной цикл работы сервиса>
       end;
     except
       on e: Exception do
         <тут сообщаю об ошибку: пишу в журнал, отсылаю email и т.д.>
     end;
   finally
     <проверяю, если какой-то ресурс сервиса <> nil, то очищаю его (если поток - то перед очищением шлю команду на завершение и waitfor)>
   end;  
 end;
end;


Подскажите, пожалуйста, есть ли какой-нибудь другой способ перезапуска или просто восстановления сервиса после ошибки (имею ввиду exception, а не системный сбой)?


 
sniknik ©   (2011-12-17 13:02) [28]

> способ перезапуска
WinSvc OpenSCManager OpenService SERVICE_START
перед выходом...
например в проекте
 Application.Run;

 if isNeedRun then
   StartService(selfName); //функция написаная с использованием вышеперечисленного


 
sniknik ©   (2011-12-17 13:03) [29]

+, пропустил в конце - StartService


 
И. Павел ©   (2011-12-17 19:06) [30]


> sniknik ©

Большое спасибо. Так и сделаю.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2012.04.08;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.009 c
2-1324306539
rilmeer
2011-12-19 18:55
2012.04.08
програмное заполнение Tibtable.locate


15-1323231809
кирилл
2011-12-07 08:23
2012.04.08
для лисенка


15-1322688602
Юрий
2011-12-01 01:30
2012.04.08
С днем рождения ! 1 декабря 2011 четверг


15-1323312036
Slider007
2011-12-08 06:40
2012.04.08
Поиск работы продолжается


6-1254820466
Tailor_McMaffin
2009-10-06 13:14
2012.04.08
SetupAPI -> GUID устройства





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский