Автоматический перезапуск службы агента сервера 1С Предприятия 8.

21.02.11

База данных - Инструменты администратора БД

Решение проблемы с утечками памяти рабочих процессов сервера 1С Предприятия средствами операционной системы.

Известно, что при функционировании рабочих процессов сервера 1С Предприятия 8.1 rphost.exe существует следующая проблема: из-за особенностей платформы, с подключением каждого нового клиента к рабочему процессу, увеличивается размер занимаемой рабочим процессом оперативной памяти. При этом, при отключении клиента, занимаемый при подключении объем не освобождается. Так же объем памяти, занимаемый рабочим процессом может увеличиваться при выполнении программного кода. Данное поведение называется “Утечками памяти” или “Memory Leaks”. В итоге, когда объем занимаемой памяти процессом rphost.exe вырастает больше опеределенного предела (в моем случае это было >1Gb), рабочий процесс безусловно перезапускается. Понятно, что клиенты, подключенные к этому процессу, получают сообщение, что соединение с сервером разорвано, прекращают работу и вынуждены переподключаться. В зависимости от количества пользователей и количества запущенных рабочих процессов, данная проблема возникает с той или иной частотой. В моем случае - пользователей порядка 60 и один рабочий процесс, подобная ситуация возникала до 5 раз в неделю. Т.е. ни о какой стабильной работе системы 1С Предприятие в этом случае речь не идет.

Первым шагом решения проблемы было - увеличить количество рабочих процессов, что и было сделано. Однако, проблему это решило лишь отчасти, перезапуски рабочих процессов стали происходить реже, но не исчезли совсем.

Второй и вполне логичный шаг - автоматический перезапуск процессов на сервере, о чем, собственно, и хочется написать.

Поскольку служба агента сервера 1С Предприятия представляет собой стандартную службу, в арсенале Windows есть стандартный способ остановки и запуска служб из командной строки командами net stop и net start. Достаточно эти команды лишь включить в bat-файл и настроить шедулер на запуск bat-файла по расписанию, я настроил перезапуск один раз в сутки, в ночное время. Следует иметь ввиду, что если перезапускать рабочие процессы в рабочее время, все подключенные к серверу 1С Предприятия клиенты будут отключены!
Кроме того, чтобы немного разнести по времени команды остановки и запуска службы, будем использовать известную утилиту sleep.exe, которую легко найти в Сети.

Примерный текст bat-файла restart1c.bat:

rem @echo off
rem \\----- начало скрипт остановки и запуска агента сервера 1С Предприятия----\\
set logfile="stopstartlog.txt"
set timeout=20
echo %date% %time% >>%logfile%
net stop "1C:Enterprise 8.1 Server Agent" >>%logfile%
c:\scripts\sleep %timeout%
echo %date% %time% >>%logfile%
net start "1C:Enterprise 8.1 Server Agent" >>%logfile%
c:\scripts\sleep %timeout%
rem \\----- конец скрипт остановки и запуска агента сервера 1С Предприятия----\\

Объяснение используемых переменных и команд:
* logfile - файл stopstartlog.txt, куда будут записываться результаты выполнения команд, размещается в том же каталоге, что и сам bat-файл;
** timeout - время в секундах;
*** c:\scripts - каталог, где предполагается разместить программу sleep.exe, bat-файл и лог-файл;

Из этого же bat-файла можно сразу после перезапуска процессов запускать скрипт бэкапа средствами 1С Предприятия. В этом случае у вас гарантированно не будет подключен ни один клиент.
Необходимая ремарка: у пользователя, под которым будет выполняться задание по перезапуску службы должны быть соответствующие права на остановку и запуск служб сервера.

 

Источники:

- материалы форума www.mista.ru;

- Документация по платформе 1С Предприятие 8.1;

- Документация по продуктам MS Windows;

См. также

Автоподбор ролей для профилей и групп доступа в любых типовых базах 1С УТ 11, КА 2, ERP2, Розница 2/3, УНФ 16/3, БП 3, ЗУП 3 и подобных (УФ, Платформа 8.3.14+)

Инструменты администратора БД Роли и права 8.3.14 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Документооборот 1С:Зарплата и кадры государственного учреждения 3 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Платные (руб)

Роли… Вы тратите много времени и сил на подбор ролей среди около 2400 в ERP или 1500 в Рознице 2, пытаясь понять какими правами они обладают? Вы все время смотрите права в конфигураторе или отчетах чтоб создать нормальные профили доступа? Вы хотите наглядно видеть какие права дает профиль и редактировать все в простом виде? А может хотите просто указать подсистему и дать права на просмотр и добавление на объекты и не лезть в дебри прав и чтоб обработка сама подобрала нужные роли? Все это теперь стало возможно! Обновление от 15.12.2023, версия 1.1.

12000 руб.

06.12.2023    2971    13    1    

34

SALE! 20%

Infostart УДиФ: Управление данными и формами

Инструменты администратора БД Инструментарий разработчика Роли и права Платформа 1С v8.3 Конфигурации 1cv8 Россия Платные (руб)

Расширение позволяет без изменения кода конфигурации выполнять проверки при вводе данных, скрывать от пользователя недоступные ему данные, выполнять код в обработчиках. Не изменяет данные конфигурации, легко устанавливается практически на любую конфигурацию на управляемых формах.

10000 8000 руб.

10.11.2023    3514    11    1    

33

SALE! 30%

PowerTools

Инструментарий разработчика Инструменты администратора БД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Россия Платные (руб)

Универсальный инструмент программиста для администрирования конфигураций. Сборник наиболее часто используемых обработок под единым интерфейсом.

3600 2520 руб.

14.01.2013    177730    1073    0    

849

Ускоренное проведение документов (x4), устранение ошибок 60/62 счетов и зачет авансов (Бухгалтерия 3.0)

Закрытие периода Инструменты администратора БД Корректировка данных Бухгалтерский учет 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Платные (руб)

Расширение «Оперативное проведение» в 4 раза уменьшает время проведения документов и закрытия месяца. Является комплексным решением проблем 62 и 60 счетов. Оптимизирует проведение при включенной функциональной опции «Раздельный учет НДС». Используется в более 10 организациях уже 2 года. Совместимо с конфигурацией Бухгалтерия 3.0 (+КОРП).

14400 руб.

29.04.2020    27373    79    146    

59

Система хранения присоединенных файлов в томах на диске

Инструменты администратора БД Платформа 1С v8.3 1С:Комплексная автоматизация 1.х 1С:Управление производственным предприятием Платные (руб)

Конфигурация Комплексная автоматизация 1.1 (и УПП 1.3 тоже) хранит файлы и изображения в справочнике Хранилище дополнительной информации в реквизите Хранилище типа ХранилищеЗначений. Та же история с ВложениямиЭлектроннойПочты. Но при этом присоединенные файлы в Электронном документообороте хранит в томах на диске. Эта доработка позволяет использовать стандартный механизм хранения файлов, изображений и вложений электронных писем в томах на диске. При этом можно разделить тома хранения по объектам конфигурации.

4200 руб.

10.11.2015    61313    88    59    

73

"Менеджер потоков 2.1": УПП: "Восстановление партий"

Инструменты администратора БД Платформа 1С v8.3 1С:Управление производственным предприятием Россия Бухгалтерский учет Управленческий учет Платные (руб)

Как оптимизировать то, что, считалось, не поддается оптимизации? Как повысить доступность базы данных? Как проводить самую «времяемкую» операцию не по паре раз в неделю, а по несколько раз в день*? Ответ есть!

20000 руб.

12.09.2019    11745    5    9    

7

Брандмауэр для сервера 1С Предприятие 8 - внешнее управление сеансами

Инструменты администратора БД Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

Управление возможностью начала и возобновления сеансов пользователей по различным условиям, ограничение общего числа возможных сеансов для работы с информационной базой, резервирование возможности работы с информационной базой определенных польззователей, запрет запуска нескольких сеансов для пользователя, журнализация событий начала (возобновления) и завершения (гибернации) сеансов, ведение списка активных сеансов для информационных баз кластера серверов

3600 руб.

06.02.2017    31106    31    18    

47

Хранилище файлов на SQL

Инструменты администратора БД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Управленческий учет Платные (руб)

Привязка файлов / сканов к объектам 1С с сохранением их на SQL-сервере

12000 руб.

09.10.2019    10980    5    8    

9
Внимание! Тема закрыта. Добавлять сообщения в закрытую тему запрещено.
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Ish_2 1104 21.02.11 19:18 Сейчас в теме
Осталась мелочь :
написать для во время выполнения каких операций перезапуск агента нежелателен.
2. AlexS2 153 21.02.11 19:43 Сейчас в теме
В принципе, в статье упомянуто, что в рабочее время "баловаться" с перезапуском службы не рекомендуется :)
Или считаете, что этого не достаточно? :)
З.Ы. Спасибо за +
3. cool.vlad4 2 22.02.11 10:48 Сейчас в теме
:D ничего против не имею...но как-то печалит постоянно снижающийся уровень статей на ИС...для того, чтобы "самому дойти" до информации в этой статье уйдет не более 5-10 минут ...
4. Ish_2 1104 22.02.11 11:08 Сейчас в теме
(3) Всегда завидовал умным и проницательным.
А я вот только сейчас стал думать о том , что предложенный автором "убойный" вариант отключения всех пользователей всех баз на сервере в моём случае , возможно самый оптимальный.
5. cool.vlad4 2 22.02.11 11:27 Сейчас в теме
(4) :D не знаю...офф я вот завидую людям из жарких стран ибо для меня сейчас холодильник отопительный прибор...насчет варианта в статье - это то что мне сразу в голову пришло...любой системный администратор должен знать команду net
PS добавлю, перед перезапуском советую проверять наличие сетевых соединений с сервером, а то меня как то раз чуть не убили :D ...
6. Ish_2 1104 22.02.11 12:01 Сейчас в теме
(5) Так ставится цель именно отрубить всех пользователей.
7. AlexS2 153 22.02.11 15:16 Сейчас в теме
Ish_2 пишет:

(5) Так ставится цель именно отрубить всех пользователей.

На самом деле, задача ставится несколько другая.. ))
9. Ish_2 1104 22.02.11 16:12 Сейчас в теме
(7) Решаются две задачи : освобождение памяти и отрубить контрагентов.
Как давно и на каких конфигурациях используется такое решение ?
10. AlexS2 153 22.02.11 17:56 Сейчас в теме
Ish_2 пишет:

(7) Решаются две задачи : освобождение памяти и отрубить контрагентов.
Как давно и на каких конфигурациях используется такое решение ?

Данное решение эксплуатируется более 3-х лет, платформа 8.1.15. Конфигурация специализированная не производства 1С, похожая на комплексную + документооборот.
Отрубить пользователей - задача вторичная, на самом деле. Первично - перезапуск службы. А отключение - просто удачный "побочный эффект". :)
8. cool.vlad4 2 22.02.11 15:34 Сейчас в теме
Как мне казалось, делается это с целью освободить память от жестоких пыток 1С. У утечок разные причины бывают. И иногда без бубнов и танцев с перезапуском сервера 1С не получается. а чтобы пользователей отрубить - вроде средства другие. У 1С вроде параметр командной строки даже есть для этого.
11. aspirator23 339 23.02.11 16:29 Сейчас в теме
(8),(9),(10) А почему нельзя использовать штатный перезапуск rphost?
12. speshuric 1326 24.02.11 09:12 Сейчас в теме
1. Есть штатный (1С-ный) перезапуск rphost, как уже подсказали в (11) (перезапуска rmngr и ragent нету, но и не нужно до 300-500 пользователей).
2. Перезапускать всю службу слишком жестоко.
3. Лучше не net start, а sc (если уж службу)
4. Лучше вообще не через cmd, а через VBS (с контролем соединений)
5. Поставить нормальный сервер (гигов 16-32, на крайняк 8) и 64-бит. Пусть хоть заутекается - можно спокойно решать вопросы, где утекает.
6. Найти проблему в прикладном коде из-за которой происходит утечка.
FlagmanGK; Светлый ум; Yurkiss; Fuego; +4 1 Ответить
23. echo77 1868 26.02.11 16:41 Сейчас в теме
(11)(12) А можно поподробнее про штатный перезапуск 1С(перезапуск rphost)?

(0) Скрипт у вас сложный. Так обычно пишут:
net stop "Агент сервера 1С:Предприятия 8.1" && net start "Агент сервера 1С:Предприятия 8.1"

Посредине можете вставить паузу, если она вам нужна :-/
Паузу без sleep'ов делают так:
ping localhost -n <кол-во секунд> >nul
vindsor; JohnConnor; ketr; cool.vlad4; +4 Ответить
24. aspirator23 339 26.02.11 18:40 Сейчас в теме
(23) Запускаешь консоль управления сервером. Становишься на кластер. Правая кнопка мыши - свойства. Последние два поля для 8.1. Для 8.2 обрамлено в рамке.
13. volsh77 17 25.02.11 08:11 Сейчас в теме
Юзаю, подобный перезапуск месяцев 5 :)) , нормально все, в ночное время.
14. vovchai 25.02.11 09:47 Сейчас в теме
вместо костыля sleep.exe можно использовать конструкцию start /wait, типа start /wait net stop "1C:Enterprise 8.2 Server Agent"
15. vovchai 25.02.11 10:00 Сейчас в теме
speshuric пишет:
Найти проблему в прикладном коде из-за которой происходит утечка.

в каком каком коде? предлагаете СКД переписать? у меня может пользователь закрутить типовой отчет на СКД по валовке за года два и все, сервер 8.2 сожрал >1Гб, рестарт. причем на построителе в 8.0 такого не было. в каком коде искать то проблему? да, и кстати сервер предприятия нормальный, 16 гиг ОЗУ
16. speshuric 1326 25.02.11 14:34 Сейчас в теме
(15) А что на нормальном сервере делает 32-битный сервер предприятия (судя по вылету после 1 ГБ)?
Если проблема с формированием типового отчета, который возвращает немного строк, то такого происходить не должно, стоит пытаться решить проблему через v8@1c.ru - не быстро (около 2-3 месяцев, если действительно ошибка в платформе), но можно. Если отчет возвращает больше 300к-500к строк, то бить по рукам пользователей или вытаскивать "онолитегов" (если уж они так нужны) в отдельную базу (а её в отдельный процесс/кластер/службу/железку).
В большинстве случаев всё нормально находится - кто и зачем сожрал, почему не отдал, как решить или временно обойти проблему и т.п. Пожалуй, единственная действительно плохо решаемая проблема - большие и глубокие иерархические выборки, особенно если в совокупности с детализацией РН/РБ по мелким периодам.
17. vovchai 25.02.11 17:43 Сейчас в теме
(16) покупали с сервером под 8.0 когда 8.1 еще не вышел, а 8.2 и в помине не было. сейчас какбэ накладно покупать х64 ключ сервера предприятия (апгрейда как я знаю нет) и саму х64 ОС. проще рестарт службы делать :)

большие и глубокие иерархические выборки, особенно если в совокупности с детализацией РН/РБ по мелким периодам.

вот это как раз и присутствует (продовольственная розница с 40 тыс. элементов справочника номенклатуры) + разрезы по датам, магазинам и т.д.
завтра буду до 8.2.13.205 обновляться, посмотрим, может поможет
18. speshuric 1326 25.02.11 18:33 Сейчас в теме
(17) (апгрейда как я знаю нет) - его отменили? Цены, правда, слегка поменялись, но апгрейд есть. Для совместных продуктов MS+1C сложнее, но как я помню тоже был апгрейд. Если у Вас 32-битная ОС, то вам тем более пора её апгрейднуть на 64-битную. В 32-битной ОС rphost не вылезает за 2 ГБ выделенной памяти, а в 64-битной доступно почти 4 даже без перехода на 64-битный сервер.
40к номенклатуры как бы и немного, но если это завёрнуто в 7-8 уровней иерархии и в отчет выгребается ВСЁ, то тогда конечно, поломается. Хотя я сомневаюсь, что аналитик тут что-то с отчетом сделает. Но тут проще потратить около 50000 рублей (это меньше, чем полмесяца нормального спеца в Москве, меньше, чем месяц, в других мегаполисах: спб, екб, нск) и проапгрейдить платформу и ОС.
19. aspirator23 339 26.02.11 11:41 Сейчас в теме
(18) А как идентифицировать причины этих вылетов? Какой отчет или хотя бы какой пользователь или его действия?
У нас больше 40 баз. Все небольшие 3-6ГБ, и пользователи(около 50) "разбросаны" по базам. Платформа 8.1
Сервер 1с 64х памяти 16 ГБ.Процессоров 8. сетевая карта 1ГБ/с.
rphost, согласно рекомендации 1с - 8штук. rphost растут, но в рамках, к обеду 0.9-1.2ГБ.
Раз в квартал сервер даже в дамп может упасть.
Технологический журнал включен. Примерно видно, когда вылетает. И примерно понятно что происходит: в CONN в этот момент виден массовый поток запросов. Но как идентифицировать кто его спровоцировал? Видны только порты через какие идут эти запросы
И странно что массовое перепроведение в одной из баз может привести к вылету других пользователей из других баз. Очевидно тут дело в каком rphost сидели эти пользователи. Гилев как-то высказывал мысль что нужен только один rphost, но без комментариев. Стремно, что при падении могут вообще все пользователи отваливаться.
Трехмесячная переписка с 1с - жевание мочала. Отправлял технологический журнал, дампы. Получил пожелания перейти на 8.2 - с предположением что возможно будет лучше.
20. speshuric 1326 26.02.11 12:04 Сейчас в теме
(19) Примерно:
1. Можно попробовать сделать несколько кластеров или даже агентов (с агентами делается аналогично тому как на ИТС пишется о запинывании 1С 8.1 и 8.2 на одном сервере). А рабочих процессов - меньше (2-4-6) или столько же. Таким образом почти снимется взаимозависимость баз. С точки зрения памяти я видел rphostы и по 6 ГБ памяти съевшие - нормально работают.
2. Надеюсь СУБД на другой железке? Если на той же, то 16 ГБ - копейки. 1ГБит тоже уже не считается "много" (хотя часто и достаточно)
3. Диагностика. Рыть, рыть и еще раз рыть.
- По счетчикам производительности выявить кто тормозит: СУБД, сервер предприятия или клиент
- По полному ТЖ (блииин, какие же они ОГРООМНЫЕ) на сервере несложно понять (если получается прочитать - бугага) кто и почему порождает запросы. Ну и понятно, что дисковая подсистема уже начинает играть роль для такого режима.
- По полной трассе SQL тоже можно найти часть узких мест
В случае если узкое место сервер предприятия, то счетчики/ТЖ/ЦУП.
4. Действительно, в 1С 8.1 много проколов, которых нет в 8.2. Но в 8.2 есть зато свои проколы, которых нет в 8.1. В 8.1 мне очень не нравится:
- как работает получение списка соединений пользователей. Если оно делается программно и часто, то это ужас.
- ужасно работает получение изменений планов обмена через ВыбратьИзменения()/ПолучитьИзменение(). Да и вообще все объекты типа СправочникВыборка/ДокументВыборка ужасно работают
- мы нарвались на ппц неправильную работу "ПрекратитьРаботуСистемы"
5. Тупо прочекать, что всё свежее: драйвера (давеча на тестовом сервере неделю коллеги мучались искали проблему, оказалось драйвера необновленные), СП для ОС, СП для SQL (плюс куммулятивные обновления!). Тупо прочекать, что антивирус не мешает. Тупо прочекать, что регламенты для СУБД делаются. Тупо прочекать, что в журналах событий приложений и системы не "красно".

В общем-то скучная и будничная работа.
Yurkiss; aspirator23; +2 Ответить
21. aspirator23 339 26.02.11 14:01 Сейчас в теме
(20) На независимых форумах можно получить более квалифицированный ответ чем в 1с, где все боятся как бы чего не ляпнуть лишнего, что может повредить имиджу.
Насчет кластеров тоже стал подумывать. Даже пару сделал, переведя на них часть баз. Действительно стабильнее работают. Остальная информация тоже очень полезная - есть направление куда рыть.
22. aspirator23 339 26.02.11 14:14 Сейчас в теме
(20) Спасибо.
Вот эту фразу можно прокомментировать подробнее
...А рабочих процессов - меньше (2-4-6) или столько же. Таким образом почти снимется взаимозависимость баз....
Почему при малом количестве процессов снимается взаимозависимость баз? Я то думал обратное: пользователи разбросаны по процессам и если один процесс сбросит, то сбросит только "своих". Пользователи в других процессах останутся "в живых". Или имеется ввиду,то что пользователи сидят на разных кластерах?
25. speshuric 1326 26.02.11 22:20 Сейчас в теме
(22)Или имеется ввиду,то что пользователи сидят на разных кластерах? - Именно. Можно даже на разных ragent.
aspirator23; +1 Ответить
26. a-novoselov 1155 30.05.11 10:00 Сейчас в теме
(0) не проще "timeout /t %timeout% /nobreak >nul" вместо "c:\scripts\sleep %timeout%" использовать? тогда и в сети ничего искать/качать не прийдется.
27. Fuego 462 30.05.11 11:21 Сейчас в теме
а кто сказал, что 20 секунд хватит, или что вообще за определенное время служба остановится? все команды системы возвращаются сразу после отправки сервису команд start|stop. И если сервис не успевает выгрузиться и при этом получает команду start, он прекращает перезапуск. Я использовал когда-то таймаут, но это подвело меня в самый неподходящий момент. Именно поэтому я для этих целей дописал программулю, которая посылает команду службе, и дожидается, пока та выполнится. И только после этого я посылаю (в пакетном режиме) команду start. Таким образом я отключаю агент 1С:82, потом скуль (заодно - он тоже отжирает порой память), затем запускаю скуль, и запускаю 1С. Потому, что ждать пока фирма 1с соизволит исправить миллионы ошибок в коде - нет смысла. Особенно убивает, как они, не читая сообщений, отвечают шаблонными сообщениями типа "пришлите скриншоты, ничё не паняна...", а при этом всё сообщение пестрит рисунками на скриншотах как для "самых маленьких". Ща материться начну.. У меня сейчас сервер 8.2 х64 не перезапускает автоматически процессы. Не перезапускает их и при превышении объёма памяти. И я уже устал отправлять логи и картинки. Бестолково это.

// svcctrl.cpp: определяет точку входа для консольного приложения.
//

#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <aclapi.h>
#include <stdio.h>

TCHAR szCommand[10];
TCHAR szSvcName[80];

SC_HANDLE schSCManager;
SC_HANDLE schService;

VOID DisplayUsage(TCHAR *);

VOID DoStartSvc(TCHAR *);

VOID DoStopSvc(TCHAR *);

void ErrorReport(PSTR);

BOOL StopDependentServices(void);


void _tmain(int argc, TCHAR *argv[])
{
	TCHAR *compName = NULL;

    printf("\n");
    if( argc < 3 )
    {
        printf("ERROR: Incorrect number of arguments\n\n");
        DisplayUsage(argv[0]);
        return;
    }

    StringCchCopy(szCommand, 10, argv[1]);
    StringCchCopy(szSvcName, 80, argv[2]);

	if (argc = 4) 
	{
		compName = argv[3];
	}

    if (lstrcmpi( szCommand, TEXT("start")) == 0 )
        DoStartSvc(compName);
    else if (lstrcmpi( szCommand, TEXT("stop")) == 0 )
        DoStopSvc(compName);
    else 
    {
        _tprintf(TEXT("Unknown command (%s)\n\n"), szCommand);
        DisplayUsage(argv[0]);
    }
}



void ErrorReport(CHAR *lpszFunction) 
{ 
    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError(); 

	FormatMessageA(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPSTR) &lpMsgBuf,
        0, NULL );

    // Display the error message and exit the process

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
		(lstrlenA((LPCSTR)lpMsgBuf)+lstrlenA((LPSTR)lpszFunction)+40)*sizeof(CHAR)); 
	StringCchPrintfA((LPSTR)lpDisplayBuf, 
        LocalSize(lpDisplayBuf) / sizeof(CHAR),
        "%s failed with error code %d: %s", 
        lpszFunction, dw, lpMsgBuf); 

	CharToOemA((CHAR*)lpDisplayBuf,(CHAR*)lpDisplayBuf);

	printf((CHAR*)lpDisplayBuf); 

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
}

VOID DisplayUsage(TCHAR *pn)
{
    printf("Description:\n");
    printf("\tCommand-line tool that controls a service.\n\n");
    printf("Usage:\n");
	printf("\t %S [command] [service_name] {[computer]}\n\n", pn);
    printf("\t[command]\n");
    printf("\t  start\n");
    printf("\t  stop\n");
}

//
// Purpose: 
//   Starts the service.
//
// Parameters:
//   None
// 
// Return value:
//   None
//

VOID DoStartSvc(TCHAR *compName)
{
    SERVICE_STATUS_PROCESS ssStatus; 
    DWORD dwOldCheckPoint; 
    DWORD dwStartTickCount;
    DWORD dwWaitTime;
    DWORD dwBytesNeeded;

    // Get a handle to the SCM database. 
 
    schSCManager = OpenSCManager( 
        compName,                    // local computer
        NULL,                    // ServicesActive database 
        SC_MANAGER_ALL_ACCESS);  // full access rights 
 
    if (NULL == schSCManager) 
    {
        //printf("OpenSCManager failed (%d)\n", GetLastError());
		ErrorReport("OpenSCManager");
        return;
    }

    // Get a handle to the service

    schService = OpenService( 
        schSCManager,         // SCM database 
        szSvcName,            // name of service 
        SERVICE_ALL_ACCESS);  // full access 
 
    if (schService == NULL)
    { 
        //printf("OpenService failed (%d)\n", GetLastError()); 
		ErrorReport("OpenService");
        CloseServiceHandle(schSCManager);
        return;
    }    

    // Attempt to start the service.

    if (!StartService(
            schService,  // handle to service 
            0,           // number of arguments 
            NULL) )      // no arguments 
    {
        //printf("StartService failed (%d)\n", GetLastError());
		ErrorReport("StartService");
        CloseServiceHandle(schService); 
        CloseServiceHandle(schSCManager);
        return; 
    }
    else printf("Service start pending...\n"); 

    // Check the status until the service is no longer start pending. 
 
    if (!QueryServiceStatusEx( 
            schService,             // handle to service 
            SC_STATUS_PROCESS_INFO, // info level
            (LPBYTE) &ssStatus,             // address of structure
            sizeof(SERVICE_STATUS_PROCESS), // size of structure
            &dwBytesNeeded ) )              // if buffer too small
    {
        return; 
    }
 
    // Save the tick count and initial checkpoint.

    dwStartTickCount = GetTickCount();
    dwOldCheckPoint = ssStatus.dwCheckPoint;

    while (ssStatus.dwCurrentState == SERVICE_START_PENDING) 
    { 
        // Do not wait longer than the wait hint. A good interval is 
        // one-tenth the wait hint, but no less than 1 second and no 
        // more than 10 seconds. 
 
        dwWaitTime = ssStatus.dwWaitHint / 10;

        if( dwWaitTime < 1000 )
            dwWaitTime = 1000;
        else if ( dwWaitTime > 10000 )
            dwWaitTime = 10000;

        Sleep( dwWaitTime );

        // Check the status again. 
 
        if (!QueryServiceStatusEx( 
            schService,             // handle to service 
            SC_STATUS_PROCESS_INFO, // info level
            (LPBYTE) &ssStatus,             // address of structure
            sizeof(SERVICE_STATUS_PROCESS), // size of structure
            &dwBytesNeeded ) )              // if buffer too small
            break; 
 
        if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
        {
            // The service is making progress.

            dwStartTickCount = GetTickCount();
            dwOldCheckPoint = ssStatus.dwCheckPoint;
        }
        else
        {
            if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
            {
                // No progress made within the wait hint.
                break;
            }
        }
    } 

    // Determine whether the service is running.

    if (ssStatus.dwCurrentState == SERVICE_RUNNING) 
    {
        printf("Service started successfully.\n"); 
    }
    else 
    { 
        printf("Service not started. \n");
        printf("  Current State: %d\n", ssStatus.dwCurrentState); 
        printf("  Exit Code: %d\n", ssStatus.dwWin32ExitCode); 
        printf("  Check Point: %d\n", ssStatus.dwCheckPoint); 
        printf("  Wait Hint: %d\n", ssStatus.dwWaitHint); 
    } 

    CloseServiceHandle(schService); 
    CloseServiceHandle(schSCManager);
}



//
// Purpose: 
//   Stops the service.
//
// Parameters:
//   None
// 
// Return value:
//   None
//
VOID DoStopSvc(TCHAR *compName)
{
    SERVICE_STATUS_PROCESS ssp;
    DWORD dwStartTime = GetTickCount();
    DWORD dwBytesNeeded;
    DWORD dwTimeout = 120000; // 2-minutes time-out

    // Get a handle to the SCM database. 
 
    schSCManager = OpenSCManager( 
        compName,                    // local computer
        NULL,                    // ServicesActive database 
        SC_MANAGER_ALL_ACCESS);  // full access rights 
 
    if (NULL == schSCManager) 
    {
        //printf("OpenSCManager failed (%d)\n", GetLastError());
		ErrorReport("OpenSCManager");
        return;
    }

    // Get a handle to the service.

    schService = OpenService( 
        schSCManager,         // SCM database 
        szSvcName,            // name of service 
        SERVICE_STOP | 
        SERVICE_QUERY_STATUS | 
        SERVICE_ENUMERATE_DEPENDENTS);  
 
    if (schService == NULL)
    { 
        //printf("OpenService failed (%d)\n", GetLastError()); 
		ErrorReport("OpenService");
        CloseServiceHandle(schSCManager);
        return;
    }    

    // Make sure the service is not already stopped.

    if ( !QueryServiceStatusEx( 
            schService, 
            SC_STATUS_PROCESS_INFO,
            (LPBYTE)&ssp, 
            sizeof(SERVICE_STATUS_PROCESS),
            &dwBytesNeeded ) )
    {
        //printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
		ErrorReport("QueryServiceStatusEx");
        goto stop_cleanup;
    }

    if ( ssp.dwCurrentState == SERVICE_STOPPED )
    {
        printf("Service is already stopped.\n");
        return;
    }

    // If a stop is pending, wait for it.

    while ( ssp.dwCurrentState == SERVICE_STOP_PENDING ) 
    {
        printf("Service stop pending...\n");
        Sleep( ssp.dwWaitHint );
        if ( !QueryServiceStatusEx( 
                 schService, 
                 SC_STATUS_PROCESS_INFO,
                 (LPBYTE)&ssp, 
                 sizeof(SERVICE_STATUS_PROCESS),
                 &dwBytesNeeded ) )
        {
           // printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
			ErrorReport("QueryServiceStatusEx");
            goto stop_cleanup;
        }

        if ( ssp.dwCurrentState == SERVICE_STOPPED )
        {
            printf("Service stopped successfully.\n");
            goto stop_cleanup;
        }

        if ( GetTickCount() - dwStartTime > dwTimeout )
        {
            printf("Service stop timed out.\n");
            goto stop_cleanup;
        }
    }

    // If the service is running, dependencies must be stopped first.

    StopDependentServices();

    // Send a stop code to the service.

    if ( !ControlService( 
            schService, 
            SERVICE_CONTROL_STOP, 
            (LPSERVICE_STATUS) &ssp ) )
    {
        //printf( "ControlService failed (%d)\n", GetLastError() );
		ErrorReport("ControlService");
        goto stop_cleanup;
    }

    // Wait for the service to stop.

    while ( ssp.dwCurrentState != SERVICE_STOPPED ) 
    {
        Sleep( ssp.dwWaitHint );
        if ( !QueryServiceStatusEx( 
                schService, 
                SC_STATUS_PROCESS_INFO,
                (LPBYTE)&ssp, 
                sizeof(SERVICE_STATUS_PROCESS),
                &dwBytesNeeded ) )
        {
            //printf( "QueryServiceStatusEx failed (%d)\n", GetLastError() );
			ErrorReport("QueryServiceStatusEx");
            goto stop_cleanup;
        }

        if ( ssp.dwCurrentState == SERVICE_STOPPED )
            break;

        if ( GetTickCount() - dwStartTime > dwTimeout )
        {
            printf( "Wait timed out\n" );
            goto stop_cleanup;
        }
    }
    printf("Service stopped successfully\n");

stop_cleanup:
    CloseServiceHandle(schService); 
    CloseServiceHandle(schSCManager);
}

BOOL StopDependentServices()
{
    DWORD i;
    DWORD dwBytesNeeded;
    DWORD dwCount;

    LPENUM_SERVICE_STATUS   lpDependencies = NULL;
    ENUM_SERVICE_STATUS     ess;
    SC_HANDLE               hDepService;
    SERVICE_STATUS_PROCESS  ssp;

    DWORD dwStartTime = GetTickCount();
    DWORD dwTimeout = 30000; // 30-second time-out

    // Pass a zero-length buffer to get the required buffer size.
    if ( EnumDependentServices( schService, SERVICE_ACTIVE, 
         lpDependencies, 0, &dwBytesNeeded, &dwCount ) ) 
    {
         // If the Enum call succeeds, then there are no dependent
         // services, so do nothing.
         return TRUE;
    } 
    else 
    {
        if ( GetLastError() != ERROR_MORE_DATA )
            return FALSE; // Unexpected error

        // Allocate a buffer for the dependencies.
        lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc( 
            GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded );
  
        if ( !lpDependencies )
            return FALSE;

        __try {
            // Enumerate the dependencies.
            if ( !EnumDependentServices( schService, SERVICE_ACTIVE, 
                lpDependencies, dwBytesNeeded, &dwBytesNeeded,
                &dwCount ) )
            return FALSE;

            for ( i = 0; i < dwCount; i++ ) 
            {
                ess = *(lpDependencies + i);
                // Open the service.
                hDepService = OpenService( schSCManager, 
                   ess.lpServiceName, 
                   SERVICE_STOP | SERVICE_QUERY_STATUS );

                if ( !hDepService )
                   return FALSE;

                __try {
                    // Send a stop code.
                    if ( !ControlService( hDepService, 
                            SERVICE_CONTROL_STOP,
                            (LPSERVICE_STATUS) &ssp ) )
                    return FALSE;

                    // Wait for the service to stop.
                    while ( ssp.dwCurrentState != SERVICE_STOPPED ) 
                    {
                        Sleep( ssp.dwWaitHint );
                        if ( !QueryServiceStatusEx( 
                                hDepService, 
                                SC_STATUS_PROCESS_INFO,
                                (LPBYTE)&ssp, 
                                sizeof(SERVICE_STATUS_PROCESS),
                                &dwBytesNeeded ) )
                        return FALSE;

                        if ( ssp.dwCurrentState == SERVICE_STOPPED )
                            break;

                        if ( GetTickCount() - dwStartTime > dwTimeout )
                            return FALSE;
                    }
                } 
                __finally 
                {
                    // Always release the service handle.
                    CloseServiceHandle( hDepService );
                }
            }
        } 
        __finally 
        {
            // Always free the enumeration buffer.
            HeapFree( GetProcessHeap(), 0, lpDependencies );
        }
    } 
    return TRUE;
}


Показать
Skaredov; evita; cool.vlad4; +3 Ответить
28. Qseft 05.10.11 16:27 Сейчас в теме
(27) Спасибо за скрипт, еще бы добавить принудительный kill процессов rphost по таймауту.
29. elena_77 26.01.12 11:26 Сейчас в теме
Спасибо за скрипт. У нас постоянно зависают сеансы на сервере и ключей не хватает тогда. Пока спасаемся только перезапуском службы Агент серсера 1С. Пришли к тому, что необходимо ночью регулярно перезапускать службу.
30. Oleg1708 15.03.12 16:08 Сейчас в теме
У нас и 81 не глючил и 82... Странно
31. sergey_s_ 17.10.12 05:58 Сейчас в теме
А в настройках кластера 1541 перезапуск рабочего процесса для чего?
33. AlexS2 153 24.10.12 10:43 Сейчас в теме
(31) sergey_s_, Я прошу прощения, Вы статью читали?
32. sergey_s_ 24.10.12 09:10 Сейчас в теме
34. maverick76 11 11.02.13 09:29 Сейчас в теме
Пользуюсь автоматическим перезапуском сервера 1С
35. bforce 481 11.02.13 09:50 Сейчас в теме
Я тоже пользую типовой перезапуск процессов и по времени, и при превышении объемов памяти (8.2.15, 8.2.16, 8.2.17). Проблем не вижу.
Оставьте свое сообщение