- PVSM.RU - https://www.pvsm.ru -

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

По мотивам статьи в Developer Connection [1] написал свою реализациию класса для вызова команд операционной системы сервера, где установлена 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:KCP866" 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é, исполняет команды, получает результат и обрабатывает ошибки. В отличие от реализации, описанной в статье [1], работа организована через устройство CommandPipe — режим «QR» для команды open. Подробнее можно почитать в документации [2].

Демо

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

Автор: morisson

Источник [5]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/razrabotka/30681

Ссылки в тексте:

[1] Developer Connection: https://developer.intersystems.com/devconnection/build/402-17/running-an-os-command

[2] в документации: http://docs.intersystems.com/cache20122/csp/docbook/DocBook.UI.Page.cls?KEY=GIOD_interproccomm#GIOD_C89992

[3] здесь: http://188.127.249.14:57772/csp/runcmd/run.csp

[4] гитхабе: https://github.com/intersystems-ru/cache-run-cmd

[5] Источник: http://habrahabr.ru/post/174601/