Язык программирования 'Sequence'

Клиент okerr имеет встроенный процессор "языка программирования" под рабочим названием 'Sequence' (сиквенс).

Особенности языка Sequence и сфера применения

Язык sequence, прямо скажем, не очень удобен, не очень гибкий, в нем нет даже циклов (и мы это специально сделали!).

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

На языке sequence можно писать код задач для мониторинга, например - посчитать количество ошибок аутентификации в логе, посмотреть наличие слова "error" в выводе утилиты RAID-мониторинга, проверить, что запущены определенные процессы, итд.

Преимущество языка sequence в том, что он пригоден для целей мониторинга (так же, как и многие другие языке программирования), но при этом код на sequence заведомо безопасен. На самом языке sequence невозможно выполнить такие опасные операции как форматирование диска, удаление или запись в файлы, на нем даже невозможно создать вечный цикл. Условно-опасные операции, такие как вызов внешних программ или чтение файлов - запрещены по умолчанию, но могут быть выборочно разрешены на клиентской стороне. Например, вы можете разрешить программе на sequence чтение данных из определенного лог-файла, но они не смогут прочитать другие файлы на системе. Можете разрешить запуск программы мониторинга RAID, но при этом нельзя будет запустить /bin/rm.

Благодаря этому намеренно урезанному функционалу есть возможность безопасно хранить код диагностических скриптов на стороне сервера. Даже в случае каких-то злонамеренных модификаций на серверной стороне (например, если взломщики получат доступ к серверам okerr и модифицируют ваши подпрограммы на сервере) - эти модификации не смогут ни навредить клиенсткой машине, которая исполняет sequence-код с сервера, ни прочитать с нее никакие данные, кроме тех, к которым разрешен доступ.

При хранении диагностических скриптов на сервере, есть возможность изменять их прямо на сервере, не заходя на клиентскую машину, и централизованно управлять ими - например, внести изменения в скрипт, и при следующей проверке он автоматически будет исполнен в новом виде сразу на всех серверах, которые его используют. Можно разом сделать резервную копию всех скриптов. Все машины могут использовать одинаковую клиентскую часть, что удобно при установке и восстановлении систем, а специфика (например - дополнительные тесты для почтового сервера) - будут динамически браться с сервера okerr.

Как избежать программирования на sequence

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

Кроме того, вы можете использовать свои скрипты (на любых языках) для диагностики, и просто вызывать okerrclient для изменения состояния индикаторов, например:

okerrclient -s OK

okerrclient --name shop:TodayOrders -s 'STR 23'

Вы уже используете sequence

Даже выполняя такую простую команду:

okerrclient -s OK

на самом деле исполняется команда "OK" на языке sequence, которая устанавливает статус ОК у текущено индикатора. Имя индикатора по-умолчанию - имя хоста.

Каждый раз когда вы просто запускаете okerrclient без параметров в конфигурации по умолчанию, из файла конфигурации берется аргумент sequence, который (по умолчанию): [ MKSEQ servers:$_name|conf:anyserver ]

Команда MKSEQ забирает данные с сервера с пути server:$_name, а если там нет ключей, то с пути conf:anyserver. Затем полученные ключи конвертируются в последовательсость команд и исполняются.

Структура программы на Sequence

Программа на sequence состоит из последовательности команд, которые исполняются линейно (подобно конвейеру в unix системах, ps | grep apache | wc -l). В ней нет циклов и условных операторов. Единственная команда, которая нарушает линейность - команда FORK, которая распараллеливает обработку.

Каждая команда работает с контекстом. Контекст - это структура из нескольких элементов, которая переходит от одной команды скрипта к следующей и так далее. В контексте хранится имя индикатора, набор переменных и данные (data), которые обрабатываются командами. После завершения исполнения последней команды, если в контексте есть данные - то обновляется индикатор, имя которого задано в контексте.

Посмотреть содержимое контекста можно командой SEQDUMP.

Рассмотрим такую команду:

Создадим в интерфейсе индикатор test, и установим ему тип numerical. Затем выполним:

okerrclient --name test -s PROCESSES LEN 

Ключ --name задает исходное имя индикатора. Его можно изменить по ходу работу скрипта.

Команда PROCESSES не требует входных данных, на выходе дает список процессов в системе. Он передается следующей команде - LEN. Команда LEN возвращает длину списка.

По исполнению последней команды, если в результате есть данные - они отправляются на сервер в качестве значения индикатора. Данные индикатора (имя и прочие) определяются из контекста. Именем индикатора будет test. (задан через --name)

Через такой скрипт можно отслеживать количество процессов на сервере.

Теперь рассмотрим более сложный пример:

okerrclient --name test -s 'NAME $_name:ps' 'METHOD numerical maxlim=450' PROCESSES LEN 

До исполнения sequence скрипта, через ключ --name в контексте устанавливается имя индикатора 'test'. Оно далее доступно через переменную $_name. (Если его не указывать, и)

Первая команда скрипта на sequence: 'NAME $_name:ps'. Так как команда имеет аргументы, она должна быть заключена в одинарные или двойные кавычки (иначе будет ошибка - будет принято как одна команда NAME (без параметров) и следующая команда $_name:ps, которая не будет опознана)

Исходно имя задано через --name test, после выполнения команды NAME с аргументами, имя будет 'test:ps'. Далее, команда METHOD устанавливает тип индикатора numeriсal, и его аргумент maxlim=450.

Далее, команды PROCESSES и LEN работают так же, как и в предыдущем примере. По завершению обработки клиент отправит результат в индикатор test:ps. Если такого индикатора не существует - он будет создан с указанным в METHOD типом и аргументами.

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

Способы указания скриптов

Командной строкой

Самый простой способ, описаный выше - через опцию -s:

$ okerrclient  -s 'NAME asdf' OK
okerr updated asdf = OK

Способ может быть не очень удобен если нужно использовать кавычки/апострофы или скритп очень длинный.

Другие способы более подробно объяснены в описании команды MKSEQ, но здесь мы их кратко опишем только:

Исполнить скрипт с сервера

$ okerrclient -s 'MKSEQ lib:uptime' 
okerr updated braconnier:uptime = 283101

Исполнить скрипт из текстового файла:

$ cat /tmp/script.seq 
NAME test
OK

$ okerrclient  --tpconf FILE:read=/tmp/script.seq -s "SEQFILE /tmp/script.seq" 
okerr updated test = OK

Свойства команд на Sequence

Список команд можно получить через okerrclient -h.

У команды есть название (например, DATETIME, NAME, JDUMP), название команды традиционно задается большими буквами.

У команды могут быть аргументы и параметр. Между (в терминологии sequence) ними есть различие. Параметр - частный случай аргумента, он всегда единственный, и задается просто значение параметра после команды (без указания его имени), например: STR hello!. Аргументов может быть произвольное число, но задаются они через имена, например: DIR path=/tmp или DIR path=/tmp sha256=1. Параметры используются для простых команд, а аргументы - для более сложных.

Подробную информацию по команде, ее аргументах и параметре можно посмотреть командой okerrclient -h <COMMAND>. Например, okerrclient -h STR , okerrclient -h DIR.

Отладка программ на Sequence

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

Read-only

При отладке не всегда требуется посылать обновление индикатора на сервер. Чтобы избежать этого, можно использовать команду в конце обработки NONE. Она удаляет текущие данные и индикатор не обновляется. Кроме этого приямого способа, технически так же подходят другие способы, например, изменить --url сервера okerr или установить неверный secret - чтобы обновление не произошло.

Наблюдение за данными

Несколько команд, которые описаны ниже, удобны для наблюдения за данными.

DUMP

Самая простая (и не самая удобная) команда наблюдения. Вставьте ее после нужной команды в последовательности, чтобы увидеть данные после ее обработки. Например: okerrclient -s PROCESSES LEN DUMP NONE

Команда выведет данные после команды LEN, а обновления индикатора не будет, так как следующая команда NONE удаляет данные.

Но если поставить команду DUMP после команды PROCESSES, будет выведено очень много информации и в неудобном формате. В этом случае лучше использовать JDUMP.

JDUMP

JDUMP аналогично DUMP, но выводит данные в удобном форматированном JSON формате.

Например, чтобы лучше понять на практике, что выдает команда PROCESSES: okerrclient -s PROCESSES JDUMP NONE | less

SEQDUMP

SEQDUMP пишет только первые 100 байт данных, но зато выводит много технической информации о контексте последовательности (имя, метод, итд). Сравните, для примера результаты команд: okerrclient -s PROCESSES SEQDUMP NONE и команду:

okerrclient --name ZZZZ -s 'METHOD numerical maxlim=100' 'TAG test' 'TAG processes' 'SET aaaa=bbbb' 'SET xxxx=yyyy' PROCESSES SEQDUMP LEN NONE

--steps

Опция --steps N клиента вызывает команду дампа через N шагов.

Например: okerrclient --steps 2 -s PROCESSES LEN NONE Обработка остановится после второго шага (команды LEN) и будет выполнен дамп.

По-умолчанию дамп делается через SEQDUMP, но можно указать другую команду okerrclient --dump JDUMP --steps 1 -s PROCESSES LEN NONE

-v

подробный (verbose) режим.

$ okerrclient -s 'NAME test' 'STR hello!' NONE
$ okerrclient -v -s 'NAME test' 'STR hello!' NONE
RUN NAME name=test
NAME: test
RUN STR str=hello!
RUN NONE
do no update indicator test, because data is None

В этом режиме выдается не так много интересной информации, но тем не менее, он может быть полезным, особенно, если есть подозрения, что информация не отправляется на сервер (или отвергается им).

Переменные и подстановки

Установка переменных

SET

Команда SET устанавливает строковое значение переменной

$ okerrclient --name 'test' -s 'SET aaa=bbb' SEQDUMP NONE
Sequence name 'test': #139708254547696 no parent
lastcmd: SEQDUMP
route:
    NONE 
details: None
method: None
tags: []
variables: {
    "aaa": "bbb"
}
no data
SAVE

SAVE сохраняет текущие данные в переменную:

$ okerrclient -s 'STR zzzzz' 'SAVE aaa' SEQDUMP NONE
Sequence name 'braconnier': #139742995741296 no parent
lastcmd: SEQDUMP
route:
    NONE 
details: None
method: None
tags: []
variables: {
    "aaa": "zzzzz"
}

Сохранять можно не только строки, но и любые другие данные, например, список словарей, которые выдает команда DIR

LOAD

LOAD выполняет функцию обратную SAVE - она загружает переменную в текущие данные:

$ okerrclient -s 'STR zzz' 'SAVE aaa' 'STR not zzz' 'LOAD aaa' SEQDUMP NONE
Sequence name 'braconnier': #140674583018096 no parent
lastcmd: SEQDUMP
route:
    NONE 
details: None 
method: None
tags: []
variables: {
    "aaa": "zzz"
}
data: (3): zzz
Подстановки

Перед выполнением команды (например, 'NAME $_name:aaa'), выполняются подстановки значений по их имени. Для выполнения подстановок создается словарь имен и значений. В словарь подстановок включаются:

  • Переменные последовательности (те, которые показывает команда SEQDUMP как variables)

  • Специальные значения:

  • Имя последовательности записывается с именем _name

  • Если данные - строка, то ее значение доступно с именем _str

  • Если данные - словарь, то каждое поле доступно по имени _dict_field, например _dict_basename

Примеры подстановок:

$ okerrclient -s 'SET aaa=bbb' 'STR $aaa' DUMP NONE
bbb
$ okerrclient -s 'NAME myname' 'STR $_name' DUMP NONE
myname
$ okerrclient --name myname -s 'STR $_name' DUMP NONE
myname
$ okerrclient -s 'STR aaa' 'STR $_str:bbb' DUMP NONE
aaa:bbb
$ okerrclient -s 'DIR path=/bin/bash sha1=1' LAST 'STR sha1 of bash is $_dict_sha1' DUMP NONE
sha1 of bash is 8e3aa19fdc42e87659746f6dc8ea3af74ab30362

Изучение языка

Для понимания языка можно использовать эту документацию, команду okerrclient -h, а для более подробной информации по конкретной команде: okerrclient -h <NAME>, например okerrclient -h DIR.

Чтобы увидеть на практике - попробуйте написать тестовый скрипт с интересующей вас командой и дампом информации после нее, чтобы увидеть, как она работает.

Можете так же посмотреть готовые стандартные скрипты в разделе ключей (переход по иконке дверного ключа над табличкой индикаторов), в подкаталоге 'lib'.

Работа с sequence-скриптами на сервере

Sequence скрипты на сервере хранятся в базе ключей проекта. (Подробнее смотрите раздел "База ключей" в справочнике)