Привет всем! Столкнулся с такой проблемой:
Имеется syslog-ng, который ловит логи от виндовой машины на udp порт. Затем я пытаюсь перенаправить их пайпом в perl скрипт, через обьект FIFO, предварительно созданный с помощью mkfifo(). Права на FIFO - rw у рута. syslog-ng и скрипт запускаются под rootом.destination { pipe(/scripts/syslog-ng.pipe); };
На стороне скрипта, открываю FIFO на чтение функцией open.
open($hLog, '<', '/scripts/syslog-ng.pipe');
Затем пытаюсь парсить полученые строки и запихивать в базу. Примерно так...
while(<$hLog>)
{
#обработка текущей строки $_
#Запись в базу...
}
Скрипт ругается на не верный SQL запрос!
После того как я перед обработкой строки, вывожу ее в STDOUT, все начинает работать без проблем. Строки базы успешно добавляются.
while(<$hLog>)
{
print $_; #!!!!
#обработка текущей строки $_
#Запись в базу...
}
Не могу понять в чем проблема, может в блокировке FIFO? Обьясните пожалуйста!
ЗЫ:Заранее благодарен.
Краткое содержание вашего поста: "у меня есть некая херня, она не работает, херню я вам не покажу, но ошибку пожалуйста найдите".
Вы ошиблись, уважаемый, форум телепатов не здесь.
конфиг syslog-ng:options {
sync (0);
time_reopen (10);
log_fifo_size (1000);
long_hostnames (off);
use_dns (no);
use_fqdn (no);
create_dirs (no);
keep_hostname (yes);
};source ext_logger {
unix-stream ("/dev/log");
udp( ip(xxx.xxx.xxx.xxx) port(xxxx));
internal();
};destination my_wks { fifo("/logs/scripts/syslog-ng.pipe"); };
log { source(ext_logger); destination(my_wks); flags(final); };;---------------------------------------------------------------------
скрипт:#!/usr/bin/perl
my $Pipe='/logs/scripts/syslog-ng.pipe';
use DBI;
my $hLog; #Log file handle
my $dbTable='xxxx'; #Name of dBase Table
my $date=''; #Event date
my $time=''; #Event time
my $user=''; #User
my $code=''; #Event code
my $addr=''; #host ip
%month = ('Jan'=>'01', 'Feb'=>'02', 'Mar'=>'03', 'Apr'=>'04', 'May'=>'05', 'Jun'=>'06', 'Jul'=>'07', 'Aug'=>'08', 'Sep'=>'09', 'Oct'=>'10'
, 'Nov'=>'11', 'Dec'=>'12'); #Month hash#----------------------------------------------------------------
my $dBase=DBI->connect("dbi:mysql:dbname=xxxxx;host=xxxxx","xxxxxx","xxxxx");open($hLog, '<', $Pipe) or die("Open Error");
while(<$hLog>)
{
if($_=~/(\S{3})\s?(\d{2})\s?(\d{2}\:?\d{2}\:?\d{2})\s?(\d{4})\s+(\d{3})\s+\S+\s+(\S+)/)
{
# $1=month $2=day $3=time $4=year $5=code $6=user_name
$date=$4.'-'.$month{$1}.'-'.$2;
$time=$3;
$user=$6;
$code=$5;
}
if(substr($user,-1,1) eq '$')
{
$addr=$user;
chop($addr);
}
elsif($_=~/(\d+\.{1}){3}\d+/) # $& - ip addr
{
$addr=$&;
}$dBase->do("insert into ".$dbTable." (date,time,user,ip,code) values ('".$date."','".$time."','".$user."','".$addr."',".$code.");");
$date, $time, $user, $code, $addr='';
}
Попросите кого-нибудь переписать этот скрипт. Вы делаете одну из самых грубых ошибок в программировании - инициализация переменных внутри блока условия и использование их за пределами этого блока. Как следствие всегда есть шанс, что часть переменных придет пустыми(это в перле, в С, например, они будут иметь произвольные значения) и значит запрос будет некорректным. Вторая ошибка чуть более высокого уровня - всегда надежней использовать параметризованные запросы через prepare+execute, чем самому загонять переменные в строку, это избавит от целого ряда проблем. Также есть неточности в регексах и корявый синтаксис, но это мелочи.
По поводу изменения поведения при print, могу лишь предположить что почему-то нарушается считывание по границе \n и print это как то исправляет, может из-за задержки с выводом, надо нормально поотлаживать, чтобы сказать наверняка. Однако в любом случае проблема в неправильном коде, он исключительно неустойчив.
>[оверквотинг удален]
>переменных придет пустыми(это в перле, в С, например, они будут иметь
>произвольные значения) и значит запрос будет некорректным. Вторая ошибка чуть более
>высокого уровня - всегда надежней использовать параметризованные запросы через prepare+execute, чем
>самому загонять переменные в строку, это избавит от целого ряда проблем.
>Также есть неточности в регексах и корявый синтаксис, но это мелочи.
>
>По поводу изменения поведения при print, могу лишь предположить что почему-то нарушается
>считывание по границе \n и print это как то исправляет, может
>из-за задержки с выводом, надо нормально поотлаживать, чтобы сказать наверняка. Однако
>в любом случае проблема в неправильном коде, он исключительно неустойчив.Прошу прощения, а где Вы нашли обьявление переменных внутри блока условия и использование их за пределами блока? Все переменные обьявляются и инициализируются вверху по тексту программы. Дело в том что когда я скармливаю скрипту файл, все прекрасно работает. Не каких пустых значений там нет.
Если вы не можете разобрать свой же код, то и не знаю чем помочь. Могу только предложить попробовать:
1. Попробуйте в консольном клиенте мускула запрос insert into some_table (date,code) values ('',)
2. perl -e '$a=1,$b=2; print "$a $b\n"; $a,$b="";print "$a $b\n";'>Дело в том что когда я скармливаю скрипту файл, все прекрасно работает
Ваш код по своей сути неустойчив, он не способен адекватно реагировать на некорректные данные, что мы и наблюдаем. Если вы не хотите об этом задумываться и предпочитаете "быдлокодить", то это ваше право. Способ как решить проблему в лоб вы и сами нашли, разбираться в причинах вам неохота, так что же вы хотите?
а какой прогой вы загоняете логи винды на syslog ?????
неподелитесь?
>[оверквотинг удален]
> chop($addr);
> }
> elsif($_=~/(\d+\.{1}){3}\d+/) # $& - ip addr
> {
> $addr=$&;
> }
>
> $dBase->do("insert into ".$dbTable." (date,time,user,ip,code) values ('".$date."','".$time."','".$user."','".$addr."',".$code.");");
> $date, $time, $user, $code, $addr='';
> }Вставьте перед строчкой
$dBase->do("insert into ".$dbTable." (date,time,user,ip,code) values ('".$date."','".$time."','".$user."','".$addr."',".$code.");");
оператор print, который будет выводит строку вашего запроса
print "insert into ".$dbTable." (date,time,user,ip,code) values ('".$date."','".$time."','".$user."','".$addr."',".$code.");";
И посмотрите, что с ней не так.
добавлю к замечаниям>while(<$hLog>)
> {
> if($_=~/(\S{3})\s?(\d{2})\s?(\d{2}\:?\d{2}\:?\d{2})\s?(\d{4})\s+(\d{3})\s+\S+\s+(\S+)/)вот это вот конструкция очень подозрительна
if($_ =~ /***/)замените ее на:
while($in = <$hLog>) {
{
а вот здесь надо выствить значения переменных по умолчанию, иначе, в случае невыполнения if они у вас будут использоваться со значениями последного успешного предыдущего шага
if($in =~ m/***/)
и далее по тексту замените $_ на $in, либо посто уберите '$_ =~'