original in de Stefan Blechschmidt
de to en Jürgen Pohl
en to ru Peter Demidov
Будучи опытным электротехником, я нашел себя в 1990 на фронте рабочей станции CAD для разработки переключающей и управляющей станции. Очевидно, я заразился тогда неизвестным "вирусом", и это просто отлично.
В редакции от ноября 2003 года Temperature Monitoring With Linux я объяснил схему, которая позволяет собирать данные о температуре через Linux. Чтобы оценить данные о температуре, мы должны сохранить их в базе данных.
Чтобы получить полностью пользу от этой статьи мы будем графически отображать данные через web-интерфейс.

Некоторые работающие приложения уже должны быть установлены на вашем компьютере
Как мы отмечаем, эта статья для отчати продвинутого пользователя Linux. Для тех, кто пока не относится к таким, это будет хорошим вступлением ;-)
В MySQL программа mysql обеспечивает интерфейс базы
данных. С командой
mysql -u root -p mysql мы присоединяемся к монитору MySQL.
С ключём -u
будет введено имя пользователя. Ключ
-u запросит пароль, и, наконец, БД, в которую необходимо
войти. В нашем случае мы выбираем БД MySQL Manager.
Вы получите приглашение mysql
> для ввода команд SQL. Сначала нам необходимо узнать,
какого типа таблицы находятся в БД. Команда
show tables;
делает это.
mysql> show tables; +-----------------+ | Tables_in_mysql | +-----------------+ | columns_priv | | db | | func | | host | | tables_priv | | user | +-----------------+ 6 rows in set (0.00 sec)
Теперь нам надо создать БД для наших данных о температуре.
С помощью команды create database
digidb мы генерируем нашу БД с именем digidb и
командой exit мы можем
выйти из монитора или могут быть введены дополнительные команды
в другом случае.
MySQL имеет администратора, который в общем называется
root. Инсталяция по умолчанию не требует пароля. Командой
mysqladmin -u root -p password geheim мы меняем пароль
для пользователя root на geheim.
Чтобы активизировать эту модификацию, таблица администратора
должна быть прочитана снова, мы делаем это при помощи команды
mysqladmin -u root -p flush-privileges. Теперь для
пользователя root обеспечена проверка пароля при каждом
обращении к БД.
Ввод команд через монитор очень сложен, однако, MySQL предлагает другую возможность ввести команды.
Чтобы сделать это мы набираем текстовый файл с командами SQL, добавляя "<" к команде mysql.
Чтобы это продемострировать, мы пишем текстовый файл для создания первой таблицы для сенсора 0.
В этом файле sensor0.sql мы сейчас пишем команды создания таблицы, это может выглядеть так.
CREATE TABLE sensor0 ( id int(11) NOT NULL auto_increment, monat char(3) NOT NULL default '', tag char(2) NOT NULL default '', dbtime timestamp(14) NOT NULL, zeit time NOT NULL default '00:00:00', messung decimal(4,2) NOT NULL default '0.00', PRIMARY KEY (id) ) TYPE=MyISAM;
Это будет введено при помощи:
mysql -u digitemp -p digitemp
< sensor0.sql
Поскольку мы используем 2 сенсора, нам необходимо только скопировать
файл и изменить строрку CREATE TABLE
sensor0 на CREATE TABLE
sensor1.
Очевидно, что ввод SQL команд посредством файла имеет реальные преимущества.
Чтобы показать вновь созданные таблицы мы используем команду:
echo 'show tables' | mysql -u
root -p digidb, конечно это также работает и наоборот.
Если мы сделали все правильно мы получим вывод:
Enter password: Tables_in_digidb sensor0 sensor1
Маленькая Perl-программа будет передавать данные в базу данных. Для этого будет использован наш первый модуль Perl (DBI), он предоставит нам методы доступа к БД.
#!/usr/bin/perl -w
#
# Digitemp preparing of log file and saving in database
# sbs 2003-08-09
#
use DBI;
use strict;
# Initialize database
my $datasource = "dbi:mysql:database=digidb";
my $user = "root";
my $pass = "geheim";
my $db = DBI->connect($datasource, $user, $pass)
or "Verbindung zur Datenbank nicht möglich: " . $DBI::errstr;
# Filtering of Digitemp
while(<STDIN>) {
chomp;
# Skip output program name
next if (m/Digi.*/);
# Skip output blank line
next if (m/^$/);
# Skip all to Fahrenheit
m/(.*).F.*/;
my $templine = $1;
# Divide temp line and save in variables
my ($monat, $tag, $zeit, $sensor_txt, $sensor_nr, $grad_txt, $grad_wert)
= split(/ /,$tempzeile);
# Fill database
$db->do( "insert into sensor$sensor_nr (monat, tag, zeit, messung)
values ('$monat', '$tag', '$zeit','$grad_wert')")
or die "do nicht möglich: " . $db->errstr();
}# END- Digitemp filter
# close database
$db->disconnect;
Программа не делает очень многого, она открывает базу данных, читает вывод, полученный от digitemp, отфильтровывает все, что нам не надо и пишет важные данные в правильную таблицу БД.
Непрерывный сбор данных производится с помощью хорошо испытаной работы cron:
0-59/15 * * * * root /root/bin/digitemp -a | /root/bin/digipipe.pl
Это все насчет сбора данных, теперь к web-интерфейсу.
Perl предлагает нам соответствующее окружение для этой задачи.
Во-первых нам надо знать директорию, где Apache обрабатывает
свои CGI программы. Их можно найти в конфигурационных файлах
Apache. Ищите строку вроде этой
<Directory
/usr/lib/cgi-bin>.
Перед тем, как мы начнем с графическим выводом, мы сперва создадим программу, которая обеспечит нас последними измерительными данными.
Было бы выгодно сохранить их в разные директории;
вам также придется сделать ваши программы исполнимыми: chmod 755
programmname.
Нам необходимо ограничить вывод последних данных и ввод их в Perl-CGI программу. Это будет выполнено при помощи SQL-запроса.
#!/usr/bin/perl
use DBI;
use strict;
# Initialize database
my $datasource = "dbi:mysql:database=digidb";
my $user = "root";
my $pass = "geheim";
my $db = DBI->connect($datasource, $user, $pass)
or "Verbindung zur Datenbank nicht möglich: " . $DBI::errstr;
# database work parameter
my $sql;
my $sth;
# Sensor work parameter
my $temp;
my $zeit;
#Prepare HTML output
print "Content-type: text/html\n\n";
# Output of individual sensors measurements
$sql = "select messung, zeit from sensor$i order by id desc limit 1;";
$sth = $db->prepare($sql)
or die "prepare nicht möglich";
$sth->execute()
or die "execute nicht möglich";
($temp, $zeit) = $sth->fetchrow_array();
$sth->finish();
print "<p>Temperatur Sensor$i: <b>[$temp]</b> $zeit</p>";
}
# Close database
$db->disconnect;
Этот пример не самый изящный, он должен только демонстрировать как просто может быть выполнена эта работа с Perl.
Теперь давайте возьмемся за графический вывод. Программа (ссылка в конце статьи) генерирует графики кривых, для других графиков ищите другие GD модули.
Более того, программа использует CGI модуль, который позволяет осуществляет HTML-вывод в Perl. Я ссылаюсь здесь на многочисленные описания этого в Internet.
Вернемся к программе. Она включает главную часть и две подпрограммы. Одна подпрограмма ответственна за SQL запрос, вторая - за графики.
Главной частью выполняются только три запроса и данные передаются подпрограммам.
Требуется изменить только запросы, чтобы генерировать другой графический вывод.
Наконец, я хочу показать вам несколько SQL запросов, посколльку они являются главным предметом этого примера.
select tag, monat, zeit,
DATE_FORMAT(dbtime,'%Y-%c-%d %H:%i:%s') as dbtime, messung
from sensor0
order by id desc
limit 5;
select tag, monat, zeit,
DATE_FORMAT(dbtime,'%Y-%c-%d %H:%i:%s') as dbtime, messung
from sensor1
where YEAR(dbtime) = YEAR(NOW())
order by messung asc
limit 1
select tag, monat, zeit,
DATE_FORMAT(dbtime,'%Y-%c-%d %H:%i:%s') as dbtime, messung
from sensor1
where YEAR(dbtime) = YEAR(NOW())
order by messung desc
limit 1
select day, month, YEAR(dbtime) as Jahr,
sum(messung)/count(*) as Durchschnitt
from sensor1
where YEAR(dbtime) = YEAR(NOW())
and DAYOFMONTH(dbtime)= DAYOFMONTH(NOW())
and MONTHNAME(dbtime) = MONTHNAME(NOW())
group by DAYOFMONTH(dbtime)
Меня всегда удивляет, как это просто - писать программы на Perl. Вообще-то, они не написаны, а скопированы, а их секции скомбинированы; так или иначе все они уже где-нибудь существуют в одной или другой форме.
Я надеюсь, у меня получилось обеспечить вам маленький проблеск в теме Perl, CGI и MySQL.