gifts2017

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

Опубликовал Александр pira@pochta.ru (Pira) в раздел Администрирование - Распределенная БД (УРИБ, УРБД)

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

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

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

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

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

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

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

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

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

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

  

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

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

   

ПарольАдмина = "123";
    Результат = "";
    
    Админ = Справочники.Пользователи.НайтиПоНаименованию("Администратор");
    Если ЗначениеЗаполнено(Админ.ИдентификаторПользователяИБ) Тогда
        ЗначХран = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(Админ.ИдентификаторПользователяИБ);
        ЗначХран.Пароль    = ПарольАдмина;
        Попытка
            ЗначХран.Записать();
        Исключение
            Результат = "Не удалось записать пользователя.";
        Конецпопытки;
        
    КонецЕсли;
    
    Если Результат = "" Тогда
        СтрокаСоединения = СтрокаСоединенияИнформационнойБазы();//File="C:\1cv8\Base".
        Если лев(СтрокаСоединения,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:\run1С.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 = Задание.УникальныйИдентификатор;
        СценарийОбъект.Записать();
Результат = "Выполнено без ошибок";
Иначе
    Результат = "Не обнаружен сценарий обмена данными с центром";
КонецЕсли;    

Скачать файлы

Наименование Файл Версия Размер
Выполнение сценария 5
.epf 7,20Kb
09.09.16
5
.epf 7,20Kb Скачать
Конфигурация для встраивания 3
.cf 40,87Kb
13.09.16
3
.cf 40,87Kb Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. борян петров (TODD22) 14.09.16 07:49
Отличная вещь... , надо развивать идею :) У самого 150 баз в РИБе.

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

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

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


Вопрос по обновлению базы в узле. У вас я смотрю какой то скрипт формируется? Можете описать общий принцип?
У меня сейчас самописная база. В ней что бы обновится достаточно закрыть 1Ску и запустить ярлык с командой обновления.
Но в типовой после обновления стартуют ещё и обработчики. Если запустить под пользователем с правами продавца они не отработают. Не достаточно прав на объекты. Нужно под админом выполнять. А сам процесс обновления может затянуться и на 20-30 минут. Как вы этот момент реализовали?
2. Александр pira@pochta.ru (Pira) 14.09.16 10:19
Задание на запуск сценария и его выполнение в узле я так понял сделано через контроль невыполненных заданий. А сами задания в справочнике появляются после обмена РИБ?

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


Задания появляются после выполнения обмена, справочник со сценариями нужно включить в состав обмена.
3. борян петров (TODD22) 14.09.16 10:22
(2) Pira,
Задания появляются после выполнения обмена, справочник со сценариями нужно включить в состав обмена.

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

А как решаете проблему с обновлением в узле? У меня в узле есть только пользователь с правами кассира.
4. Александр pira@pochta.ru (Pira) 14.09.16 10:28
(1) TODD22,
По обновлению у меня отдельная обработка, которая в регламентном задании. Тут только настройка выполнения регламента.

А так - да, есть скрипт:
1. Ставим блокировку начала сеансов.
2. Запускаем обновление под админом.
3. Разрешаем работу пользователей.

Файлик run1C я создал в узлах чтобы могли обновить и разрешить вход в систему сотрудники службы поддержки, если что - то пошло не так, а меня нет на рабочем месте
5. борян петров (TODD22) 14.09.16 11:09
(4) Pira, Мне в магазине блокировать пользователей не нужно.
Получается так что пользователь под собой может сделать обмен, но потом нужно запускать обновление... и вот тут пока не придумал что сделать....
6. Александр pira@pochta.ru (Pira) 14.09.16 16:44
(5) TODD22, Ну так у меня в магазинах так и сделано:
Под пользователем загружается обмен.
Обработка в регламенте "Видит" что программа требует обновление (У меня обновление ночью проходит, пакет с обновленной конфой утром при начале работы получают).
Включается блокировка - всех пользователей выкидывает.
Затем запускается обновление под админом, по окончании его - разрешаем входить в базу.
7. Александр pira@pochta.ru (Pira) 15.09.16 10:19
(5) TODD22, Вот посмотрите, выложил обработку обновления.
http://infostart.ru/public/548907/
8. борян петров (TODD22) 15.09.16 10:22
(7) Pira, Спасибо :) Я уже увидел эту публикацию :)

На следующей неделе буду разбираться :)
9. борян петров (TODD22) 20.09.16 07:17
Скачал я вашу разработку.
Правильно ли я понимаю что мне нужно только добавить в свою конфигурацию справочник и регистр сведений?
Никакого кода, модулей и тд менять, копировать я так понимаю не нужно. Всё остальное делается уже доп обработками и сценариями?

10. Александр pira@pochta.ru (Pira) 21.09.16 23:14
(9) TODD22, Настроить план обмена еще нужно - включить в его состав добавленные объекты.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа