Hi!
Такая задача:
Мониторю радиолинию на BreezeLink'ах, у них интерактивный интерфейс через RS232, поэтому посылаю в порт команду и жду в ответе определенную подстроку. Но в случае потери дальнего конца или еще чего
демон периодически вываливается (возможно модем отрубается), никак не пойму по какому сигналу... может посоветуете чего или ошибку какую найдете:
Вот программа:
#!/usr/bin/perl -w
#
use Term::ReadKey;
use strict;
use Fcntl;
use IO::Handle;
my ($napr,$port,$period);
my $lock_port_dir = "/var/lock";
my $cfgfile = "naprav.conf";
#---------------------------
my $debug=($ARGV[0] eq '-D')?1:0;
my $lockfile;
my $pidfile="/var/run/testbreeze.pid";
my %equip=readcfg($cfgfile);
my $logfile;
my (@ans,$stime);
demonize_me($pidfile);
while (1) { #run forever
$stime=time;
EQUIP: foreach $napr (sort(keys %equip)){ #foreach
print "start...\n" if $debug;
$port=$equip{$napr};
print $napr." - ".join("x",$port)."\n" if $debug;
########
#getans
#########
if (plock($port)) { #if1
#unlocked
@ans=(time,getans($port));
} else { #if1
#locked
next EQUIP;
} #if1
unplock($port);
#########
#printlog
#########
chomp ($period=qx(date +%m%Y));
$logfile=$napr.".".$period.".log";
open(LOG,">>$logfile") or die $!;
print LOG join(" ",@ans)."\n";
close(LOG);
} #foreach
print "stop\n" if $debug;
select(undef,undef,undef,180-(time-$stime));
print "stop\n" if $debug;
} # while 1 run forever
exit;
sub readcfg {
my $cfg=shift;
my (%equip, $in, @value);
open CFG,"$cfg" or die "Can't find ".$cfg.":".$!;
while (<CFG>) {
next if (/^#/ || /^\s+$/) ;
$in = $_;
@value = split(/:/,$in,2);
for (@value) {
s/^\s+//;
s/\s+$//;
}
$equip{$value[0]}=$value[1];
}
close CFG;
return %equip;
}
sub getans {
my $p=shift;
my (@ans,$msel);
open (COM,"+<$p") or die $!;
COM->autoflush(1);
ReadMode(5,*COM);
alarm 100;
$msel=modsel("L");
print "select L - ".$msel."\n" if $debug;
if ($msel<1) { @ans[0 .. 1]=&geter(); } else { return (0,0,0,0);}
print "errors L - ".join(" ",@ans[0 .. 1])."\n" if $debug;
$msel=modsel("R");
print "select R - ".$msel."\n" if $debug;
if ($msel<1) { @ans[2 .. 3]=&geter(); } else { return (@ans,0,0);}
print "errors R - ".join(" ",@ans[2 .. 3])."\n" if $debug;
$msel=modsel("L");
print "select L - ".$msel."\n" if $debug;
alarm 0;
close (COM);
return @ans;
}
sub modsel {
#return 0 if Ok
#return 1 if Not Normal mode
#return 2 if TimeOut
my $m=shift;
my ($p1,$p2,$i);
LM: $p2=0;
$i=0;
$p1="=" x 59;
$p1.='$';
do {print COM chr(27); $p2=modans($p1); $i++;} until ($p2 or $i>5);
return 2 if ($i>5);
print COM chr(13);
$p2=modans('System is in Normal Mode');
return 1 unless $p2;
print COM chr(13);
if ($m eq "R") { $p1='\(Remote monitor\)\s+$';} else { $p1='\(Local monitor\)\s+$';}
$p2=modans($p1);
return 0 if $p2;
print COM "1";
$p2=modans('REMOTE Parameters\s+$');
goto LM unless ($p2);
print COM "4";
$p2=modans('REMOTE Parameters menu\s+$');
goto LM unless ($p2);
if ($m eq "R") {
print COM "1";
$p2=modans('Loaded remote database\s+$',2.0);
print COM chr(13) if ($p2);
} else {
print COM "20".chr(13);
}
goto LM;
}
sub geter {
my ($p1,$p2,@x,$i);
LN: $p2=0;
$i=0;
print COM chr(13);
$p1="=" x 59;
$p1.='$';
do {print COM chr(27); $p2=modans($p1); $i++;} until ($p2 or $i>5);
return (0,0) if ($i>5);
print COM chr(27);
print COM "2";
$p2=modans('Counters menu\s+$');
goto LN unless ($p2);
#get counters
print COM "1";
while (defined($p2=ReadLine(0.5,*COM))) {
if ($p2=~ /LIU [TR]X BUFFERS:\s+(\w+)/ ) {
push (@x,$1);
}
if ($p2=~/(LIU|RADIO) BUFFER ERROR RATE:\s+([\-\+\.\w]+)/) {
push (@x,$2);
}
if (($#x eq 1) and (($x[0] eq 0) or ($x[1] eq 0))) {@x[2..3]=(0,0);}
last if ($#x eq 3);
}
while (ReadKey(0.5,*COM)){}
print COM chr(27);
$p2=modans('Counters menu\s+$');
goto LN unless ($p2);
#reset counters
print COM "4";
print COM chr(27);
return @x[2..3];
}
sub modans {
my $p4=shift;
my $pause=shift || 0.5;
my $p3=0;
my ($p5,$p);
print $p4."\n\n" if $debug;
if (defined($p4)){
$p5.=$p while (defined($p=ReadKey($pause,*COM)));
$p3=1 if $p5=~/$p4/m;
print $p3."- p3 p5 - " if $debug;
print $p5."\n\n" if $debug;
}
return $p3;
}
sub plock {
my $port1 = shift;
$port1=~/\/(\w+)$/;
$lockfile = $lock_port_dir."/LCK..$1";
return 0 if (!sysopen(F,$lockfile,O_RDWR|O_CREAT|O_EXCL));
print F $$."\n".$0."\n";
close F;
$SIG{__DIE__}=\&quit;
$SIG{'HUP'} = 'IGNORE';
$SIG{'INT'}=\&quit;
$SIG{'TERM'}=\&quit;
$SIG{'QUIT'}=\&quit;
#### Ignore alarm signals from kernel
$SIG{'ALRM'} = 'IGNORE';
return 1;
}
sub unplock {
unlink $lockfile;
}
sub quit {
my $signame=shift;
print "Exit: ".$!." ".$@."\nSIG$signame\n";
unplock($port);
unlink $pidfile;
exit;
}
sub demonize_me {
my $pidfile = shift;
print "Daemonizing ...\n";
defined (my $pid = fork) or die "Can't fork: $!";
if ($pid) {
exit;
} else {
if (defined $pidfile){
die "ERROR: I Quit! Another copy seems to be running. Check $pidfile\n" if -f $pidfile;
open(PIDFILE,">$pidfile") or warn "creating $pidfile: $!\n";
print PIDFILE "$$\n";
close PIDFILE;
}
require 'POSIX.pm';
&POSIX::setsid or die "Can't start a new session: $!";
open STDOUT,($debug)?'>/tmp/breeze.tmp':'>/dev/null' or die "ERROR: Redirecting STDOUT to /dev/null: $!";
open STDIN, '</dev/null' or die "ERROR: Redirecting STDIN from /dev/null: $!";
}
}