Первым делом настроили РБД таким образом, что в регионах остались подчиненные узлы, а в едином центре — главные (делалось это конечно не только ради обновления — иначе можно было бы попробовать и другие варианты, без УРБД). Главные узлы подключили к единому хранилищу. Однако обновлять десять баз, даже при наличии хранилища — занятие довольно «муторное». Поднимаем вопрос пакетного режима конфигуратора:
REM ------------- Обновление базы из хранилища (cmd) ----------------------- set bin = "C:Program Files (x86)1cv88.3.9.2170in1cv8.exe" set Srvr = srv set Base = infobase set Name = Admin set Pass = pass set Repo = tcp://srv/conf set Code = GoD set Log = D:autologslog_%date:~0,2%%date:~3,2%%date:~6,4%.txt %bin% DESIGNER /S"%Srvr%/%Base%" /N%Name% /P%Pass% /ConfigurationRepositoryF%Repo% /ConfigurationRepositoryN%Base% /ConfigurationRepositoryUpdateCfg /UC%Code% /OUT%Log% -NoTruncate REM ---------------- Обновление базы данных (cmd) -------------------------- set bin = "C:Program Files (x86)1cv88.3.9.2170in1cv8.exe" set Srvr = srv set Base = infobase set Name = Admin set Pass = pass set Code = GoD set Log = D:autologslog_%date:~0,2%%date:~3,2%%date:~6,4%.txt %bin% DESIGNER /S"%Srvr%/%Base%" /N%Name% /P%Pass% /UpdateDBCfg -Server /UC%Code% /OUT%Log% -NoTruncate
Уже неплохо! Написать bat/cmd файлик, который сделает это для десятка баз — не составляет труда… Если бы не одно «но» — все это нужно делать в «монопольном» режиме, т.е. когда в системе/системах нет пользователей. Как выгонять пользователей из клиент-серверной 1С? Скриптом! vbs, например:
'----------------------- Закрыть все соединения с конкретной базой (vbs) --------------------------- Set ComConnector = CreateObject("v83.ComConnector")'это, по сути, консоль кластера Set ServerAgent = ComConnector.ConnectAgent("srv")' вернее вот это Clasters = ServerAgent.GetClusters() For Each Claster In Clasters ServerAgent.Authenticate Claster, ClasterAdminName, ClasterAdminPass 'Как не странно неинициализированные значения прокатывают, если на кластере нет авторизации Sessions = ServerAgent.GetSessions(Claster) For Each Session In Sessions If Session.InfoBase.Name = "infobase" Then Call ServerAgent.TerminateSession(Claster,Session) End If Next Exit For Next '----------------------- Запретить соединения с конкретной базой (vbs) ----------------------------- Set ComConnector = CreateObject("v83.ComConnector") Set ServerAgent = ComConnector.ConnectAgent("srv") Clasters = ServerAgent.GetClusters() For Each Claster In Clasters ServerAgent.Authenticate Claster, ClasterAdminName, ClasterAdminPass WorkingProcesses = ServerAgent.GetWorkingProcesses(Claster) For Each WorkingProcess In WorkingProcesses 'чуток сложнее, нужно подключение к рабочему процессу... If WorkingProcess.Running = 1 Then Set connecttoworkprocess = ComConnector.ConnectWorkingProcess("tcp://" + WorkingProcess.HostName + ":" + CStr(WorkingProcess.MainPort)) connecttoworkprocess.AddAuthentication "Admin", "pass" 'а здесь уже нужны реальные логин/пароль к конкретной базе InfoBases = connecttoworkprocess.GetInfoBases() For Each InfoBase In InfoBases If InfoBase.Name = "infobase" Then InfoBase.ConnectDenied = True InfoBase.DeniedFrom = CStr(Now()) InfoBase.DeniedTo = CStr(Now() + 1 / 24 * 3) InfoBase.DeniedMessage = "База заблокированна администратором!" InfoBase.PermissionCode = "GoD" connecttoworkprocess.UpdateInfoBase (InfoBase) Exit For End If Next Exit For End If Next Exit For Next
Ну, т.е. мы сначала запрещаем соединения с базой (не забыв при этом установить код разрешения), потом обрываем существующие сессии пользователей, потом обновляем конфигурацию из хранилища и конфигурацию базы данных (указывая установленный ранее код разрешения)… Разрешить работу с базами после этого не сложнее, чем запретить, просто в строке InfoBase.ConnectDenied = True меняем на False (и при желании очищаем остальные поля).
Все это хорошо, но у нас базы распределенные. В принципе изменения в удаленные базы уйдут с ближайшим обменом по расписанию, но мы можем сделать это и принудительно, причем способов у нас несколько (речь идет об относительно типовой конфигурации, где присутствуют стандартные настройки УРБД):
- Настроить автоматический обмен по событию — при входе определенного пользователя в систему. Тогда нам просто достаточно запустить 1С под этим пользователем.
- Можем использовать параметр командной строки /Execute для запуска обработки в которой может быть прописано что угодно, включая вызов экспортной процедуры общего модуля для запуска обмена.
- Или можем использовать vbs скрипт в тех же целях:
'------------------- Выполнить экспортную процедуру общего модуля (vbs) ------------------------------ Set Base = CreateObject("V83.Application") Base.Connect("Srvr='srv';Ref='infobase';Usr=Admin;Pwd=pass;UC=GoD")'Стандартная строка соединения 1С Base.[МодульРегламентныхЗаданий].[ВыполнитьОбменДаннымиДляНастройкиАвтоматическогоОбменаДанными]("000001") 'Для того, что бы свободно использовать кириллицу, нужны квадратные скобки
Продолжим… В принципе для автоматического обновления ночью приведенной информации достаточно: нужно просто настроить автоматические задания на головном и региональных серверах с запасом по времени на обмен. Ну т.е. мы сначала проводим все эти действия на стороне головного сервера, а потом запускаем все тоже самое в обратном порядке (сначала обмен, потом выгоняем пользователей и обновляем базу) в регионе. Но в нашем случае есть ряд нюансов, а именно:
- Нестабильные каналы и разные часовые пояса превращают расчет этого самого «запаса» в непростой квест.
- Базы а регионе далеко не всегда работают в клиент-серверном режиме, есть и файловые. А значит, выгнать пользователей этим скриптом не получится.
- Хотелось бы иметь инструмент, позволяющий запустить принудительное обновление, не в конкретно заданное время, а в любой момент, т.е. процедуры «здесь» и «там» должны быть связаны (выполнятся последовательно).
Зато имеются и положительные моменты (я же рассказываю о собственном конкретном опыте, а не об универсальном решении):
- удаленные сервера доступны внутри единой сети;
- пользователи удаленных площадок работают на терминалах, т.е. клиенты 1С запущены не на рабочих станциях, а на одном конкретном сервере.
Первое позволяет использовать программку psexec для удаленного запуска команды на нужном сервере, а второе радикально решить проблему завершения сеансов с помощью taskkill. Первую нужно скачать, вторая доступна из командной строки по умолчанию.
Вообще типовые конфигурации 1С предоставляют условно «штатный» механизм завершения работы пользователей, который по задумке должен одинаково отрабатывать и в файловом и в клиент-серверном варианте работы (для установки нужно зайти в базу с параметром /CЗавершитьРаботуПользователей, для снятия /CРазрешитьРаботуПользователей). однако на деле мне показался этот метод не очень стабильным, а главное «тяжеловесным» (запускать целое приложение ради сравнительно элементарных действий не хочется) и долгим (по факту 1С запускает обработчик ожидания, который пытается завершить сенсы, пока это у него в конце концов не получится). Вариант с vbs, описанный выше, неплохо зарекомендовал себя на клиент-серверных базах, но он не применим в файловом режиме ( нету объекта v83.ComConnector). Для файлового же режима пара «лайфхаков»:
- Заблокированна база или нет по факту определяется наличием либо отсутствием файлика 1Cv8.cdn в каталоге базы данных. Да, вот так все просто. 🙂 Содержимое файлика:
{1,00010101000000,00010101000000,"База заблокирована администратором","GoD",""}
Где второй и третий «параметр» — дата начала блокировки и дата конца блокировки соответственно в формате ГГГГММДДччммсс. (вы всегда можете запустить вашу файловую базу с параметром /CЗавершитьРаботуПользователей, что бы получить этот файл и проанализировать его)
- Команда taskkill прекрасно, хотя возможно излишне «сурово» завершает работу пользователей! 🙂 в числе прочих ее параметров, есть /FI, который позволяет достаточно гибко настроить ,какие именно процессы надо завершать. Сейчас я остановился на варианте taskkill /f /FI «IMAGENAME eq 1cv8.exe», хотя в таком случае «безвинно пострадают» сеансы, не имеющие отношения к целевой базе (если таковые имеются). Я пробовал более «элегантный» вариант: taskkill /f /FI «WINDOWTITLE eq 1С:Предприятие — Рабочая база» (Где <Рабочая база> — заголовок окна программы заданный в настройках), но он работает только в идеальных условиях (например — не «убиваются» сеансы, когда пользователь запустил 1С, система дошла до ввода пароля и на этом — все).
Кроме того, несколько стандартных «граблей» на которые я наступал в процессе:
- Пара слов о psexec. Формат вызова: psexec \reg_srv -u username -p pass -c -f «reg_todo_t.bat». Вроде бы все понятно, но как обычно есть пара нюансов. Ключ -c копирует файл reg_todo_t.bat из каталога запуска psexec на удаленную машину перед исполнением. И копирует он его в системный каталог (system32, кажется). Поэтому ,если есть необходимость в каких-то дополнительных исполняемых файлах (например vbs), их нужно или предвариательно положить туда же, или первой строкой в reg_todo_t.bat устанавливать нужный рабочий каталог.
- Еще один важный момент. Особенностью cmd/bat файла является то, что вызвав запуск сторонней программы, он считает данную инструкцию выполненной и переходит к следующей. Нам же нужно обеспечить запуск всех наших действий СТРОГО последовательно (нет смысла запускать обновление, если еще не закончилась процедура завершения сеансов). Для этих целей нужно использовать конструкцию start /wait.
- cmd/bat файлы имеют OEM кодировку. Кирилические шрифты (в сообщения логирования, например) при открытии файла в блокноте по умолчанию будут отображаться «кракозябрами». Переключаем шрифт на terminal.
Ну, вроде бы все необходимое у нас есть. План такой:
- Блокируем доступ к центральной базе (база серверная, поэтому vbs)
- Завершаем сеансы пользователя (тоже самое — vbs)
- Обновляем конфигурацию из хранилища (cmd/bat пакетный режим конфигуратора)
- Обновляем конфигурацию базы данных (то же самое)
- Запускаем обмен (vbs)
- Снимаем блокировку базы (серверная база, поэтому vbs)
- Удаленно на региональном сервере запускаем bat/cmd/wsf (psexec) , в котором:
- блокируем доступ к базе (для файловых баз: файлик 1Cv8.cdn, для серверных см п.1, vbs)
- Завершаем сеансы (для файловых баз: taskkill, для серверных — vbs)
- Запускаем обмен (CreateObject(«V83.Application») работает как для серверных, так и для файловых баз)
- Обновляем конфигурацию базы данных (см п.4, пакетный режим)
- Снимаем блокировку базы (файлик 1Cv8.cdn или vbs)
Пример всего этого (для гипотетической инфраструктуры) во вложении.
Описание вложения:
- DoIt!.bat — запускает обновление центральной и переферийной баз из хранилища tcp://srv/conf, в котором имя пользователя равно имени базы (infobase), без пароля. Так или иначе вызывает остальные файлы.
- users.vbs — скрипт, который выгоняет пользователей и устанавливает блокировку базы, либо снимает блокировку базы в зависимости от параметра (off|on).
- update.bat обновляет базу из хранилища и обновляет конфигурацию БД.
- obmen.vbs — запускает экспортную процедуру общего модуля, инициализирующую обмен по существующей настройке УРБД.
Нюансы предполагаемой инфраструктуры:
- Предполагаем наличие в сети сервера srv, с базой ibfobase.
- Предполагается так же, что на стороне удаленной площадки есть сервер reg_srv, доступный по сети, на котором:
- — в папке C:auto есть папка Logs и файл obmen.vbs.
- — установлена 1с и база лежит в каталоге D:1C_Basesinfobase
- — авторизация в базе настроена по авторизации операционной системы.
- Программа psexec.exe в поставку не входит, ее следует скачать отдельно.
Upd 18.04.2024
- В типовых 1С есть «прекрасная» процедура при начале работы системы: КонтрольВерсииКонфигурации.ПроверитьВерсиюКонфигурации();
Эта процедура, проверяет константу ДатаТекущейВерсии, и, если она на два или более месяца меньше текущей даты, выводит модальное окно о необходимости одновить конфигурацию… Это окно выходит внезависимости от того — запускается ли сеанс с параметрами /DisableStartupMessage и /AU- , оно просто появляется и все. И ломает всю схему. Вариантов есть несколько… С точки зрения 1С, видимо, необходимо поддерживать актуальную конфигурацию. Для тех, у кого разрешены изменения конфигурации стоит закомментировать приведенную выше строчку кода в модуле обычного приложения. У кого не разрешены: Константы.ДатаТекущейВерсии.Установить(Дата(‘21000101’)); т.е. ставим дату конфигурации на 2100 год… Но это нужно будет делать после каждого обновления.
- При вызове экспортной процедуры с помощью vbs скрипта — в строке соединения не было параметра UC, что не давало ему запустится (т.к. на момент его запуска соединения с БД запрещены). Добавил по тексту и исправил пример во вложении.
(0) Деплойку не смотрел?http://infostart.ru/webinars/564260/ Она в том числе умеет отрубать соединения через RAS
(1) Посмотрел — любопытная штука. Но… Не смотря на открытый код — все равно «вещь в себе». Не полезешь ведь, без острой необходимости, в код — будешь использовать как «черный ящик»: работает — не трогай. А я больше на примере хотел показать ,что можно фактически «из командной строки» сделать с минимальным скриптингом…
(2) С помощью деплойки можно в принципе код упростить сильно, не влезая во внутрянкуhttps://gist.github.com/pumbaEO/9a52710dfa519c060dc45e9b81b9af5e
(3) О! Onescript… Не сразу заметил… os — это хорошо! 😉 Но все же это все в моем понимании из другой области… Хороших инструментов много всяких разных, но хотелось бы уметь/иметь возможность сделать все без них.
(1) О! Нашел про RAS — вот этого не знал, спасибо!
такая же задача стояла. решением получилось создание клиент-серверного варианта приложения для запуска скриптов обновления баз риб. смстатья
плюсом прикрутили мониторинг бекапов, онлайн просмотр версии конфигурацииплатформы. ну и запуск обновления в гетерогенной сетевой среде через psexec может не сработать (у нас филиальная сеть в разных городах, не объединенная в рамках одной локальной сети)
(7) да, у меня все тоже к тому шло… Рассматривал варианты и небольших сервисных баз на стороне регионов с доступом по веб-сервису (благо для этого клиент-сервер не нужен, достаточно апача) и интеграцию с инстаграм, но… Все это пока в виде разрозненных набросков. До реализации полноценной не дошло. А то, что тут изложил — работает, как не странно: изменения, которые сегодня вернули в хранилище — завтра с утра во всех базах появляются… Не долго правда: пару недель всего. Плюс в начале неделю косяки отлавливал! 😉
СПАСИБИЩЕ!!!!