30. Скрипты¶
ПАК “Фортикс” позволяет автоматизировать действия администратора с помощью сценариев (скриптов) на языке программирования Lua.
Для интеграции скриптов в систему команд необходимо:
(опционально) создать директории для хранения файлов-скриптов в диретории
/system/scripts/;загрузить файлы-скрипты в подкаталоги;
запустить скрипт в командной строке с помощью команды
@режима администрирования.
Иерархия директорий в /system/scripts доступна как параметр команды @.
Для выполнения скрипта, находящегося в созданной директории, применяется команда:
> @ <directory> <script>
где
<directory>– имя директории относительно директории/system/scripts/;<script>– имя скрипта.
Например, для выполнение скрипта enable_all.lua из каталога /system/scripts/iface применяется команда:
> @ iface enable_all.lua
Для команд-скриптов применимо автодополнение по клавише <Tab>.
Для создания скриптов непосредственно в командной строке необходимо:
Запустить текстовый редактор для файла-скрипта:
> edit <file-path>
где <file-path> – полное имя файла-скрипта или имя файла относительно домашней директории пользователя.
В текстовом редакторе непосредственно записать текст скрипта.
Использовать комбинацию клавиш
<C>+<O>для сохранения файла и<C>+<X>для выхода из текстового редактора.
Пример создания скрипта непосредственно на ПАК “Фортикс”:
Запуск текстового редактора для файла-скрипта:
> edit /system/scripts/hello.lua
Запись скрипта в текстовом редакторе:
print "Hello, Fortics!"
Сохранение файла-скрипта: <C> + <O>.
Выход из текстового редактора: <C> + <X>.
Запуск созданного скрипта:
> @ hello.lua
Hello, Fortics!
30.1. Дескрипторы¶
Для использования параметров, указываемых после имени скрипта при его запуске, применяются описатели параметров (дескрипторы) или массив ARGS, в который помещаются параметры.
Пример текста скрипта без дескрипторов:
print("Hello, ",ARGS[1])
Запуск скрипта из примера:
@ hello.lua world
Hello, world
Дескрипторы представляют собой строки заголовка скрипта, начинающиеся с --@. Данные строки воспринимаются окружением Lua как комментарии. Для описания параметров предусмотрены следующие дескрипторы:
@help <Help>– текстовое описание скрипта, которое выводится по горячей клавише<?>перед набором имени скрипта;@arg <id>:<value> <Help>– обязательный параметр, где<id>– идентификатор параметра,<value>– тип параметра в формате строки,<Help>– текстовое описание параметра;@arg* <id>:<value>– массив обязательных параметров (1 или более), где<id>– идентификатор параметра,<value>– тип параметра в формате строки;@opt <id>:<value>– необязательный параметр, где<id>– идентификатор параметра,<value>– тип параметра в формате строки или списка (см. ниже);@opt* <id>:<value>– массив необязательных параметров, где<id>– идентификатор параметра,<value>– тип параметра в формате строки.
В окружении Lua любые задаваемые параметры являются строками независимо от значения в <value>, которое задаётся только для отображения в справке.
В качестве <value> допустимо указание списка из возможных вариантов строк, например:
--@arg op:set|del Operation
В данном примере параметр op принимает только значения set или del.
Для описания специфики выполнения скрипта предусмотрены следующие дескрипторы:
@timeout – максимальный интервал выполнения скрипта, запущенного не интерактивно (в фоновом режиме), по истечении которого выполнение скрипта останавливается, где
<sec>– число секунд, по умолчанию – 30;@noerror – отключение режима остановки выполнения скрипта по ошибке (по умолчанию скрипт останавливается при любой ошибке).
Пример текста скрипта с дескрипторами:
--@help Example
--@arg msg:string Message string
print("Hello,",ARGS.msg)
При запуске указанного скрипта отображаются подсказки по горячей клавише <?> и осуществляется проверка на корректность всех значений параметров.
30.2. Функции¶
Скрипты выполняются в ограниченном окружении Lua, в котором доступны следующие стандартные функции:
dofile;
ipairs;
pairs.
print;
tonumber;
tostring;
type.
В ПАК “Фортикс” предусмотрены специфичные для данной среды исполнения функции.
30.2.1. Функции set_config() и del_config()¶
Функции set_config() и del_config() позволяют устанавливать и удалять узлы в конфигурации candidate. Предусмотрено два способа работы с функциями:
непосредственное указание пути к узлу конфигурации в формате командной строки для операций;
использование специального объекта (применим при генерации пути к узлу конфигурации в формате командной строки для операций).
Пример применения функции set_config() с непосредственным указанием пути к узлу конфигурации в формате командной стркои для операций:
set_config [[interface ether en0 description "en0"
interface ether en0 description "en1"
interface ether en0 description "en2"
interface ether en0 description "en3"]]
Пример использования специального объекта:
cfg = set_config()
for i = 0, 3 do
cfg:printf('interface ether en%d description "en%d"\n', i, i)
end
cfg:apply()
Предупреждение
Функции set_config() и del_config() оптимизированы для выполнения групп операций. Данные функции работают значительно быстрее, чем последовательные вызовы для выполнения каждой операции по отдельности. Например, выполнение следующих последовательных операций:
set_config 'interface ether en0 description "en0"'
set_config 'interface ether en0 description "en1"'
set_config 'interface ether en0 description "en2"'
set_config 'interface ether en0 description "en3"'
значительно медленнее, чем выполнение следующей группы операций:
set_config [[interface ether en0 description "en0"
interface ether en0 description "en1"
interface ether en0 description "en2"
interface ether en0 description "en3"]]
Предупреждение
Данные функции изменяют конфигурацию candidate. Для применения указанных изменений к конфигурации running необходимо выполнить команду commit.
30.2.2. Функция load_config()¶
Функция load_config() позволяет дополнять конфигурацию candidate фрагментами конфигурации. Данная функция изменяет конфигурацию candidate.
Пример применения функции load_config():
load_config [[interface {
ether en0 {
description "en0"
enable
}
}]]
В указанном примере добавляются/изменяются параметры enable и description, при этом другие параметры конфигурации остаются неизменными.
Для замены конфигурации интерфейса целиком перед применением рассматриваемой функции выполняется функция del_config():
del_config "interface ether en0"
load_config [[interface {
ether en0 {
description "en0"
enable
}
}]]
30.2.3. Функция commit()¶
Функция commit() осуществляет фиксацию конфигурации с помощью команды commit.
Применение функции commit():
commit()
Пример применения функции commit():
set_config 'interface ether en0 description "en0"'
commit()
Применение функции commit() для указанного узла конфигурации:
commit 'path'
где path – путь к узлу конфигурации в формате командной строки.
Пример применения функции commit() для указанного узла конфигурации:
set_config 'interface ether en0 description "en0"'
commit 'interface ether en0'
30.2.4. Функция revert()¶
Функция revert() отменяет изменения в конфигурации candidate.
Применение функции:
revert()
Для применения revert() для указанного узла конфигурации используется конструкция:
revert 'path'
где path – путь к узлу конфигурации в формате командной строки.
30.2.5. Функция exit()¶
Функция exit() соответствует стандартной функции Lua os.exit().
Применение функции:
exit(true)
30.2.6. Функция command()¶
Функция command() позволяет выполнять последовательность команд режима администрирования.
Применение функции command():
command('<command-adm>')
где <command-adm> – команда режима администрирования.
Пример применения функции command():
command('show version')
По умолчанию вывод команды на экран подавляется и возвращается в виде двух таблиц stdout и stderr, например:
out = command 'show version'
print(out[2]) -- Показать версию (вторая строка вывода)
Для стандартного выполнения команды и получения её вывода в качестве второго параметра задается true.
Применение функции с указанием второго параметра true:
command('<command>', true)
где <command> – команда режима администрирования.
Пример применения функции с указанием второго параметра true:
command('show version', true)
Данная функция не возвращает таблицы с stdout и stderr.
Пример выполнения последовательности команд:
command([[show version
show system software]], true)
30.2.7. Функция file()¶
Функция file() позволяет получать содержимое файлов или создавать текстовые файлы.
Пример применения функции file():
file("hello.txt", "Hello, World!")
command("cat hello.txt", true)
txt = file 'hello.txt'
txt = txt:gsub('World', 'Fortics')
file("hello2.txt", txt)
command("cat hello2.txt", true)
30.2.8. Функция sleep()¶
Функция sleep() позволяет скрипту переходить в режим сна на указанное время.
Пример применения функции sleep():
sleep(1)
30.2.9. Функция getenv()¶
Функция getenv() соответствует стандартной функции Lua os.getenv и позволяет получать переменные окружения. Некоторые службы ПАК “Фортикс”, которые могут быть интегрированы со скриптами, передают информацию о событиях с помощью переменных окружения.
30.2.10. Функция stop_on_error()¶
По умолчанию любая ошибка останавливает выполнение скрипта. Для изменения режима обработки ошибок предусмотрено:
применение дескриптора
@noerror– выключает режим остановки выполнения скрипта по ошибке полностью;применение функции
stop_on_error(true|false)– включает (true) или выключает (false) режим остановки по ошибке.
Функция stop_on_error() возвращает предыдущее значение режима.
Применение функции stop_on_error():
stop_on_error(true|false)
Пример применения функции stop_on_error():
old_mode = stop_on_error(false)
print(io.file("hello.txt"))
stop_on_error(true)
Функции noerror() и check_error() меняют поведение обработки ошибок для указанных вызовов функций.
30.2.11. Функция noerror()¶
Функция noerror() позволяет отключать режим остановки выполнения скрипта по ошибке для указанной функции.
Пример применения функции noerror():
-- проверить, существует ли файл
if noerror(file)("test") then
print "test is exist"
else
print "test is not exist"
end
30.2.12. Функция check_error()¶
Функция check_error() позволяет включать режим остановки выполнения скрипта по ошибке для указанной функции.
Пример применения функции check_error():
--@noerror
del_config "interface ether en1 enable"
check_error(commit)()
print "Commit done!"
30.2.13. Функции time() и date()¶
Функции time() и date() соответствуют стандартным функциям Lua os.time() и os.date().
30.2.14. Функция send_smtp¶
Функция send_smtp позволяет отправлять e-mail сообщения на некоторый сервер.
Применение функции send_smtp:
send_smtp(<opt>, <message>)
где
<opt>– lua-таблица, ключами которой являются опции, а значениями – значения опций;<message>– строка сообщения, которая может содержать получателей и отправителя (см. пример ниже).
Доступны следующие опции для таблицы <opt>:
recipients– получатели, значение опции – адреса, указанные через “;”, в кавычках;password– пароль для аутентификации на почтом сервере отправителя, значение опции – строка в кавычках;user– имя пользователя для аутентификации на почтовом сервере, значение опции – строка в кавычках;host– адрес почтового сервера, значение опции – строка в кавычках;from– отправитель письма, значение опции – строка в кавычках;tls– включение/отключение TLS для связи с почтовым сервером (все необходимые для проверки сертификаты сервера должны находиться в каталоге/system/ssl/certs, если проверка сертификата не отключена), значение опции – “on”/“off”;auth– включение/отключение аутентификации при связи с сервером, значение опции – “on”/“off”, при значении “on” данной опции значения опцийuserиpasswordдолжны быть определены;tls-certcheck– включение/отключение проверки сертификата почтового сервера при включенном tls, значение опции – “on”/“off”.
Если опции recipients и/или from не указаны, их значения извлекаются из строки сообщения.
Пример определения значений опций recipients и from в строке сообщения:
local message = "From: best_programmer@zts.ru\n To: test@zts.ru\n Hello!\n"
Пример применения функции send_smtp:
local opts = {
password = "Aqwl;vxcjk123",
user = "test@inbox.ru",
tls = "off",
host = "smtp.mail.ru",
auth = "on",
}
local message = "From:test@inbox.ru\n Hello world!\n"
local ret, err = send_smtp(opts, message)
Допустимо указание значения nil строки сообщения. В этом случае отправляется пустое сообщение, при этом определение значений опций from и recipients обязательно.
30.2.15. Функция send_snmp¶
Функция send_snmp позволяет отправлять SNMP-сообщения trap/inform на удалённый сервер с помощью протокола SNMP второй и третьей версии.
Применение функции send_snmp:
send_snmp(<opt>, <message>)
где
<opt>– lua-таблица, ключами которой являются опции, а значениями – значения опций;<message>– набор таблиц.
Доступны следующие опции для таблицы <opt>:
snmtype– тип посылаемого сообщения, значение опции – “trap” или “inform”, по умолчанию – “trap”;version– версия сообщения, значение опции – “2” или “3”, по умолчанию – “2”;addr– адрес приёмника, значение опции – адрес хоста, для указания порта добавляется:<port>, где<port>– число от 1 до 65535;uptime– (опционально) время работы системы (по умолчанию указывается время работы после загрузки системы), значение опции – число секунд в кавычках;user– (только для v3) имя пользователя для аутентификации на сервере, значение опции – строка в кавычках;sec_engine_id– (только для v3) engineID, используемое при включённой аутентификации на принимающей стороне, значение опции – hex-значение в кавычках;auth_alg– (только для v3) алгоритм аутентификации, значение опции – “MD5”/“SHA”;auth_key– (только для v3) ключ аутентификации, значение опции – строка в кавычках;privacy_alg– (только для v3) алгоритм шифрования, значение опции – “DES”/“AES”;privacy_key– (только для v3) закрытый ключ, используемый для шифрования, значение опции – строка в кавычках;context_engine_id– (только для v3) engineID для контекста, значение опции – hex-значение в кавычках;community– (только для v2) идентификатор отправителя, значение опции – строка в кавычках.
Сообщение – это набор таблиц, где в начале указывается oid события и далее дополнительный oid. Каждая таблица в начале содержит базовый oid/mib, далее опциональное значение, которое является строкой или числом. Данное значение отправляется с типом ASN1_INTEGER или ASN1_STRING в зависимости от переданного значения.
Пример сообщения:
{"1.2.3.4", "2"}
{"1.2.3.4", 2}
В первом случае сообщение отправится как ASN1_STRING, во втором – как ASN1_INTEGER.
Примеры:
local conf1 = {
snmptype = "trap",
version = "3",
addr = "192.168.56.1:12345",
sec_engine_id = "0x8000123acd1ab43abbfff000fa",
user = "test",
auth_alg = "MD5",
auth_key = "testsnmp",
privacy_alg = "DES",
privacy_key = "testSNMP",
}
send_snmp(conf1, {"SNMPv2-MIB::coldStart"}, {"iso.3.6.1.6.3.1.1.6.2", 2},
{"SNMPv2-MIB::sysName.0", "My Device"}) --Send snmpv3 trap with auth and privacy. uptime from system
local conf2 = {
version = "3",
addr = "192.168.56.1:12345",
user = "test2",
}
send_snmp(conf2, {"SNMPv2-MIB::coldStart"}, {"iso.3.6.1.6.3.1.1.6.2", 2},
{"SNMPv2-MIB::sysName.0", "My Device"}) -- --Send snmpv3 trap without auth and privacy, uptime from system
local conf3 = {
addr = "192.168.56.1:12345",
community = "public",
}
send_snmp(conf2, {"SNMPv2-MIB::coldStart"}, {"iso.3.6.1.6.3.1.1.6.2", 2},
{"SNMPv2-MIB::sysName.0", "My Device"}) -- --Send snmpv2 trap
30.2.16. Функция journal¶
Функция journal позволяет отправлять сообщения в системный журнал.
Предусмотрены следующие уровни отправляемых в журнал сообщений:
alert– оповещение, требующее немедленной реакции администратора;err– ошибка;warning– предупреждение;info– информационное сообщение.
Пример применения функции journal:
journal("alert", "No free space available!")
Пример использования форматной строки в функции journal:
journal("info", "%d days left", days)
30.2.17. Функции get, get_data, get_xpath¶
Функции get, get_data и get_xpath позволяют выполнять выборку из конфигурации running, возвращая lua-таблицу с данными. Функции get и get_data получают в качестве параметра путь к узлу конфигурации в формате командной строки. Функция get_xpath получает в качестве параметра путь в виде yang xpath-запроса.
Функция get возвращает узел. Функции get_data и get_xpath возвращают поддерево от корня конфигурации до узла. Функция get не может быть использована в тех случаях, когда под выборку попадает несколько элементов.
Для анализа структур применяется функция table.dump().
Пример применения функций get, get_data, get_xpath, table.dump():
local addr = get_data "interface ether en0 ipv4 address"
if not addr then
exit()
end
printf("data: %s\n\n", table.dump(addr, true))
for _, v in ipairs(addr[1][1][2]) do
print(v[1].val)
end
print(addr:dump())
local enable = get "interface ether en0 enable"
printf("data: %s\n\n", table.dump(enable, true))
printf("enabled: %s\n", enable and enable[1] and true)
30.3. Библиотеки¶
В ПАК “Фортикс” поддерживаются следующие стандартные библиотеки Lua:
table;string;math.
В ПАК “Фортикс” поддерживаются следующие нестандартные библиотеки:
ipnet;rex.
30.4. Расширение стандартных библиотек¶
В ПАК “Фортикс” для удобства решения типовых задач стандартные библиотеки Lua расширены дополнительными функциями.
30.4.1. Расширение библиотеки string¶
string.empty(<string>)– проверить, что строка состоит из пробелов и табуляций, где<string>– строка;string.strip(<string>,[набор символов])– убрать разделители в конце строки, где<string>– строка;string.split(<string>, [макс. разбиений], [separator])– разбить строку на массив строк, где<string>– строка,[separator]– разделитель;string.startswith(<string>, <prefix>)– проверить, что строка начинается с указанного префикса, где<string>– строка,<prefix>– префикс строки;string.endswith(<string>, <postfix>)– проверить, что строка заканчивается на указанный постфикс, где<string>– строка,<postfix>– постфикс строки;string.lines(<text>)– построчный итератор.
30.4.2. Расширение библиотеки table¶
table.append(<dst>, <src>)– добавить элементы таблицы<src>в таблицу<dst>, где<dst>– lua-таблица,<src>– lua-таблица;table.clone(<src>)– клонировать таблицу, где<src>– lua-таблица;table.merge(<dst>, <src>)– внести в таблицу элементы таблицы без изменений, где<dst>– lua-таблица,<src>– lua-таблица;table.empty(<src>)– проверить, что таблица пуста, где<src>– lua-таблица;table.unpack(<src>)– распаковать таблицу в список значений, где<src>– lua-таблица;table.iter(<src>)– аналогична стандартной функцииipairs, при этом индекс не возвращается, где<src>– lua-таблица.
30.5. Пример скрипта¶
Пример скрипта, выполняющего команды для группы параметров:
--@help For iterator
--@arg start:int Start value
--@arg stop:int End value
--@arg op:set|del Command
--@arg* arg:path Path
local start = tonumber(ARGS.start)
local stop = tonumber(ARGS.stop)
local cmd = ''
for _, v in ipairs(ARGS.arg) do
cmd = cmd .. string.quote(v) .. ' '
end
local cfg = ARGS.op == 'del' and del_config() or set_config()
for i=start, stop do
cfg:printf(cmd..'\n', i)
end
cfg:apply()
Применение скрипта из примера:
@ for 0 10 set interface ether en%d enable