Исполнение команд операционной системы на сервере Caché

По мотивам статьи в Developer Connection написал свою реализациию класса для вызова команд операционной системы сервера, где установлена Caché или Ensemble.
Класс может пригодиться, когда нужно из Caché что-то сделать на хостовой ОС: распорядиться файлами бэкапов, настроить работу с системой контроля версий и другие полезные действия.
Класс позволяет выполнить команду на любой хостовой ОС и получить ответ в глобал или локальную переменную.

Код класса с комментариями

Class Server.Manage Extends %RegisteredObject
{

Parameter cmdlist = "dir,type,ver";

/// метод убирает из командной строки последовательности команд
/// оставляет только разрешённые команды
ClassMethod 
safeCmd(cmdAs %String
{
  
set cmd=$piece(cmd,"&&")  // оставляем одну команду
  
set cmd=$piece(cmd,"|")
  
for i=1:1:$length(..#cmdlist,","set safe($p(..#cmdlist,",",i))=""  // список разрешённых команд
  
if $data(safe($piece(cmd," "))) set cmd=""   
  
quit cmd
}

/// метод выполняет команду cmd на сервере и складывает результат в глобал ad так, что:
/// @ad=количество строк
/// @ad@(номер строки)=значениеa
ClassMethod 
runCmd(cmdad As %StringAs %Status
{
  
set sc=$$$OK
  do $SYSTEM
.Process.SetZEOF(1)     // выключаем режим генерации ошибки на EOF
  // делаем командную строку безопасной
  
set cmd(1)=..safeCmd(cmd
  
quit:cmd(1)="" $$$ERROR($$$GeneralError,"Недопустимая команда "_cmd)
  
set cmd=cmd(1)
  
// очищаем присланный глобал
  
kill @ad
  
set count=0

  try {
  
// открываем устройство с выполнением командной строки и чтением ответа
  
open cmd:"QR:K\CP866\" if $test  $$$ThrowStatus($$$ERROR($$$GeneralError,"Не удалось выполнить команду "_cmd))
  
Set IO=$IO  // запоминаем текущее устройство
  // вычитываем построчно результат команды пока не наступит конец файла и складываем его в глобал
  
for  
    
use cmd 
    
read str quit:$zeof=-1
    
set @ad@($Increment(count))=str
    
}
  
set @ad=count
  
// закрываем устройство 
  
#dim as %Exception.AbstractException
  
Catch {
      
set sc=e.AsStatus()
      
//do e.Log()   // 
  
}
  
// закрываем устройство 
  
close cmd

  // возвращаем текущее устройство
  
If $data(IOUse IO
 
quit sc
}

}
Параметр cmdlist содержит список разрешённых команд через запятую.
Метод safeCmd() причёсывает командную строку.
Метод runCmd() собственно выполняет команду cmd и кладёт результат в косвенный адрес ad.

Приведённый код работает на всех операционных системах, поддерживаемых Caché, исполняет команды, получает результат и обрабатывает ошибки. В отличие от реализации, описанной в статье, работа организована через устройство CommandPipe – режим “QR” для команды open. Подробнее можно почитать в документации.

Демо

Пример использования можно наблюдать здесь – небольшой проект, собранный на CSP+Twitter Bootstrap.
Сервер не отдан на заклание – разрешённые команды: type, ver, format с, dir.
Код класса и веб-проекта выложен на гитхабе.

Добавить комментарий

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