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.