The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
именованные каналы(FIFO), проблема чтения, !*! cricket, 22-Мрт-08, 21:48  [смотреть все]
Привет всем! Столкнулся с такой проблемой:
Имеется 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? Обьясните пожалуйста!
ЗЫ:Заранее благодарен.

  • именованные каналы(FIFO), проблема чтения, !*! angra, 14:00 , 23-Мрт-08 (2)
    Краткое содержание вашего поста: "у меня есть некая херня, она не работает, херню я вам не покажу, но ошибку пожалуйста найдите".
    Вы ошиблись, уважаемый, форум телепатов не здесь.
    • именованные каналы(FIFO), проблема чтения, !*! cricket, 16:04 , 23-Мрт-08 (3)
      конфиг 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='';
      }

      • именованные каналы(FIFO), проблема чтения, !*! angra, 02:13 , 24-Мрт-08 (4)
        Попросите кого-нибудь переписать этот скрипт. Вы делаете одну из самых грубых ошибок в программировании - инициализация переменных внутри блока условия и использование их за пределами этого блока. Как следствие всегда есть шанс, что часть переменных придет пустыми(это в перле, в С, например, они будут иметь произвольные значения) и значит запрос будет некорректным. Вторая ошибка чуть более высокого уровня - всегда надежней использовать параметризованные запросы через prepare+execute, чем самому загонять переменные в строку, это избавит от целого ряда проблем. Также есть неточности в регексах и корявый синтаксис, но это мелочи.  
        По поводу изменения поведения при print, могу лишь предположить что почему-то нарушается считывание по границе \n и print это как то исправляет, может из-за задержки с выводом, надо нормально поотлаживать, чтобы сказать наверняка. Однако в любом случае проблема в неправильном коде, он исключительно неустойчив.

        • именованные каналы(FIFO), проблема чтения, !*! cricket, 10:12 , 24-Мрт-08 (5)
          >[оверквотинг удален]
          >переменных придет пустыми(это в перле, в С, например, они будут иметь
          >произвольные значения) и значит запрос будет некорректным. Вторая ошибка чуть более
          >высокого уровня - всегда надежней использовать параметризованные запросы через prepare+execute, чем
          >самому загонять переменные в строку, это избавит от целого ряда проблем.
          >Также есть неточности в регексах и корявый синтаксис, но это мелочи.
          >
          >По поводу изменения поведения при print, могу лишь предположить что почему-то нарушается
          >считывание по границе \n и print это как то исправляет, может
          >из-за задержки с выводом, надо нормально поотлаживать, чтобы сказать наверняка. Однако
          >в любом случае проблема в неправильном коде, он исключительно неустойчив.

          Прошу прощения, а где Вы нашли обьявление переменных внутри блока условия и использование их за пределами блока? Все переменные обьявляются и инициализируются вверху по тексту программы. Дело в том что когда я скармливаю скрипту файл, все прекрасно работает. Не каких пустых значений там нет.

          • именованные каналы(FIFO), проблема чтения, !*! angra, 18:37 , 24-Мрт-08 (7)
            Если вы не можете разобрать свой же код, то и не знаю чем помочь. Могу только предложить попробовать:
            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";'

            >Дело в том что когда я скармливаю скрипту файл, все прекрасно работает

            Ваш код по своей сути неустойчив, он не способен адекватно реагировать на некорректные данные, что мы и наблюдаем. Если вы не хотите об этом задумываться и предпочитаете "быдлокодить", то это ваше право. Способ как решить проблему в лоб вы и сами нашли, разбираться в причинах вам неохота, так что же вы хотите?

      • именованные каналы(FIFO), проблема чтения, !*! stas, 10:47 , 24-Мрт-08 (6)
        >[оверквотинг удален]
        >    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.");";
        И посмотрите, что с ней не так.

      • именованные каналы(FIFO), проблема чтения, !*! NuINu, 19:32 , 28-Июн-08 (9)
        добавлю к замечаниям

        >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, либо посто уберите '$_ =~'




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру