При переносе рабочих баз 1С на тестовые серверы для разработки, тестирования или обучения администраторы и программисты часто сталкиваются с опасной ситуацией. Если в коде прописаны регламентные задания, автоматические обмены или выгрузки данных во внешние системы, тестовая база может «по привычке» запустить эти процессы. Это приводит к замусориванию рабочей базы тестовыми данными или, что еще хуже, к отправке реальным клиентам тестовых писем и SMS.
Для предотвращения подобных ситуаций разработчики обычно используют проверку имени сервера. Однако стандартный метод получения строки соединения в фоновом задании преподносит неприятный сюрприз: вместо реального имени сервера он возвращает localhost. В этой статье мы подробно разберем, почему так происходит, и рассмотрим четыре надежных способа обойти это ограничение.
Для начала проанализируем поведение платформы «1С:Предприятие». В обычном клиентском сеансе вызов функции СтрокаСоединенияИнформационнойБазы() возвращает строку подключения, которую ввел пользователь в своем стартере 1С (например, Srvr="prod-server";Ref="work_db";). Это происходит потому, что инициатором соединения выступает клиентское приложение.
В фоновом задании ситуация принципиально иная:
rphost.localhost или 127.0.0.1).СтрокаСоединенияИнформационнойБазы() (и её обертки в БСП, такие как СоединенияИБКлиентСервер.ПутьКИнформационнойБазе()) внутри фонового задания возвращает строку вида localhost\имя_базы, что делает невозможным стандартную проверку по имени боевого сервера.Ниже мы подробно разберем четыре практических способа решения этой проблемы.
Это самый простой, быстрый и кроссплатформенный способ разделения рабочего и тестового контуров. Встроенная функция платформы ИмяКомпьютера() при выполнении на стороне сервера (а фоновые задания всегда выполняются на сервере) возвращает сетевое имя (NetBIOS-имя) физического или виртуального сервера, на котором запущен рабочий процесс rphost.
Даже если в настройках кластера обеих баз прописан localhost, физические имена серверов операционной системы (например, под управлением Windows или Linux) гарантированно будут отличаться.
Рассмотрим пример реализации такой проверки в коде регламентного задания:
Процедура ВыполнитьОбменДанными() Экспорт
// Получаем имя текущего сервера ОС в верхнем регистре
ТекущийСервер = ВРег(ИмяКомпьютера());
// Проверяем, соответствует ли сервер рабочему контуру
Если ТекущийСервер <> "PROD-SERVER-OS" Тогда
// Это тестовый контур. Логируем событие и прерываем выполнение обмена.
ЗаписьЖурналаРегистрации("ОбменДанными.Блокировка",
УровеньЖурналаРегистрации.Предупреждение,
,
,
"Запуск обмена отменен: текущий сервер (" + ТекущийСервер + ") не является рабочим.");
Возврат;
КонецЕсли;
// Далее идет основной код обмена...
ИнтеграцияСВнешнимиСистемами.ВыгрузитьДанные();
КонецПроцедуры
Преимущества: Работает моментально, не зависит от настроек кластера 1С, корректно отрабатывает как на Windows, так и на Linux.
Если ваша конфигурация построена на базе Библиотеки Стандартных Подсистем (БСП), вам не нужно писать собственные велосипеды для проверки имени сервера. В БСП встроен готовый и очень надежный механизм защиты от случайного запуска регламентных заданий в копиях баз.
Когда вы копируете базу на тестовый сервер и запускаете её, БСП автоматически фиксирует изменение параметров подключения (изменяется имя сервера, имя СУБД или имя самой базы). При первом входе администратора система выводит предупреждение: «Информационная база перемещена или восстановлена из резервной копии».
Если администратор выбирает вариант «Это копия информационной базы», БСП автоматически блокирует работу со всеми внешними ресурсами (блокируются регламентные задания, отправка почты, синхронизация данных, веб-сервисы).
Для проверки этой блокировки в коде вашего фонового задания достаточно вызвать стандартный метод БСП:
Процедура ВыполнитьОбменДаннымиБСП() Экспорт
// Проверяем, разрешена ли работа с внешними ресурсами для данной базы
Если НЕ ОбщегоНазначения.РазрешенаРаботаСВнешнимиРесурсами() Тогда
// База определена как копия, блокируем выполнение транзакций во внешние системы
ЗаписьЖурналаРегистрации("ОбменДанными.Блокировка",
УровеньЖурналаРегистрации.Предупреждение,
,
,
"Регламентное задание заблокировано, так как база запущена в режиме копии.");
Возврат;
КонецЕсли;
// Безопасный запуск обмена
ИнтеграцияСВнешнимиСистемами.ВыгрузитьДанные();
КонецПроцедуры
Преимущества: Это промышленный стандарт разработки под 1С. Механизм учитывает не только имя сервера, но и имя базы данных в СУБД, обеспечивая комплексную защиту.
Если вам принципиально важно, чтобы функция СтрокаСоединенияИнформационнойБазы() возвращала красивое и реальное имя сервера во всех фоновых заданиях, необходимо устранить первопричину на уровне администрирования кластера 1С.
Разберем по шагам, как это сделать:
localhost.localhost на реальное сетевое имя сервера (например, prod-app-server) или его статический IP-адрес. Нажмите «ОК».В некоторых сложных случаях требуется ручная правка конфигурационных файлов кластера. Для этого:
C:\Program Files\1cv8\srvinfo).1cv8wsrv.lst и 1CV8Clst.lst.localhost на реальное сетевое имя сервера.После выполнения этих действий фоновые задания будут корректно определять имя сервера через любые функции работы со строкой соединения.
Если сервер приложений 1С работает под управлением операционной системы Windows, мы можем запросить переменные окружения ОС напрямую через системную оболочку, полностью минуя любые алгоритмы платформы 1С.
Посмотрим на пример кода, запрашивающий системную переменную %COMPUTERNAME%:
Функция ПолучитьИмяСервераЧерезОС()
ИмяСервераОС = "";
#Если Сервер Тогда
Попытка
// Создаем объект системной оболочки Windows Script Host
WshShell = Новый COMОбъект("WScript.Shell");
// Читаем системную переменную окружения COMPUTERNAME
ИмяСервераОС = WshShell.ExpandEnvironmentStrings("%COMPUTERNAME%");
Исключение
// Обработка исключения на случай, если запуск происходит на Linux
// или у пользователя службы 1С нет прав на работу с COM-объектами
ИмяСервераОС = "";
КонецПопытки;
#КонецЕсли
Возврат ИмяСервераОС;
КонецФункции
Этот способ можно использовать в качестве резервного, если по каким-то причинам стандартные механизмы недоступны.
Для надежной защиты вашей информационной системы мы рекомендуем комбинировать подходы:
ИмяКомпьютера() (Способ 1), так как она не требует сложной настройки операционной системы и не зависит от архитектурных ограничений вызова строки соединения в фоне.