Удаленное администрирование распределенной базы


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

Дополнительное ПО устанавливать не нужно, работает как на файловом, так и клиент-серверном варианте. Код полностью открыт.

Работает на управляемых формах.

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

В центральном узле добавляем сценарий в соответствующий справочник. Ставим метки в каких узлах нужно выполнить задание.

В магазине работает регламентное задание, которое проверяет наличие не выполненных заданий и выполняет их по мере необходимости. По одному за каждый запуск, в порядке очередности установленной в справочнике.

Результат выполнения записывается в регистр сведений. После обмена можно в центральной базе посмотреть: выполнилось ли задание, наличие ошибки выполнения. Если есть необходимость — то через результат выполнения можно передать с узла в центр данные.

Задание выполняется один раз на каждом узле.

Примеры сценариев:

1  Создать копию рабочего места

  

 МассивФайлов = НайтиФайлы("C:Users","1cv8u.pfl",Истина);
Результат = "Всего фалов настройки "+МассивФайлов.Количество();
Если МассивФайлов.Количество()>0 тогда
Для Каждого НайденФайл Из МассивФайлов Цикл
СтарыйФайл = СтрЗаменить(НайденФайл.ПолноеИмя,"1cv8u.pfl","_1cv8u.pfl");
КопироватьФайл(НайденФайл.ПолноеИмя, СтарыйФайл);
КонецЦикла;
Иначе
Результат = "Нет файлов настройки";
КонецЕсли;    

2 Создание файла run1C и смена пароля админа

   

ПарольАдмина = "123";
Результат = "";

Админ = Справочники.Пользователи.НайтиПоНаименованию("Администратор");
Если ЗначениеЗаполнено(Админ.ИдентификаторПользователяИБ) Тогда
ЗначХран = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(Админ.ИдентификаторПользователяИБ);
ЗначХран.Пароль    = ПарольАдмина;
Попытка
ЗначХран.Записать();
Исключение
Результат = "Не удалось записать пользователя.";
Конецпопытки;

КонецЕсли;

Если Результат = "" Тогда
СтрокаСоединения = СтрокаСоединенияИнформационнойБазы();//File="C:1cv8Base".
Если лев(СтрокаСоединения,4) = "Srvr" Тогда  //Srvr="obmensrv";Ref="testpirozhkov";
Сервак = Лев(СтрокаСоединения,Найти(СтрокаСоединения,";Ref="));
База   = Прав(СтрокаСоединения,Найти(СтрокаСоединения,";Ref="));
Сервак = СтрЗаменить(Сервак, "Srvr=", "");
Сервак = СтрЗаменить(Сервак, ";", "");
База = СтрЗаменить(База, ";", "");
СтрокаСоединения = Сервак+""+База;
СтрокаСоединения = СтрЗаменить(СтрокаСоединения, """", "");
КаталогПрограммы = КаталогПрограммы();
ИмяФайлаПрограммы = КаталогПрограммы + "1cv8.exe";

КоманднаяСтрокаОбновления = "echo off
|cls
|"""+ИмяФайлаПрограммы+""" CONFIG /S"""+СтрокаСоединения+""" /N""Администратор"" /P"""+ПарольАдмина+""" /DisableStartupMessages /UpdateDBCfg /UC""КодРазрешения""
|"""+ИмяФайлаПрограммы+""" ENTERPRISE /S"""+СтрокаСоединения+""" /N""Администратор"" /P"""+ПарольАдмина+""" /DisableStartupMessages /C""РазрешитьРаботуПользователей"" /UC""КодРазрешения""";
Иначе

СтрокаСоединения = СтрЗаменить(СтрокаСоединения, "File=", "");
СтрокаСоединения = СтрЗаменить(СтрокаСоединения, ";", "");
КаталогПрограммы = КаталогПрограммы();
ИмяФайлаПрограммы = КаталогПрограммы + "1cv8.exe";

КоманднаяСтрокаОбновления = "echo off
|cls
|"""+ИмяФайлаПрограммы+""" CONFIG /F"+СтрокаСоединения+" /N""Администратор"" /P"""+ПарольАдмина+""" /DisableStartupMessages /UpdateDBCfg /UC""КодРазрешения""
|"""+ИмяФайлаПрограммы+""" ENTERPRISE /F"+СтрокаСоединения+" /N""Администратор"" /P"""+ПарольАдмина+""" /DisableStartupMessages /C""РазрешитьРаботуПользователей"" /UC""КодРазрешения""";
КонецЕсли;

ИмяФайлаСкрипта = "C:
un1С.bat";
Ф = Новый ТекстовыйДокумент();
Ф.УстановитьТекст(КоманднаяСтрокаОбновления);
Ф.Записать(ИмяФайлаСкрипта, КодировкаТекста.OEM);
Результат = "Выполнено";
КонецЕсли;

3 Настройка регламента «ВыполнениеПроизвольногоСценария»

//ВключитьРегламент("ВыполнениеПроизвольногоСценария");
ИмяРег = "ВыполнениеПроизвольногоСценария";
//запуск в магазинах регламента
//Процедура ВключитьРегламент(ИмяРег)
УстановитьПривилегированныйРежим(Истина);
Отб = Новый Структура;
ИмяРЗ = "Дополнительная обработка: "+ИмяРег+" / Команда: "+ИмяРег;
Отб.Вставить("Наименование", ИмяРЗ);
Задания = РегламентныеЗадания.ПолучитьРегламентныеЗадания(Отб);
Если Задания.Количество()>0 тогда
Задание = Задания[0];
Иначе
Задание = РегламентныеЗадания.СоздатьРегламентноеЗадание("ЗапускДополнительныхОбработок");
КонецЕсли;
Задание.Использование = Истина;
Задание.Наименование =   ИмяРЗ;
Расписание = Новый РасписаниеРегламентногоЗадания;
Расписание.ПериодНедель = 1;
МД = Новый Массив();
МД.Добавить(1);
МД.Добавить(2);
МД.Добавить(3);
МД.Добавить(4);
МД.Добавить(5);
МД.Добавить(6);
МД.Добавить(7);
Расписание.ДниНедели = МД;
Расписание.ДатаНачала = ТекущаяДата();
Расписание.ПериодПовтораВТечениеДня = 1800;
Расписание.ПериодПовтораДней = 1;
Задание.Расписание = Расписание;
ПарЗад = Новый Массив;
ПарЗад.Добавить(Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию(ИмяРег));
ПарЗад.Добавить(ИмяРег);
Задание.Параметры = ПарЗад;
Задание.Записать();
//КонецПроцедуры
Результат = "Выполнено без ошибок";

4 Настройка регламента «ОбновлениеКонфигурации»   

 //ВключитьРегламент("ОбновлениеКонфигурации");
ИмяРег = "ОбновлениеКонфигурации";
//запуск в магазинах регламента
//Процедура ВключитьРегламент(ИмяРег)
УстановитьПривилегированныйРежим(Истина);
Отб = Новый Структура;
ИмяРЗ = "Дополнительная обработка: "+ИмяРег+" / Команда: "+ИмяРег;
Отб.Вставить("Наименование", ИмяРЗ);
Задания = РегламентныеЗадания.ПолучитьРегламентныеЗадания(Отб);
Если Задания.Количество()>0 тогда
Задание = Задания[0];
Иначе
Задание = РегламентныеЗадания.СоздатьРегламентноеЗадание("ЗапускДополнительныхОбработок");
КонецЕсли;
Задание.Использование = Истина;
Задание.Наименование =   ИмяРЗ;
Расписание = Новый РасписаниеРегламентногоЗадания;
Расписание.ПериодНедель = 1;
МД = Новый Массив();
МД.Добавить(1);
МД.Добавить(2);
МД.Добавить(3);
МД.Добавить(4);
МД.Добавить(5);
МД.Добавить(6);
МД.Добавить(7);
Расписание.ДниНедели = МД;
Расписание.ДатаНачала = ТекущаяДата();
Расписание.ПериодПовтораВТечениеДня = 300;
Расписание.ПериодПовтораДней = 1;
Задание.Расписание = Расписание;

УправляющийПользователь = "";
Управляющий = Справочники.ГруппыДоступа.НайтиПоНаименованию("СударьУправляющий");
Для каждого Стр Из Управляющий.Пользователи Цикл
УправляющийПользователь = Стр.Пользователь;
Попытка
Если ЗначениеЗаполнено(УправляющийПользователь) тогда
Если ЗначениеЗаполнено(УправляющийПользователь.ИдентификаторПользователяИБ) Тогда
ЗначХран = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(УправляющийПользователь.ИдентификаторПользователяИБ).Имя;
Прервать;
КонецЕсли;
КонецЕсли;
Исключение
конецпопытки
КонецЦикла;
Задание.ИмяПользователя = ЗначХран;


ПарЗад = Новый Массив;
ПарЗад.Добавить(Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию(ИмяРег));
ПарЗад.Добавить(ИмяРег);
Задание.Параметры = ПарЗад;
Задание.Записать();
//КонецПроцедуры
Результат = "Выполнено без ошибок";

5 Настройка регламента «Синхронизация с центром»

Сценарий = Справочники.СценарииОбменовДанными.НайтиПоКоду("00001");
Если ЗначениеЗаполнено(Сценарий) Тогда
УстановитьПривилегированныйРежим(Истина);
Отб = Новый Структура;
ИмяРЗ = "Выполнение обмена по сценарию: Сценарий синхронизации для Центр";
Отб.Вставить("Наименование", ИмяРЗ);
Задания = РегламентныеЗадания.ПолучитьРегламентныеЗадания(Отб);
Если Задания.Количество()>0 тогда
Задание = Задания[0];
Иначе
Задание = РегламентныеЗадания.СоздатьРегламентноеЗадание("СинхронизацияДанных");
Задание.Наименование = "Выполнение обмена по сценарию: Сценарий синхронизации для Центр";
КонецЕсли;
Задание.Использование = Истина;
Расписание = Новый РасписаниеРегламентногоЗадания;
Расписание.ПериодНедель = 1;
//ТекущийОбъект.НастройкиОбмена
//ТекущийОбъект
МД = Новый Массив();
МД.Добавить(1);
МД.Добавить(2);
МД.Добавить(3);
МД.Добавить(4);
МД.Добавить(5);
МД.Добавить(6);
МД.Добавить(7);
Расписание.ДниНедели = МД;
//Расписание.ДатаНачала = ТекущаяДата();
Расписание.ПериодПовтораВТечениеДня = 2400;
Расписание.ПериодПовтораДней = 1;
Расписание.ДатаНачала = НачалоДня(ТекущаяДата());
Задание.Расписание = Расписание;
Задание.ИмяПользователя = "Администратор";

ПараметрыРегламентногоЗадания = Новый Массив;
ПараметрыРегламентногоЗадания.Добавить(Сценарий.Код);
Задание.Параметры = ПараметрыРегламентногоЗадания;
Задание.Записать();
СценарийОбъект = Сценарий.ПолучитьОбъект();
СценарийОбъект.РегламентноеЗаданиеGUID = Задание.УникальныйИдентификатор;
СценарийОбъект.Записать();
Результат = "Выполнено без ошибок";
Иначе
Результат = "Не обнаружен сценарий обмена данными с центром";
КонецЕсли;

10 Comments

  1. TODD22

    Отличная вещь… , надо развивать идею 🙂 У самого 150 баз в РИБе.

    В центральном узле добавляем сценарий в соответствующий справочник. Ставим метки в каких узлах нужно выполнить задание.

    В магазине работает регламентное задание, которое проверяет наличие не выполненных заданий и выполняет их по мере необходимости. По одному за каждый запуск, в порядке очередности установленной в справочнике.

    Задание на запуск сценария и его выполнение в узле я так понял сделано через контроль невыполненных заданий. А сами задания в справочнике появляются после обмена РИБ?

    Вопрос по обновлению базы в узле. У вас я смотрю какой то скрипт формируется? Можете описать общий принцип?

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

    Но в типовой после обновления стартуют ещё и обработчики. Если запустить под пользователем с правами продавца они не отработают. Не достаточно прав на объекты. Нужно под админом выполнять. А сам процесс обновления может затянуться и на 20-30 минут. Как вы этот момент реализовали?

    Reply
  2. Pira

    Задание на запуск сценария и его выполнение в узле я так понял сделано через контроль невыполненных заданий. А сами задания в справочнике появляются после обмена РИБ?

    Потребность выполнения определяется просто:

    Процедура ВыполнитьКоманду(ИдентификаторКоманды) Экспорт
    ЭтотМагазин = ПараметрыСеанса.ТекущийМагазин;
    Запрос = Новый Запрос;
    Запрос.Текст =
    «ВЫБРАТЬ ПЕРВЫЕ 1
    | ИсполняемыеСценарииМагазиновМагазины.Ссылка
    |ИЗ
    | Справочник.ИсполняемыеСценарииМагазинов.Магазины КАК ИсполняемыеСценарииМагазиновМагазины
    |  ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ВыполнениеСценарияВМагазине КАК ВыполнениеСценарияВМагазине
    |  ПО ИсполняемыеСценарииМагазиновМагазины.Магазин = ВыполнениеСценарияВМагазине.Магазин
    |   И ИсполняемыеСценарииМагазиновМагазины.Ссылка = ВыполнениеСценарияВМагазине.Сценарий
    |ГДЕ
    | ИсполняемыеСценарииМагазиновМагазины.Ссылка.Активно
    | И ИсполняемыеСценарииМагазиновМагазины.Магазин = &Магазин
    | И ИсполняемыеСценарииМагазиновМагазины.Выполнять
    | И НЕ ЕСТЬNULL(ВыполнениеСценарияВМагазине.Выполнено, ЛОЖЬ)
    |
    |УПОРЯДОЧИТЬ ПО
    | ИсполняемыеСценарииМагазиновМагазины.Ссылка.ПорядокВыполнения»;
    Запрос.УстановитьПараметр(«Магазин»,ЭтотМагазин);
    ВыборкаЗапроса = Запрос.Выполнить().Выбрать();
    Если ВыборкаЗапроса.Следующий() Тогда //За каждый запуск делаем по одному, далее снимаем флаг и следующий выполняем
    ВыполнитьСценарий(ВыборкаЗапроса.Ссылка,ЭтотМагазин);
    КонецЕсли;
    КонецПроцедуры

    Показать

    Задания появляются после выполнения обмена, справочник со сценариями нужно включить в состав обмена.

    Reply
  3. TODD22

    (2)

    Задания появляются после выполнения обмена, справочник со сценариями нужно включить в состав обмена.

    С обменами это не очень удобно…

    А как решаете проблему с обновлением в узле? У меня в узле есть только пользователь с правами кассира.

    Reply
  4. Pira

    (1) TODD22,

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

    А так — да, есть скрипт:

    1. Ставим блокировку начала сеансов.

    2. Запускаем обновление под админом.

    3. Разрешаем работу пользователей.

    Файлик run1C я создал в узлах чтобы могли обновить и разрешить вход в систему сотрудники службы поддержки, если что — то пошло не так, а меня нет на рабочем месте

    Reply
  5. TODD22

    (4) Мне в магазине блокировать пользователей не нужно.

    Получается так что пользователь под собой может сделать обмен, но потом нужно запускать обновление… и вот тут пока не придумал что сделать….

    Reply
  6. Pira

    (5) TODD22, Ну так у меня в магазинах так и сделано:

    Под пользователем загружается обмен.

    Обработка в регламенте «Видит» что программа требует обновление (У меня обновление ночью проходит, пакет с обновленной конфой утром при начале работы получают).

    Включается блокировка — всех пользователей выкидывает.

    Затем запускается обновление под админом, по окончании его — разрешаем входить в базу.

    Reply
  7. Pira

    (5) TODD22, Вот посмотрите, выложил обработку обновления.

    http://infostart.ru/public/548907/

    Reply
  8. TODD22

    (7) Спасибо 🙂 Я уже увидел эту публикацию 🙂

    На следующей неделе буду разбираться 🙂

    Reply
  9. TODD22

    Скачал я вашу разработку.

    Правильно ли я понимаю что мне нужно только добавить в свою конфигурацию справочник и регистр сведений?

    Никакого кода, модулей и тд менять, копировать я так понимаю не нужно. Всё остальное делается уже доп обработками и сценариями?

    Reply
  10. Pira

    (9) TODD22, Настроить план обмена еще нужно — включить в его состав добавленные объекты.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *