В связи с переходом на отечественное ПО в организации пришлось искать замену Windows утилиты администрирования кластера. После изучения вопроса выяснилось, что для администрирования кластера 1С существует 3 подхода:

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

  2. Windows утилита администрирования кластера — графический интерфейс, только под Windows. Достаточно удобная, но под российскими операционными системами она не работает (может под каким-нибудь wine и запуститься, но этот вариант не всегда приемлем).

  3. Консольная утилита rac (Remote Administrative Client) — кроссплатформенная, но консольная. Конечно, весь функционал присутствует, но не сказать, чтобы это было прямо сильно удобно.

Изучив альтернативные варианты, был найден только один вариант, написанный на java. Кроссплатформенный, с красивым веб-интерфейсом и очень богатый функциями. Весьма не- плохой вариант, но мне его функционала было слишком много (один сервер, два десятка пользователей).

Решил сделать что-то своё с необходимым минимальным количеством функций. Для начала нужно было определиться, как получать данные из 1с. Немного изучив консольное приложение, решил, что проще всего будет сделать небольшой php скрипт (на сервере уже крутилась публикация приложений 1с под apache2), который будет возвращать ответы от консольной утилиты в виде json, а для интерфейса пользователя использовать приложение на javascript.

Когда выбор инструментария был сделан, осталось придумать, в каком виде передавать запросы и параметры для консольной утилиты (rac).

После изучения синтаксиса командной строки оказалось вполне логично передавать все данные запроса через GET запрос. Причём команды удобно передавать как часть URL — путь к ресурсу, а параметры в виде параметров. Таким образом получился следующий формат запроса:

http://localhost/192.168.1.2/infobase/summary/list?cluster=00000000-0000-0000-0000-000000000000

который преобразовывался в командную строку вида:

rac 192.168.1.2 infobase summary list —cluster=00000000-0000-0000-0000-000000000000

Таким образом, можно давать любые команды консольной утилите через URL.

Далее, изучая ответы утилиты администрирования, стало понятно, что нужно делить строки на имя параметра и его значение по символу двоеточия «:», а отделять один блок информации от другого по пустой строке между блоками.

Спустя некоторое время я написал небольшой скрипт, выполняющий задуманное. Чтобы постоянно не писать адрес сервера администрирования, решил его внести в сборку командной строки через определение константы admServer. При необходимости её можно выкинуть из скрипта (ниже привожу листинг моего файла index.php с небольшими комментариями).

<?php
define('pathToRac', '/opt/1cv8/x86_64/8.3.22.2106/rac');
define('admServer', '192.168.1.2');

Определяем константы: pathToRac — путь в утилите администрирования, admServer — IP адрес сервера администрирования (порт стандартный, но можно и указать).

function responseToArray($response)
{
   $result = array();
   $object = array();

   if (count($response) > 0) {
      for ($i = 0; $i < count($response); $i++) {
         if ($response[$i] !== '') {
            preg_match('/(?<key>[^:]*)[ ]*:(?<value>.*)/', $response[$i], $matches);
            $object[trim($matches['key'])] = trim($matches['value']);
         } else {
            $result[] = $object;
            $object = array();
         }
      }
   }

   return $result;
}

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

$request = explode('?', $_SERVER['REQUEST_URI']);
$request = array_filter($request, 'strlen');
$parts = explode('/', $request[0]);
$parts = array_filter($parts, 'strlen');

Здесь глобальная переменная REQUEST_URI разделяется по знаку вопроса на две части: адрес и параметры. Удаляются пустые элементы массива ($request). Берётся первая часть ($request[0]) — адрес и разделяется на отдельные команды для утилиты администрирования. Так же удаляются пустые элемента массива ($parts).

if (count($parts) > 0) {
   $commandLine = implode(' ', $parts);
   $params = '';
   foreach ($_GET as $key => $value) {
      if ($key !== '' && $value !== '') {
         $params .= ' ' . '--' . $key . '=' . $value;
      }
   }

   $commandLine = pathToRac . ' ' . admServer . ' ' . $commandLine . $params;
   exec($commandLine, $outputArray, $retval);

Если есть команды для rac, то собираем командную строку. Вначале объединяем в строку все команды через пробел. Далее перебираем все параметры переданные через GET запрос из глобального массива $_GET и собираем их в строковую переменную $params, предварительно добавляя перед именем параметра два знака минус «--», а после знак равно «=» и значение параметра. Следом собираем всю командную строку в переменную $commandLine и передаём на выполнение.

   if ($retval == 0) {
      preg_match('/Remote Administrative Client Utility/', $outputArray[0], $matches);
      if (count($matches) > 0) {
         $result['error'] = -1;
         $result['output'] = $outputArray;
      } else {
         $result['error'] = 0;
         $result['objects'] = responseToArray($outputArray);
      }
   } else {
      $result['error'] = $retval;
      $result['output'] = $outputArray;
   }

В этой части происходит обработка результата выполнения команды. Если получаем код выхода из консольной утилиты равным нулю, значит утилита отработала нормально, и можно разбирать результаты. Если в результате выполнения в первую строку ответа утилиты управления попала подстрока «Remote Administrative Client Utility», то будем считать, что это не результат, который нам нужен, и выставив флажок ($result['error']) успешности выполнения в значение «-1», вернём весь вывод консоли. А если нет выше указанной подстроки, то вывод из консоли обрабатываем нашей функцией responseToArray. При возникновении ошибки значение переменной $retval будет больше 0, значит ставим флажок ($result['error']) в значение вернувшееся после выполнения утилиты администрирования и передаём весь массив строк вывода консоли.

   header('Content-Type: application/json; charset=utf-8');
   echo json_encode($result);
} else {
   include_once('app.php');
}
?>

Оборачиваем ответ в json и передаём на клиентскую сторону. Если никаких параметров в URL не передано, то подключаем скрипт отвечающий за frontend.

Для работы вышеуказанного скрипта ещё нужно настроить веб сервер (у меня настройка для сервера apache2). Содержимое файла .htaccess:

Options -Indexes
ErrorDocument 403 /

<Files *.php>
    deny from all
</Files>

<Files index.php>
    allow from all
</Files>

<IfModule mod_rewrite.c>
    RewriteEngine On
    Options +FollowSymlinks
    RewriteBase /

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>

Таким образом получилась обёртка над консольной утилитой, позволяющая создать полноценное веб-приложение.

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

Надеюсь мой опыт кому-то пригодиться. Спасибо за потраченное на чтение время.

Комментарии (13)


  1. jackmas
    04.10.2024 17:27

    Хорошая статья, беру в копилку. Не увидел , это решение для linux или windows ?


    1. fr1703 Автор
      04.10.2024 17:27

      я это писал под linux, но можно использовать и на windows серверах.


  1. AlexLeonov
    04.10.2024 17:27

    Чем хорош PHP - на нем можно писать в таком стиле, за который уже 15 лет назад руки отрывали, а оно всё равно работает ))


    1. fr1703 Автор
      04.10.2024 17:27

      в двадцать строк кода внедрять ООП считаю излишним.


  1. mikleh
    04.10.2024 17:27

    И что, никто еще не догадался в параметры "; rm -rf /" передать?


    1. fr1703 Автор
      04.10.2024 17:27

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


  1. Necessitudo
    04.10.2024 17:27

    А что за утилита на Java?


    1. fr1703 Автор
      04.10.2024 17:27

      ПУСК от IT Expertise


  1. bo_va
    04.10.2024 17:27

    У меня на infostart есть разработка сценария администрирования для bash с использованием rac и ras если что.


    1. fr1703 Автор
      04.10.2024 17:27

      спасибо. где можно ознакомиться?


      1. bo_va
        04.10.2024 17:27

        Публикация называется "Интерфейс к утилите администрирования кластера серверов для ОС Linux", на infostart.ru должна найтись.


  1. svk28
    04.10.2024 17:27

    Первые строки в выводe поиска по "racgui" на yandex. И тут на хабре есть статья по rac gui.