Итак…
Задача.
Необходимо реализовать автоматический рестарт службы Агент сервера 1С: Предприятия 8.2 с помощью планировщика задач Windows. Но перед рестартом необходимо проверить, не работает ли кто-нибудь в базе Base, расположенной на сервере 1С: Предприятия. Если кто-нибудь работает, то перезапуск службы недопустим.
Решение.
У вас может закрасться вопрос, мол, зачем нужно периодически перезапускать службу Агента сервера? Дело в том, что в версии 1С: Предприятие 8.2 х64 есть одна “маленькая” ошибка. Она возникает при динамическом обновлении информационной базы и приводит БД к невозможности обновления и работы в ней. Разработчики официально (в личной переписке с ними) заявили, что данная ошибка не планируется к исправлению в версии 8.2. Придется ждать и “выживать” до официального релиза 8.3. Я-то знаю способ исправления этой ошибки (если надо — расскажу в комментариях или апдейте статьи). Но, как заверяют разработчики, данный способ обхода может разрушить базу данных совсем. У меня за год использования этого способа обхода база не разрушилась. Но не об этом статья.
Итак. Задача поставлена. Основной проблемой для меня стало условие проверки существующих подключений к определенной БД. Для реализации поставленной задачи я решил не использовать встроенный язык 1С: Предприятия, ни один из .Net-языков, а также Java (only console, only true linux-way).
В синтаксис-помощнике 1С: Предприятия был найден метод проверки наличия подключений к БД, но он предполагал использование OLE/COM-соединения к Агенту сервера 1С: Предприятия. Что ж… Приступим.
GetInfoBaseConnections (GetInfoBaseConnections)
Синтаксис:
GetInfoBaseConnections(<Кластер>, <ИнформационнаяБаза>)
Параметры:
<Кластер> (обязательный)
Тип: Кластер серверов. Кластер серверов, для которого должен быть получен массив описаний соединений.
<ИнформационнаяБаза> (обязательный)
Тип: Описание информационной базы. Информационная база, для которой должен быть получен массив описаний соединений.
Возвращаемое значение:
Тип: COMSafeArray. Массив описаний соединений кластера. Каждое описание соединения представлено объектом с интерфейсом Описание соединения.
Описание:
Получает массив описаний соединений информационной базы.
Доступность:
Интеграция.
Для работы с OLE/COM-объектами средствами Perl нам понадобиться задействовать модуль Win32::OLE. В используемой мной сборке StrawberryPerl данный модуль уже был предустановлен. Но даже если это не так, можно установить его через CPAN:
C:\Perl\perl\bin\cpan Win32::OLE
Чтобы получить список соединений базы данных 1С, нам нужно:
- Создать COM-подключение к объекту V82.COMConnector;
- Подключиться к агенту кластера серверов 1С: Предприятия;
- Получить объект кластера 1С;
- Авторизоваться на кластере;
- Получить список баз 1С на этом кластере;
- Найти необходимую нам базу;
- Получить список активных соединений к этой базе данных.
Вот код с комментариями, который получает список активных соединений клиентов с базой данных 1С: Предприятия, расположенной на сервере 1С: Предприятия.
use strict; use warnings; use Win32::OLE; use Data::Dumper; sub getConnectionsCount { # имя сервера (с портом) и имя базы будем получать из параметров метода my ($server, $dbname) = @_; # создаем COM-соединение my $ole1c = Win32::OLE->new("V82.COMConnector") or die "Could not create OLE-connector!\n"; # создаем объект Агента сервера 1С:Предприятия my $_agent = $ole1c->ConnectAgent($server) or die "Could not connect to server!\n" . cnv(Dumper $ole1c->ErrorDescription()); # получаем объект кластера (у меня один кластер) my $_cluster = $_agent->GetClusters()->[0] or die "Could not get cluster 0 from array\n"; # авторизуемся на кластере серверов. # Авторизоваться надо с помощь логина и пароля Администратора кластера серверов, # которого можно задать в утилите Администрирования сервера 1С:Предприятия. # не путайте этого администратора с администратором базы данных, что заводится # через конфигуратор в пользователях. # У меня нет администраторов, оставляю пустыми параметры логина и пароля. $_agent->Authenticate($_cluster, "", ""); # получаем список баз данных, расположенных в данном кластере my $_basesinfo = $_agent->GetInfoBases($_cluster); # найдем нашу базу данных my @_bases = grep { defined $_->{Name} && $_->{Name} =~ m/^$dbname$/ } @$_basesinfo; # она точно будет одна my $_base = $_bases[0]; # заведем счетчик подключений my $connCounter = 0; # получим все активные подключения или сразу вернем 0 my $_baseconns = $_agent->GetInfoBaseConnections($_cluster, $_base) or return 0; # “отсечем” все соединения по типу приложения, на которые можно не обращать внимание. # если эти подключения есть, то можно смело перегружать службу # Агента сервера 1С:Предприятия foreach (@$_baseconns) { # нам не важны планировщики задач и подключения через консоль кластера if ($_->{Application} !~ m/JobScheduler/ && $_->{Application} !~ m/SrvrConsole/) { $connCounter++; } } return $connCounter; } # вызов очень простоой. # только порт нужно указывать тот, который слушает агент кластера серверов 1С:Предприятия print “There are “ . getConnectionsCount(“localhost:1540”, “Base”) . “ active connections\n”;
Перезапустить службу Агента можно с помощью команд “net start” и “net stop”:
net stop <ИмяСлужбы> net start <ИмяСлужбы>
Полный код, выполняющий поставленную задачу я расположил на Bitbucket-е.
ссылка на оригинал статьи http://habrahabr.ru/post/174857/
Добавить комментарий