Простой вебсервис, на Perl, но не CGI
Просто хочу показать, как с помощью Perl можно сделать простой веб-сервис, на примере мониторинга свободного места на диске и свободной памяти.
Почему именно на Perl — потому что на примере минимального дистрибутива Debian, где Perl уже установлен по умолчанию, и для создания вебсервиса потребуются минимальные усилия.
Ну и заодно — как делаются библиотеки функций и автотесты.
Итак, сам Perl установлен в дистрибутиве.
Устанавливаем дополнительно фреймворк Mojolicious:
apt install libmojolicious-perl
Он займет дополнительно около 70 мегабайт места, но значительно сэкономит время «разработки» данного вебсервиса.
Как уже говорил, в данном примере просто контролируем свободное место на диске и доступную память. Разумеется, задача может быть любой другой, это просто пример.
Чтобы не изобретать велосипед — данные будем получать через системные утилиты, просто добавим обертку над ними, в виде двух функций.
Но это пока еще не веб-приложение, это просто пара функций. Чтобы не забивать себе голову, куда и как их добавить — вынесем их в отдельный модуль, который назовем MyStat.pm
#!/usr/bin/perl
# название модуля должно соответствовать имени файла MyStat.pm
package MyStat;
# Получение информации о свободном месте на диске
sub get_disk_space {
my $df_output = `df -h /`; # Получаем информацию о корневом разделе
my @lines = split("\n", $df_output);
my @fields = split(/\s+/, $lines[1]);
return $fields[3]; # Возвращаем доступное пространство
}
# Получение информации о доступной памяти
sub get_memory {
my $free_output = `free -h`; # Получаем информацию о памяти
my @lines = split("\n", $free_output);
my @fields = split(/\s+/, $lines[1]);
return $fields[6]; # Возвращаем доступную память
}
# модуль всегда завершается возвратом 1
1;
Теперь в любой программе достаточно будет подключить этот модуль и вызвать функции, примерно так:
#!/usr/bin/perl
# эта строчка нужна чтобы указать, где лежит модуль,
# если он не находится в системных каталогах типа /usr/share/perl...
# в данном случае он лежит в каталоге lib в домашнем каталоге пользователя
use lib $ENV{HOME}.'/lib';
# подключаем его
use MyStat;
# получаем данные
my $df = MyStat::get_disk_space;
my $mem = MyStat::get_memory;
....
Теперь напишем для модуля автотест. Это необязательно, но когда со временем модули разрастаются, усложняются и изменяются — успешное прохождение автотеста поможет выявить баг до того, как обновление поломает работующую систему.
И лучше это делать сразу — потом будет просто некогда.
Традиционно, его можно назвать MyStat.t, но вообще-то это непринципиально, просто так удобнее понять потом что это было.
#!/usr/bin/perl
use lib $ENV{HOME}.'/lib';
use MyStat;
use Test::More;
my $df = MyStat::get_disk_space;
ok(defined $df, "disk space is $df");
my $mem = MyStat::get_memory;
ok(defined $mem, "free memory is $mem");
done_testing();
По сути — это обычный скрипт, который просто вызывает функции, а команда ok проверяет, то ли мы получили что хотели или нет.
Если выполнить команду perl MyStat.t — получим примерно следующее:
ok 1 — disk space is 70G
ok 2 — free memory is 3.3Gi
1…2
Первый тест ОК, результат »70G», второй тест ОК, результат 3.3Gi.
Оба теста успешно отработали, вернули значения.
Модуль исправен.
Теперь делаем собственно вебсервис: он будет по запросу выдавать JSON с данными о наличии свободного места.
Для этого выполняем команду:
mojo generate lite-app MyApp
У нас получилась заготовка мини-приложения MyApp.pl
#!/usr/bin/env perl
use Mojolicious::Lite -signatures;
get '/' => sub ($c) {
$c->render(template => 'index');
};
app->start;
__DATA__
@@ index.html.ep
% layout 'default';
% title 'Welcome';
Welcome to the Mojolicious real-time web framework!
@@ layouts/default.html.ep
<%= title %>
<%= content %>
В данный момент приложение содержит один единственный метод GET »/», который отрисовывает шаблон index, причем сам шаблон определен в этом же файле, в секции __DATA__ , и состоит из двух частей: шаблона самой страницы, @@ index.html.ep, и шаблона макета default.html.ep.
Такая двойная конструкция позволяет засунуть в макет общие для всего приложения стили, скрипты и прочее, а рендеринг отдельных страниц делать отдельными шаблонами, используя этот макет, или другой, или без макета выводить просто кусок текста, или вообще обходиться без шаблонов.
Но сейчас и всего этого не нужно, рисовать отдельные страницы мы не будем, просто выведем JSON.
#!/usr/bin/env perl
use Mojolicious::Lite -signatures;
use Mojolicious::Static;
# ==============================================
use lib $ENV{HOME}.'/lib';
use MyStat;
get '/getstat' => sub ($c) {
my $mem = MyStat::get_memory;
$mem =~ s/([\d\.]+).*/$1/;
my $drive = MyStat::get_disk_space;
$drive =~ s/([\d\.]+).*/$1/;
my $t = {
mem => $mem,
drive => $drive,
};
$c->res->headers->header('Access-Control-Allow-Origin' => '*');
$c->render(json => $t);
};
# ==============================================
get '/' => sub ($c) {
$c->render(template => 'index');
};
app->start;
__DATA__
........
Добавлен метод GET »/getstat» который выводит строку наподобие {«mem»:2.6, «drive»:102.4}
Для этого он вызывает ранее созданные функции из модуля, получает данные, отрезает от них буквы и формирует JSON.
Его можно вызвать из внешней системы, чтобы получить данные о ресурсах на этом сервере.
Примерно по такой же схеме можно добавить самые разные вебсервисы, включая запросы к какой-нибудь базе данных или что-то еще подобное. Вопрос только в добавлении методов и функций.
А теперь добавим на «главную страницу» простейшие графики, чтобы можно было сразу в графическом виде смотреть, что оно там нам выдает.
Для этого создаем обыкновенную html-страницу с javascript, вызывающим созданный ранее метод и подставляющим данные в график. А потом внедряем ее в скрипт:
__DATA__
@@ layouts/default.html.ep
Memory and Disk Usage
<%= content %>
@@ index.html.ep
% layout 'default';
% title 'Welcome';
System Monitoring
Графики загруженности памяти и занятости диска
По сути, в данном случае при запросе к »/» сервер просто выдаст страничку, которая начнет запрашивать »/getstat» и заполнять графики.
А теперь всё это запустим, например так:
morbo -l http://*:8080 MyApp.pl
При подключении браузером к порту 8080 получим примерно такую страницу:
В принципе ничего не мешает сделать страницу красивой, настроить Nginx frontend — и получится небольшое веб-приложение, возможно с десятком страниц и методов. Для большего лучше создавать приложение чуть по другому, но это другая история.
Ну, а для нужд внутреннего мониторинга можно оставить и так.
Писать этот текст было дольше…
Habrahabr.ru прочитано 808 раз