Консоль кластера серверов 1С — оснастка MMC «Администрирование серверов 1С Предприятия», которую ещё называют консолью сервера 1С. В ней видны базы, сеансы, блокировки и рабочие процессы сервера. Ниже — как зарегистрировать консоль после обновления платформы, чем заменить её на Linux, какие команды rac пригодятся в скриптах и как сделать то же самое из кода через объект АдминистрированиеСервера.
Консоль ставится компонентом «Администрирование сервера 1С:Предприятия». В меню «Пуск» она лежит в папке «1С Предприятие 8 (x86-64) → Дополнительно» под именем «Администрирование серверов 1С Предприятия x86-64». Ярлык открывает общий для всех версий файл C:\Program Files\1cv8\common\1CV8 Servers (x86-64).msc, а работает оснастка через radmin.dll конкретной версии.
Зарегистрирована может быть только одна версия radmin.dll, и она должна совпадать с версией агента сервера. После обновления платформы запустите ярлык «Дополнительно → номер версии → Регистрация утилиты администрирования серверов x86-64»: он вызывает bin\RegMSC.cmd, а тот с правами администратора выполняет regsvr32 /i:user radmin.dll.
Затем добавьте сервер: правой кнопкой по узлу «Центральные серверы 1С:Предприятия 8.3» → «Создать» → «Центральный сервер 1С:Предприятия 8.3». Протокол — TCP, имя — srv01, IP порт — 1540 (порт агента ragent). В дереве появятся «Кластеры → Локальный кластер» и узлы «Информационные базы», «Рабочие процессы», «Сеансы», «Блокировки», «Администраторы».
@echo off
rem Windows, cmd от имени администратора. Версия - та же, что у агента сервера (ragent).
set "V8BIN=C:\Program Files\1cv8\8.3.27.1786\bin"
rem 1. Регистрация консоли кластера этой версии. То же делает ярлык
rem "Регистрация утилиты администрирования серверов": он запускает bin\RegMSC.cmd
regsvr32 /i:user "%V8BIN%\radmin.dll"
rem 2. Сервер администрирования ras как служба: слушает 1545, агент кластера - localhost:1540
sc create "1C:Enterprise 8.3 Remote Server" binPath= "\"%V8BIN%\ras.exe\" cluster --service --port=1545 localhost:1540" DisplayName= "1C:Enterprise 8.3 Remote Server" start= auto
sc start "1C:Enterprise 8.3 Remote Server"
rem 3. Проверка: rac видит кластер через ras
"%V8BIN%\rac.exe" localhost:1545 cluster list
Самой консоли ras не нужен: она ходит к агенту напрямую. Сервер администрирования (ras, порт 1545) нужен rac, функции «Управление серверами» и коду ниже. Пока в кластере нет администраторов, управлять им может любой, кому доступен порт 1540, — заведите их в узле «Администраторы».
Здесь базы регистрируют в кластере, удаляют и правят их свойства — после входа администратором информационной базы. В свойствах — «Блокировка начала сеансов включена» с полями «Начало», «Конец», «Сообщение» и «Код разрешения», а также «Блокировка регламентных заданий включена» и «Разрешить выдачу лицензий сервером 1С:Предприятия». Как закрыть вход перед обновлением и войти с ключом /UC — в статье «Блокировка базы 1С». При удалении консоль предлагает удалить базу данных целиком, очистить её или оставить без изменений; если данные в СУБД ещё нужны, выбирайте последнее.
Колонка «Приложение» в узле «Сеансы» показывает, кто подключён: 1CV8C — тонкий клиент, 1CV8 — толстый, WebClient — браузер, Designer — конфигуратор, BackgroundJob — фоновое задание, COMConnection — внешнее соединение, SrvrConsole — сама консоль. В контекстном меню сеанса две нужные команды:
«Соединения» разрывают редко — обычно хватает сеансов. Зависшие фоновые задания ищите по приложению BackgroundJob и колонке «Время вызова (текущее)».
Узел «Блокировки» показывает объектные блокировки кластера, например монопольный или разделяемый доступ сеансов к базе. Транзакционных управляемых блокировок, из-за которых документ висит при проведении, там нет. Кто кого ждёт, показывают колонки сеансов «Заблокировано упр.» и «Заблокировано СУБД»: в них номер сеанса, который держит блокировку. Когда сеансов сотни, пары удобнее собрать кодом — функция ниже. Как сократить время блокировок — в статье про транзакции.
В «Рабочих процессах» видны PID каждого rphost, память и «Доступная производительность» — по ней кластер выбирает процесс для нового клиента. С 8.3.27 разросшийся процесс можно выключить командой «Выключить рабочий процесс»: он остановится, когда отключатся пользователи или истечёт время принудительного завершения. В той же версии перезапуск процессов задают «Расписанием перезапуска» в формате cron — для кластера или отдельного рабочего сервера, а старый интервал перезапуска больше не действует. Лимиты памяти задают в свойствах рабочего сервера: «Критический объем памяти процессов», «Временно допустимый объем памяти процессов» и интервал его превышения. С лицензией ПРОФ они влияют только на перезапуск процессов, прерывать по ним вызовы умеет лишь КОРП. Если база тормозит без видимой причины, начните с диагностики производительности.
MMC есть только в Windows. Кластер на Linux администрируют четырьмя способами:
rac через сервер администрирования ras. Она работает на любой ОС и годится для скриптов.АдминистрированиеСервера, о нём ниже.С 8.3.21 в дистрибутив для Linux входят systemd-сценарии запуска кластера и ras:
# Linux, платформа 8.3.21+: ras как служба systemd, unit-файл лежит в каталоге платформы
V=8.3.27.1786
sudo systemctl link /opt/1cv8/x86_64/$V/ras-$V.service
sudo systemctl enable --now ras-$V
# без systemd: /opt/1cv8/x86_64/$V/ras cluster --daemon --port=1545 localhost:1540
rac не обязан совпадать по версии с ras, а ras управляет кластерами других версий начиная с 8.3.9 — доступно то, что поддерживают обе стороны. Скрипт ниже делает то, ради чего обычно открывают консоль.
#!/bin/bash
# rac-check.sh <имя базы в кластере>: долгие вызовы, ожидания блокировок, процессы
RAC=/opt/1cv8/x86_64/8.3.27.1786/rac
RAS=srv01:1545 # адрес ras, а не агента (1540)
IB_NAME=${1:?укажите имя базы в кластере}
AUTH=() # если заведены администраторы кластера:
# AUTH=(--cluster-user="$CL_USER" --cluster-pwd="$CL_PWD")
# rac печатает записи блоками "ключ : значение", блоки разделены пустой строкой.
# rows поле1 поле2 ... -> по строке на запись, поля через табуляцию
rows() { awk -v want="$*" 'BEGIN { RS = ""; FS = "\n"; n = split(want, k, " ") }
{ delete r
for (i = 1; i <= NF; i++) { p = index($i, ":"); if (!p) continue
key = substr($i, 1, p - 1); gsub(/[ \t]/, "", key)
val = substr($i, p + 1); gsub(/^[ \t"]+|[ \t"]+$/, "", val); r[key] = val }
line = r[k[1]]; for (j = 2; j <= n; j++) line = line "\t" r[k[j]]; print line }'; }
CL=$($RAC $RAS cluster list | rows cluster port | awk -F'\t' '$2 == 1541 { print $1 }')
IB=$($RAC $RAS infobase summary list --cluster="$CL" "${AUTH[@]}" | rows infobase name |
awk -F'\t' -v n="$IB_NAME" '$2 == n { print $1 }')
[ -n "$IB" ] || { echo "база $IB_NAME не найдена в кластере"; exit 1; }
echo "== Сеансы: вызов дольше 30 с или ожидание блокировки"
$RAC $RAS session list --cluster="$CL" "${AUTH[@]}" --infobase="$IB" |
rows session-id user-name app-id duration-current blocked-by-ls blocked-by-dbms |
awk -F'\t' '$4 > 30000 || $5 > 0 || $6 > 0 {
printf "сеанс %s %s (%s): вызов %d с, ждёт упр. %s, СУБД %s\n", $1, $2, $3, $4 / 1000, $5, $6 }'
echo "== Объектные блокировки базы"
$RAC $RAS lock list --cluster="$CL" "${AUTH[@]}" --infobase="$IB" | rows session locked descr
echo "== Рабочие процессы: сервер, PID, память, доступная производительность"
$RAC $RAS process list --cluster="$CL" "${AUTH[@]}" | rows host pid memory-size available-perfomance
# Прервать серверные вызовы клиентов дольше 20 минут. DRY=0 - выполнить, иначе только показать
$RAC $RAS session list --cluster="$CL" "${AUTH[@]}" --infobase="$IB" |
rows session app-id duration-current |
awk -F'\t' '($2 == "1CV8C" || $2 == "1CV8" || $2 == "WebClient") && $3 > 1200000 { print $1 }' |
while read -r SID; do
if [ "${DRY:-1}" = 1 ]; then echo "будет прерван вызов сеанса $SID"; continue; fi
$RAC $RAS session interrupt-current-server-call --cluster="$CL" "${AUTH[@]}" \
--session="$SID" --error-message="Операция прервана администратором: дольше 20 минут"
done
# Перед обновлением: lock_ib on, после него: lock_ib off. Нужен администратор базы;
# IB_USER, IB_PWD и код разрешения UC_CODE - из переменных окружения, не в тексте скрипта
lock_ib() {
$RAC $RAS infobase update --cluster="$CL" "${AUTH[@]}" --infobase="$IB" \
--infobase-user="$IB_USER" --infobase-pwd="$IB_PWD" \
--sessions-deny="$1" --scheduled-jobs-deny="$1" \
--denied-message="Обновление базы, вход временно закрыт" --permission-code="$UC_CODE"
}
Функция rows превращает блоки «ключ : значение» в строки с нужными полями, дальше хватает awk. В blocked-by-ls и blocked-by-dbms — те же номера, что в колонках «Заблокировано упр.» и «Заблокировано СУБД». Без DRY=0 скрипт только показывает, чьи вызовы прервёт. На Windows команды rac те же.
С версии 8.3.14 кластером можно управлять из встроенного языка без COM. Объект АдминистрированиеСервера подключается к ras, доступен на сервере, в тонком и толстом клиенте и не требует совпадения версий клиента и кластера. До него оставался COM-объект V83.COMConnector: только Windows и строго та же версия. Код ниже рассчитан на модуль формы внешней обработки. Первый листинг — подключение, остальные его используют.
// Модуль формы внешней обработки «Консоль кластера». Платформа 8.3.14 и новее,
// на сервере 1С запущен ras. В общем модуле с флагом «Сервер» директивы не нужны.
// Адрес ras и порт кластера - под свой сервер. Пароль администратора кластера
// передавайте из формы или безопасного хранилища, а не строкой в коде.
&НаКлиентеНаСервереБезКонтекста
Функция ПараметрыПодключения(Знач Администратор = "", Знач Пароль = "")
Возврат Новый Структура("АдресRAS, ПортRAS, ПортКластера, Администратор, Пароль",
"srv01", 1545, 1541, Администратор, Пароль);
КонецФункции
&НаСервереБезКонтекста
Функция КластерСерверов(Знач Подключение)
Агент = Новый АдминистрированиеСервера(Подключение.АдресRAS, Подключение.ПортRAS);
Для Каждого Кластер Из Агент.ПолучитьКластеры() Цикл
Если Кластер.Порт = Подключение.ПортКластера Тогда
// Если администраторы кластера не заведены, имя и пароль - пустые строки
Кластер.ВыполнитьАутентификацию(Подключение.Администратор, Подключение.Пароль);
Возврат Кластер;
КонецЕсли;
КонецЦикла;
ВызватьИсключение СтрШаблон("На %1:%2 нет кластера с портом %3", Подключение.АдресRAS,
Формат(Подключение.ПортRAS, "ЧГ="), Формат(Подключение.ПортКластера, "ЧГ="));
КонецФункции
&НаСервереБезКонтекста
Функция БазаВКластере(Кластер, Знач ИмяВКластере)
Для Каждого База Из Кластер.ПолучитьИнформационныеБазы() Цикл
Если НРег(База.Имя) = НРег(ИмяВКластере) Тогда
Возврат База;
КонецЕсли;
КонецЦикла;
// Нужно имя базы в кластере (Ref в строке соединения), а не имя базы данных в СУБД
ВызватьИсключение СтрШаблон("В кластере нет информационной базы ""%1""", ИмяВКластере);
КонецФункции
// Истина, если код выполняется в этой же базе: Srvr="srv01";Ref="trade";
&НаСервереБезКонтекста
Функция ЭтоТекущаяБаза(Знач ИмяВКластере)
СтрокаСоединения = НРег(СтрокаСоединенияИнформационнойБазы());
Возврат СтрНайти(СтрокаСоединения, "ref=""" + НРег(ИмяВКластере) + """") > 0;
КонецФункции
Главная функция для разбора «почему всё висит» — сеансы с долгим вызовом и ожиданием блокировок вместе с виновниками:
// Сеансы базы, которые ждут чужую блокировку или долго выполняют серверный вызов.
// Возвращает массив структур - его можно передать на клиент.
&НаСервереБезКонтекста
Функция ПроблемныеСеансы(Знач Подключение, Знач ИмяВКластере, Знач ПорогСекунд = 30)
База = БазаВКластере(КластерСерверов(Подключение), ИмяВКластере);
Сеансы = База.ПолучитьСеансы();
ПоНомеру = Новый Соответствие; // номер сеанса -> сеанс, чтобы найти виновника
Для Каждого Сеанс Из Сеансы Цикл
ПоНомеру.Вставить(Сеанс.НомерСеанса, Сеанс);
КонецЦикла;
Результат = Новый Массив;
Для Каждого Сеанс Из Сеансы Цикл
ЖдетУправляемую = Сеанс.НомерСеансаВыполнившегоУправляемуюБлокировку;
ЖдетСУБД = Сеанс.НомерСеансаБлокирующегоСУБД;
ВызовСекунд = Окр(Сеанс.ДлительностьВызововТекущее / 1000); // свойство - в миллисекундах
Если ЖдетУправляемую = 0 И ЖдетСУБД = 0 И ВызовСекунд < ПорогСекунд Тогда
Продолжить;
КонецЕсли;
Описание = Новый Структура("Номер, Пользователь, Приложение, Компьютер, ВызовСекунд, Ждет",
Сеанс.НомерСеанса, Сеанс.ИмяПользователя, Сеанс.ИмяПриложения, Сеанс.ИмяКомпьютера,
ВызовСекунд, "");
НомерВиновника = ?(ЖдетУправляемую <> 0, ЖдетУправляемую, ЖдетСУБД);
ВидБлокировки = ?(ЖдетУправляемую <> 0, "управляемую блокировку", "блокировку СУБД");
Виновник = ПоНомеру.Получить(НомерВиновника);
Если Виновник <> Неопределено Тогда
Описание.Ждет = СтрШаблон("%1 сеанса %2 (%3, %4, вызов идет %5 с)", ВидБлокировки,
Виновник.НомерСеанса, Виновник.ИмяПользователя, Виновник.ИмяПриложения,
Окр(Виновник.ДлительностьВызововТекущее / 1000));
ИначеЕсли НомерВиновника <> 0 Тогда
Описание.Ждет = СтрШаблон("%1 сеанса %2", ВидБлокировки, НомерВиновника);
КонецЕсли;
Результат.Добавить(Описание);
КонецЦикла;
Возврат Результат;
КонецФункции
// Обработчик команды формы: проблемные сеансы базы trade
&НаКлиенте
Процедура ПоказатьПроблемныеСеансы(Команда)
Сеансы = ПроблемныеСеансы(ПараметрыПодключения(), "trade", 30);
Если Сеансы.Количество() = 0 Тогда
Сообщить("Ожиданий блокировок и долгих серверных вызовов нет");
КонецЕсли;
Для Каждого Описание Из Сеансы Цикл
Сообщить(СтрШаблон("Сеанс %1, %2 (%3, %4): вызов %5 с. %6", Описание.Номер,
Описание.Пользователь, Описание.Приложение, Описание.Компьютер, Описание.ВызовСекунд,
?(ПустаяСтрока(Описание.Ждет), "", "Ждет " + Описание.Ждет)));
КонецЦикла;
КонецПроцедуры
Если отчёт пользователя крутится полчаса, вызов можно прервать, не выкидывая человека из программы:
// Прерывает серверные вызовы, которые идут дольше ПорогМинут. Сеанс остается,
// пользователь получит ошибку с текстом ТекстОшибки. Свой сеанс не трогаем.
// Приложения - массив идентификаторов вида "1CV8C"; по умолчанию только клиенты пользователей.
&НаСервереБезКонтекста
Функция ПрерватьДолгиеВызовы(Знач Подключение, Знач ИмяВКластере, Знач ПорогМинут = 20,
Знач Приложения = Неопределено)
Если Приложения = Неопределено Тогда
// Конфигуратор (Designer) и фоновые задания (BackgroundJob) без явного указания не трогаем
Приложения = СтрРазделить("1CV8C,1CV8,WebClient", ",");
КонецЕсли;
База = БазаВКластере(КластерСерверов(Подключение), ИмяВКластере);
СвойНомер = ?(ЭтоТекущаяБаза(ИмяВКластере), НомерСеансаИнформационнойБазы(), 0);
ТекстОшибки = СтрШаблон("Операция прервана администратором: выполнялась дольше %1 мин.", ПорогМинут);
Прерванные = Новый Массив;
Для Каждого Сеанс Из База.ПолучитьСеансы() Цикл
Если Сеанс.НомерСеанса = СвойНомер
Или Сеанс.ДлительностьВызововТекущее < ПорогМинут * 60000
Или Приложения.Найти(Сеанс.ИмяПриложения) = Неопределено Тогда
Продолжить;
КонецЕсли;
Попытка
Сеанс.ПрерватьТекущийСерверныйВызов(ТекстОшибки);
Прерванные.Добавить(СтрШаблон("%1 (%2, %3)", Сеанс.НомерСеанса, Сеанс.ИмяПользователя,
Сеанс.ИмяПриложения));
Исключение
// Вызов мог закончиться сам между получением списка и прерыванием
ЗаписьЖурналаРегистрации("Консоль кластера", УровеньЖурналаРегистрации.Предупреждение, , ,
КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЦикла;
Возврат Прерванные;
КонецФункции
Операции с базой и рабочими процессами — запрет регламентных заданий в тестовой копии и сводка по памяти rphost:
// Запрет регламентных заданий: копия рабочей базы, развернутая как тестовая, не должна
// отправлять письма и выгружать заказы на сайт. ПользовательИБ - администратор этой базы.
&НаСервереБезКонтекста
Процедура УстановитьЗапретРегламентныхЗаданий(Знач Подключение, Знач ИмяВКластере,
Знач ПользовательИБ, Знач ПарольИБ, Знач Запретить = Истина)
База = БазаВКластере(КластерСерверов(Подключение), ИмяВКластере);
База.ВыполнитьАутентификацию(ПользовательИБ, ПарольИБ);
Если База.БлокировкаРегламентныхЗаданий <> Запретить Тогда
База.БлокировкаРегламентныхЗаданий = Запретить;
База.Записать();
КонецЕсли;
КонецПроцедуры
// Рабочие процессы кластера: где растет память и падает производительность
&НаСервереБезКонтекста
Функция СостояниеРабочихПроцессов(Знач Подключение)
Результат = Новый Массив;
Для Каждого Процесс Из КластерСерверов(Подключение).ПолучитьРабочиеПроцессы() Цикл
Описание = Новый Структура;
Описание.Вставить("Сервер", Процесс.ИмяКомпьютера);
Описание.Вставить("PID", Процесс.ИдентификаторПроцесса);
Описание.Вставить("Порт", Процесс.Порт);
Описание.Вставить("Активен", Процесс.Активен);
Описание.Вставить("ПамятьМБ", Окр(Процесс.ПотреблениеПамяти / 1048576)); // в байтах
Описание.Вставить("Производительность", Процесс.ДоступнаяПроизводительность);
Описание.Вставить("СреднийВызовСек", Процесс.СредняяДлительностьВызова); // в секундах
Описание.Вставить("ПревышениеПамятиСек", Процесс.ВремяПревышенияПоПамяти);
Результат.Добавить(Описание);
КонецЦикла;
Возврат Результат;
КонецФункции
Новый АдминистрированиеСервера(Подключение.АдресRAS, Подключение.ПортRAS) — адрес и порт ras: 1545, а не 1540. Код выполняется на сервере 1С, и ras должен быть доступен оттуда.Кластер.ВыполнитьАутентификацию(...) — без неё ПолучитьИнформационныеБазы() не сработает (так в справке); пустые имя и пароль — для кластера без администраторов.ПоНомеру — соответствие «номер сеанса → сеанс». Свойства НомерСеансаВыполнившегоУправляемуюБлокировку и НомерСеансаБлокирующегоСУБД содержат номер виновника или 0.ДлительностьВызововТекущее — сколько миллисекунд идёт текущий серверный вызов; 0 — сеанс ничего не выполняет. А СредняяДлительностьВызова процесса — в секундах, ПотреблениеПамяти — в байтах: не перепутайте пороги.ПрерватьТекущийСерверныйВызов(ТекстОшибки) — пользователь получит исключение с этим текстом. ЗавершитьСеанс(Текст) закрыл бы сеанс целиком.СвойНомер — чтобы функция не прервала саму себя. Номер сеанса уникален только внутри базы, поэтому сравниваем его лишь для текущей базы.База.ВыполнитьАутентификацию(ПользовательИБ, ПарольИБ) перед Записать() — то же, что ключи --infobase-user и --infobase-pwd у rac.radmin.dll удалённой версии. Запустите «Регистрация утилиты администрирования серверов» нужной версии или regsvr32 из первого листинга.localhost:1545.--cluster-user и --cluster-pwd, в коде передайте имя и пароль в ПараметрыПодключения.rac infobase info и update, запись в коде) нужен пользователь этой базы с административными правами.Консоли нет в дистрибутиве тонкого клиента. Запустите установщик полной платформы той же версии, что сервер, отметьте компонент «Администрирование сервера 1С:Предприятия» и зарегистрируйте консоль ярлыком «Регистрация утилиты администрирования серверов». Если ставить ничего нельзя, откройте в клиенте 8.3.15 и новее «Все функции → Стандартные → Управление серверами» — нужен только запущенный ras.
Удаление закрывает сеанс, несохранённые данные пропадают. Прерывание останавливает только текущую серверную операцию, и пользователь работает дальше. Для зависшего отчёта начинайте с прерывания.
Там только объектные блокировки кластера, транзакционные управляемые не показываются. Виновника ищите в «Сеансах» по колонкам «Заблокировано упр.» и «Заблокировано СУБД» или функцией ПроблемныеСеансы.
Консоль работает с той версией radmin.dll, которая зарегистрирована последней, поэтому перед переходом к другому серверу её перерегистрируют ярлыком нужной версии. Удобнее rac и АдминистрированиеСервера: ras управляет кластерами других версий (от 8.3.9), а объекту встроенного языка совпадение версий не нужно.
Если блокировки повторяются каждый день, процессы растут по памяти или нужен ночной сценарий «закрыть вход — обновить — открыть» без ручной работы в консоли, это задача для программиста, который сопровождает серверы 1С. Опишите проблему на площадке: разместить задачу можно бесплатно, оценка тоже бесплатная, ответ — в течение рабочего дня. Если база просто медленно работает, посмотрите услугу «1С тормозит».
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.