HeatSeekerCannibal has asked for the wisdom of the Perl Monks concerning the following question:

Hello everybody, thanks for taking time to read my post.

I know this question has been asked and answered a number of times. I've read these posts and tried most of what is suggested in them without luck.

I've also spent a considerable amount of time trying different approaches and reading documentation and still have not been able to make this thing work.

I work at the datacenter for a Telecom company in the operations department and take care of a number of solaris and windows servers. Before I got here, they used to have BMC's Patrol to monitor around 10 servers (7 of them, domains in a 10K machine). When I got here, they asked me to write a small hack to make Patrol send emails of alarm conditions only to those people working the current shift.

After a while the Patrol license expired and the budget didnt allow to renew it, so they asked to write "something roughly equivalent"....

So I came up with this thing based in Net::Daemon and making heavy use of Config::IniFiles. It is basically a server that receives the results of monitoring shells being executed in remote servers. The remote shells are called from a perl script and check some specific aspect of the server (filesystems, memory, database usage, pings, etc) which is in turn started from a cron file. The perl script in the remote server sends the results through tcp/ip sockets and the Net::Daemon server receives them, parses them and, depending on the info on the ini file correspoding to the server which sent the data, decide if it is an alarm or not. If it is, send email to the staff currently in the shift and also a "voice alarm" with a brief description of the alarm.

This was all very easy to mantain when we had 10 servers...but the workload has now increased and we've been taking in additional projects and we're now monitoring around 60 servers...and more to come.

So now taking care of the configuration files in both the Net::Daemon server (which i called Monica) and the remote servers (the ones being monitored) has become a nightmare.

I wanted something that every afternoon would check the remote configuration files (the ones that say how to run the diagnostic scripts) comparing them against the local configuration files (the ones that Monica uses to decide if we have an alarm or not) and tell me when something is wrong. But they also need to see this information grafically displayed whenever they want.

SO HERES MY CURRENT PROBLEM:

I wrote a server script which is executed in each server being monitored. This server script listens to a socket tcp/ip port waiting for a command from the IP where the Monica server runs. When this string arrives, if it has the proper syntax, it dumps the configuration ini file to a plain string with Data::Dumper and sends it back to the Monica server. I call this part the Sara server.

The client runs in the machine where the Monica server is executed. It is a GUI which uses Tk to display the configuration file as a tree. This GUI is supposed to display the configuration file for the alarms (the local ini file) and the configuration file of the diagnostic shells (the remote ini file). But to display this last file...it needs to send a message through a tcp/ip socket the the Sara server running in the remote machine.

I KNOW that the Sara server works correctly, because i've requested info from it without the GUI bit in the local client and it does give me the Data::Dumper string which i can convert back to a hash to examine.

But, for the life of me, i cannot make the GUI send the socket message to the Sara server!

I debug and trace the code in both ends simultaneously, but the Sara server only gets the message AFTER i abort the GUI client (¿?).

I’m trying to use the fileevent instruction to make the wait for the socket to receive the answer from the server while still refreshing the GUI. Without luck.

Heres my code and what you need to execute it:

The following are the files needed on the server side (the non-GUI part): SaraServer.pl, SaraServer.ini and FileInfo.pm You need to create an environment variable called MONICACTEINIFILE and give it the full path and name of the SaraServer.ini file. Also put the FileInfo.pm in a directory called "bin" under your $HOME path. These are the files needed on the client (GUI part): finanzas.ini, client.pl, SrvMonica.ini You need to create an environment variable called MONICASRVINIFILE2 and give it the full path and name of the SrvMonica.ini file. Also, modify the line in SrvMonica.ini that corresponds to the FINANZAS server, you need to give it the full path and name of the finanzas.ini file. =====================code for the SaraServer.pl=====================
#!/usr/bin/perl -w use Config::IniFiles; use IO::Socket; use Data::Dumper; require $ENV{HOME}."/bin/FileInfo.pm"; # Sera bueno poner esto en el archivo de configuracion? my @ArgTypes = qw(CMD CAT SUB PARAM SUBPARAM VAL); my $CmdValues = "LEE|MODIFICA|BORRA"; # Abre archivo de configuracion my $NomArchivoCfg = $ENV{MONICACTEINIFILE}; die "Error variable de ambiente MONICACTEINIFILE no contiene nombre de + archivo" unless defined $NomArchivoCfg; my $CfgFileOb = new Config::IniFiles( -file => $NomArchivoCfg ); die "Error al abrir $NomArchivoCfg: $!" unless defined $CfgFileOb; my $SrvMonicaAddr = $CfgFileOb->val("MONICACTE", "MONICASRVADDR1"); die "Error en parametro SrvMonicaAddr: $!" unless defined $SrvMonicaAd +dr; my $SrvSaraPort = $CfgFileOb->val("SRVSARACFG", "SRVSARAPORT"); die "Error en parametro SrvMonicaPort: $!" unless defined $SrvSaraPort +; my $Debug = $CfgFileOb->val("SRVSARACFG", "DEPURACION"); die "Error en parametro Debug: $!" unless defined $Debug; # Determina el archivo de log a usar y redirecciona stdout y stderr my $LogFile = $CfgFileOb->val("SRVSARACFG", "LOGFILE"); die "Error en parametro LogFile: $!" unless defined $LogFile; open(STDOUT, ">>$LogFile") || die "No se pudo redirigir stdout: $!"; open(STDERR, ">&STDOUT") || die "No se pudo redirigir stderr: $!"; select(STDOUT); $| = 1; select(STDERR); $| = 1; my $PidFile = $CfgFileOb->val("SRVSARACFG", "PIDFILE"); die "Error en parametro PidFile: $!" unless defined $PidFile; open(PIDFILE, ">$PidFile") || die "Error al abrir $PidFile: $!"; print PIDFILE $$; close PIDFILE; $server = IO::Socket::INET->new( Proto => 'tcp', LocalPort => $SrvSaraPort, Listen => SOMAXCONN, Reuse => 1); die "Error al iniciar socket: $!" unless $server; select((select($server), $| = 1)[0]); $fecha_hora = `date '+%a %d/%m/%y %H:%M:%S'`; chomp($fecha_hora); print "[Servidor Sara $0 aceptando clientes $fecha_hora]\n"; while($client = $server->accept()) { $client->autoflush(1); $fecha_hora = `date '+%a %d/%m/%y %H:%M:%S'`; chomp($fecha_hora); # Checa que el mensaje venga desde el servidor donde corre Monica next unless $client->peerhost eq $SrvMonicaAddr; my $CadenaRecibida = <$client>; chomp $CadenaRecibida; my @ElementosRecibidos = split(/\s+/, $CadenaRecibida); print $fecha_hora." Desde [".$client->peerhost."] llego [".$CadenaR +ecibida."]\n" if $Debug eq "SI"; my %cmdline = (); my $ndx = 0; my ($ArgType, $ArgVal); # Valida el formato del mansaje recibido foreach my $Cadena(@ElementosRecibidos) { last unless $Cadena =~ /(\w+)=([\w\/\*]+)/; ($ArgType, $ArgVal) = split(/=/, $Cadena); if ($ndx == 0) { last unless $Cadena =~ /(CMD)=(\w+)/ && index($CmdValues, $Ar +gVal) > -1; last if ($ArgVal eq "MODIFICAR" || $ArgVal eq "BORRAR") && $#ElementosRecibidos < 5; } else { last unless $ArgType eq $ArgTypes[$ndx] && defined $ArgVal; } $cmdline{$ArgTypes[$ndx++]} = $ArgVal; } if ($ndx < $#ElementosRecibidos) { print $client "ERROR $ArgTypes[$ +ndx]\n"; next; } my %FileInfo = %{ FileInfo::ObtenerInfoArchivo($NomArchivoCfg) }; if ($cmdline{CMD} eq "LEE" && $cmdline{CAT} eq "*") { my %Host = (); my %Seccionesespeciales = (); my %Categorias = (); my @SeccionesEspeciales = qw(MONICACTE SRVSARACFG); foreach my $SeccionEspecial (@SeccionesEspeciales) { my %Seccionespecial = (); my @SeccionEspecialParams = $CfgFileOb->Parameters($SeccionEs +pecial); foreach my $SeccionEspecialParam (@SeccionEspecialParams) { $Seccionespecial{$SeccionEspecialParam} = $CfgFileOb->val( +$SeccionEspecial, $SeccionEspecialParam); } $Seccionesespeciales{$SeccionEspecial} = \%Seccionespecial; } $Host{CONFIGURACION} = \%Seccionesespeciales; my @CategoriasValidas = $CfgFileOb->Groups(); foreach my $Categoria (@CategoriasValidas) { my %Subcategorias = (); @SubCategorias = $CfgFileOb->GroupMembers( $Categoria ); foreach my $SubCategoria (@SubCategorias) { my %Monitoreo; my @Monitoreos = $CfgFileOb->val($SubCategoria, 'MONITOREO +S'); foreach my $monitoreo (@Monitoreos) { my %ParamsMonitoreo; my @SubParams = $CfgFileOb->Parameters($monitoreo) if $CfgFileOb->SectionExists($monitoreo); foreach my $SubParam(@SubParams) { my @ListaSubParametros = $CfgFileOb->val($monitoreo, + $SubParam); $ParamsMonitoreo{$SubParam} = \@ListaSubParametros; } $Monitoreo{$monitoreo} = \%ParamsMonitoreo; } my ($categoria, $subcategoria) = split(/\s+/, $SubCategori +a, 2); my @LineasCronTab = EncuentraLineaCrontab($Categoria, $sub +categoria); $Monitoreo{CRONTAB} = \@LineasCronTab; $Subcategorias{$subcategoria} = \%Monitoreo; } $Categorias{$Categoria} = \%Subcategorias; } $Host{CATEGORIAS} = \%Categorias; $Host{CFGFILEINFO} = \%FileInfo; $Data::Dumper::Indent = 0; $Data::Dumper::Purity = 1; # my $strHostHash = Data::Dumper->Dump([ \%Host ], [ qw(*Host) ] +); my $strHostHash = Dumper( \%Host ); print $client "OK $strHostHash\n"; } else # SI EL COMANDO NO ES LECTURA..... { my @CategoriasValidas = $CfgFileOb->Groups(); if (grep(/$cmdline{CAT}/, @CategoriasValidas) < 1) { print $client "ERROR CAT\n"; next; } my @SubCategoriasValidas = $CfgFileOb->GroupMembers( $cmdline{CA +T} ); if (grep(/$cmdline{SUB}/, @SubCategoriasValidas) < 1) { print $client "ERROR SUB\n"; next; } my @MonitoreosValidos = $CfgFileOb->val("$cmdline{CAT} $cmdline{ +SUB}", 'MONITOREOS'); if (grep(/$cmdline{PARAM}/, @MonitoreosValidos)<1) { print $client "ERROR PARAM\n"; next; } my @SubParams = $CfgFileOb->Parameters($cmdline{PARAM}) if $CfgFileOb->SectionExists($cmdline{PARAM}); unless (@SubParams && $#SubParams == 1) { print $client "ERROR PARAM\n"; next; } } # elsif ($cmdline{CMD} eq "MODIFICA") # { # @SubCategorias = $CfgFileOb->GroupMembers( $Categoria ); # } # elsif ($cmdline{CMD} eq "BORRA") # { # SubCategorias = $CfgFileOb->GroupMembers( $Categoria ); # } } close $client; # ################################################################# # EncuentraLineaCrontab # # # ################################################################# sub EncuentraLineaCrontab { my @CrontabLines = (); my $Cat = $_[0]; my $SubCat = $_[1]; my $CronCmd = "crontab -l | grep clntMonica | grep CAT=".$Cat." | g +rep SUB=".$SubCat; my @crontablines = `$CronCmd`; if ($#crontablines == -1) { push @CrontabLines, "NO HAY LINEA CORRESPONDIENTE EN CRON"; } else { while(@crontablines) { my $linea = shift @crontablines; chomp $linea; push @CrontabLines, $linea; } } return @CrontabLines; }
=====================code for the SaraServer.ini=====================
[MONICACTE] DEPURACION=SI LOGFILE=/home/cisic_mty/big_oper/monica/log/clntMonica.log MONICASRVADDR1=10.192.3.14 MONICASRVADDR2=10.192.4.205 CONNECTIONTIMEOUT=10 MONICASRVPORT=9000 [SRVSARACFG] SRVSARAPORT=9001 DEPURACION=SI LOGFILE=/home/cisic_mty/big_oper/monica/log/srvSara.log PIDFILE=/home/cisic_mty/big_oper/monica/bin/srvSara.pid [INFORMIX FINANZAS_TCP] MONITOREOS=<<EOT STATUS SEGV ASF CHD DBSP LOGS EOT [INFORMIX PROCESOS] MONITOREOS=<<EOT ONTAPE EOT [SISTOP FSYSTEM1] MONITOREOS=<<EOT / /VAR EOT [SISTOP FSYSTEM2] MONITOREOS=<<EOT /USR /HOME /HERRAMIENTAS /USERS /OPT /FICHAS /USER /RESPALDO /OXLEY /EXCLUSIVO /DBEXPORTS /ONTAPES /VAR/CRASH EOT [SISTOP MEMORIA] MONITOREOS=<<EOT RAM SWAP EOT [APLICACION WEBSERVER] MONITOREOS=<<EOT ADMSERV AUTO_ERR CONSDISP CAT_CTA CECOBE HERMES INTRACTA CTRLPAGO SICOR GASOLIN EGRCAP CONECAU EOT # Webserver configurados sin listar: # CONSDISP, CAT_CTA, CECOBE, HERMES, INTRACTA, CTRLPAGO, SICOR, GASOLI +N, EGRCAP, CONECAU [APLICACION SCOTIABANK] MONITOREOS=<<EOT ARCHIVO EOT ######################################################### # INSTANCIA FINANZAS_TCP ######################################################### [STATUS] SCRIPT=/home/cisic_mty/big_oper/monica/shells/informix.sh ARGUMENTOS=<<EOT /home/informix onconfig finanzas_tcp /home/informix/etc/sqlhosts STATUS EOT [SEGV] SCRIPT=/home/cisic_mty/big_oper/monica/shells/informix.sh ARGUMENTOS=<<EOT /home/informix onconfig finanzas_tcp /home/informix/etc/sqlhosts SEGV EOT [ASF] SCRIPT=/home/cisic_mty/big_oper/monica/shells/informix.sh ARGUMENTOS=<<EOT /home/informix onconfig finanzas_tcp /home/informix/etc/sqlhosts ASF EOT [CHD] SCRIPT=/home/cisic_mty/big_oper/monica/shells/informix.sh ARGUMENTOS=<<EOT /home/informix onconfig finanzas_tcp /home/informix/etc/sqlhosts CHD EOT [DBSP] SCRIPT=/home/cisic_mty/big_oper/monica/shells/informix.sh ARGUMENTOS=<<EOT /home/informix onconfig finanzas_tcp /home/informix/etc/sqlhosts DBSP EOT [LOGS] SCRIPT=/home/cisic_mty/big_oper/monica/shells/informix.sh ARGUMENTOS=<<EOT /home/informix onconfig finanzas_tcp /home/informix/etc/sqlhosts LOGS EOT [ONTAPE] SCRIPT=/home/cisic_mty/big_oper/monica/shells/busca_ontape_c.sh ARGUMENTOS=<<EOT EOT ######################################################### # FILE SYSTEM 1 ######################################################### [/] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT / EOT [/VAR] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /var EOT ######################################################### # FILE SYSTEM 2 ######################################################### [/USR] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /usr EOT [/HOME] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /home EOT [/HERRAMIENTAS] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /herramientas EOT [/USERS] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /users EOT [/OPT] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /opt EOT [/FICHAS] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /fichas EOT [/USER] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /user EOT [/RESPALDO] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /respaldo EOT [/OXLEY] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /oxley EOT [/EXCLUSIVO] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /exclusivo EOT [/DBEXPORTS] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /dbexports EOT [/ONTAPES] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /ontapes EOT [/VAR/CRASH] SCRIPT=/home/cisic_mty/big_oper/monica/shells/fs.sh ARGUMENTOS=<<EOT /var/crash EOT ######################################################### # MEMORIA ######################################################### [RAM] SCRIPT=/home/cisic_mty/big_oper/monica/shells/memoria.sh ARGUMENTOS=<<EOT RAM EOT [SWAP] SCRIPT=/home/cisic_mty/big_oper/monica/shells/memoria.sh ARGUMENTOS=<<EOT SWAP EOT ######################################################### # APLICACION WEBSERVER ######################################################### [ADMSERV] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT ADMSERV EOT [AUTO_ERR] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT AUTO_ERR EOT [CONSDISP] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT CONSDISP EOT [CAT_CTA] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT CAT_CTA EOT [CECOBE] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT CECOBE EOT [HERMES] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT HERMES EOT [INTRACTA] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT INTRACTA EOT [CTRLPAGO] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT CTRLPAGO EOT [SICOR] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT SICOR EOT [GASOLIN] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT GASOLIN EOT [EGRCAP] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT EGRCAP EOT [CONECAU] SCRIPT=/home/cisic_mty/big_oper/monica/shells/webserver.sh ARGUMENTOS=<<EOT CONECAU EOT ######################################################### # APLICACION SCOTIABANK ######################################################### [ARCHIVO] SCRIPT=/home/cisic_mty/big_oper/monica/shells/archivo_SB.sh ARGUMENTOS=<<EOT EOT
=====================code for the FileInfo.pm=====================
package FileInfo; use File::stat; use User::grent; use User::pwent; use POSIX qw(strftime); sub ObtenerInfoArchivo { my %Datos = (); my $st = stat(shift @_) or die "No se pudo abrir archivo"; my $ActTime = strftime "%a %d/%m/%y %H:%M:%S", localtime($st->atime +); my $ModTime = strftime "%a %d/%m/%y %H:%M:%S", localtime($st->mtime +); my $CreTime = strftime "%a %d/%m/%y %H:%M:%S", localtime($st->ctime +); my $grupo = getgrgid($st->gid); my $ident = getpwuid($st->uid); $Datos{UNAME} = $ident->[0]; $Datos{UID} = $st->uid; $Datos{GNAME} = $grupo->[0]; $Datos{GID} = $st->gid; $Datos{ATIME} = $ActTime; $Datos{MTIME} = $ModTime; $Datos{CTIME} = $CreTime; return \%Datos; } 1;
=====================code for the client.pl=====================
#!/usr/local/ActivePerl-5.6/bin/perl -w use IO::Select; use IO::Socket; use Tk; use Tk::IO; use Tk::HList; use Config::IniFiles; use vars qw/$IMG_PARAMHOST $IMG_CAT $IMG_SUBCAT $IMG_PARAM $IMG_SUBPAR +AM/; use subs qw/lee_socket muestra_datos_host cierra_socket/; use strict; # use clntSara; my $SocketHandler; my $Socket_; my $ArchivoCfg = $ENV{MONICASRVINIFILE2}; my $cfgfile = new Config::IniFiles( -file => $ArchivoCfg ); die "Error al abrir $ArchivoCfg: $!" unless defined $cfgfile; my @Hosts = $cfgfile->Parameters("SRVMONICACFG"); my $NumHosts = $#Hosts; my $VentanaPrincipal = MainWindow->new; $VentanaPrincipal->configure(-title => "Configuracion de Servidor Moni +ca", -background => 'blue'); my $FrameSup = $VentanaPrincipal->Frame(-relief => 'groove', -borderwidth => 3, -background => 'seagreen2', )->pack(-side => 'top', -fill +=> 'x'); my $Etiqueta = $FrameSup->Label(-text => $ArchivoCfg)->pack(-side => ' +left'); $Etiqueta->pack; $Etiqueta->bind('' => sub { $VentanaPrincipal-> destroy }); my $FrameInt = $VentanaPrincipal->Frame(-relief => 'groove', -borderwidth => 3, -background => 'seagreen2', )->pack(-side => 'top', -fill +=> 'x'); my $Lista = $FrameInt->Scrolled(qw/Listbox -setgrid 1 -height 10 -scrollbars e/)->pack(qw/-side left -expand yes -fill both/); $Lista->focus; $Lista->bind('<Double-1>' => sub{ muestra_datos_host($_[0]->get('activ +e')) }); $Lista->insert(0, @Hosts); $Lista->activate(0); my $FrameInf = $VentanaPrincipal->Frame(-relief => 'groove', -borderwidth => 3, -background => 'seagreen2', )->pack(-side => 'top', -fill +=> 'x'); my $ConfigDisplay = $FrameInf->Scrolled(qw\HList -separator | -selectmode extended -width 55 -height 20 -indent 35 -scrollbars se -itemtype imagetext\ )->grid(qw/-sticky nsew/); # $IMG_CAT = $VentanaPrincipal->Bitmap(-file => Tk->findINC('folder.xb +m')); # $IMG_SUBCAT = $VentanaPrincipal->Bitmap(-file => Tk->findINC('file.x +bm')); # $IMG_PARAMHOST = $VentanaPrincipal->Bitmap(-file => 'parametrohost.x +bm'); $IMG_PARAMHOST = $VentanaPrincipal->Bitmap(-file => 'subparametro.xbm' +); $IMG_CAT = $VentanaPrincipal->Bitmap(-file => 'categoria.xbm'); $IMG_SUBCAT = $VentanaPrincipal->Bitmap(-file => 'subcategoria.xbm'); $IMG_PARAM = $VentanaPrincipal->Bitmap(-file => 'parametro.xbm'); $IMG_SUBPARAM = $VentanaPrincipal->Bitmap(-file => 'subparametro.xbm') +; MainLoop; sub muestra_datos_host { $ConfigDisplay->delete('all'); my $HostIniFileName = $cfgfile->val('SRVMONICACFG', $_[0]); my $HostIni = new Config::IniFiles( -file => $HostIniFileName ); die "Error al abrir $ArchivoCfg: $!" unless defined $HostIni; my @ParametrosHost = $HostIni->Parameters($_[0]); foreach my $ParametroHost(@ParametrosHost) { next if $ParametroHost eq 'CATEGORIAS'; my $Valor = $HostIni->val($_[0], $ParametroHost); $ConfigDisplay->add($ParametroHost, -text => $ParametroHost."=".$Valor, -image => $IMG_PARAMHOST, -data => $ParametroHost); } my @Categorias = $HostIni->val($_[0], 'CATEGORIAS'); foreach my $Categoria(@Categorias) { $ConfigDisplay->add($Categoria, -text => "$Categoria", -image => $IMG_CAT, -data => "CAT=$Categoria"); my @SubCategorias = $HostIni->val($Categoria, 'SUBCATEGORIAS'); foreach my $SubCategoria(@SubCategorias) { $ConfigDisplay->add("$Categoria|$SubCategoria", -text => "$SubCategoria", -image => $IMG_SUBCAT, -data => "CAT=$Categoria|SUB=$SubCategoria") +; my @Parametros = $HostIni->Parameters($SubCategoria); foreach my $Parametro(@Parametros) { $ConfigDisplay->add("$Categoria|$SubCategoria|$Parametro", -text => "$Parametro", -image => $IMG_PARAM, -data => "CAT=$Categoria|SUB=$SubCategori +a|PARAM=$Parametro"); my @SubParametros = $HostIni->val($SubCategoria, $Parametro +); foreach my $SubParametro(@SubParametros) { $ConfigDisplay->add("$Categoria|$SubCategoria|$Parametro +|$SubParametro", -text => "$SubParametro", -image => $IMG_SUBPARAM, -data => "CAT=$Categoria|SUB=$SubCa +tegoria|PARAM=$Parametro|SUBPARAM=$SubParametro"); } } } } my $Mensaje = "CMD=LEE CAT=*"; # my $ProgramaClntSara = $cfgfile->val("CLNTSARA CONFIGURACION", 'PR +OGRAMACLIENTE'); my $SrvSaraIPAddress = gethostbyname(lc($_[0])); my $SrvSaraPort = $cfgfile->val("CLNTSARA CONFIGURACION", 'PUERTO'); $Socket_ = IO::Socket::INET->new(Proto => 'tcp', PeerAddr => inet_ntoa($SrvSaraIP +Address), PeerPort => $SrvSaraPort, # Listen => 10, Reuse => 'yes', # Type => SOCK_STREAM, Timeout => 10) or die "No se pudo crear conexion con $SrvSaraIPAddress: $!"; select((select($Socket_), $| = 1)[0]); print $Socket_ $Mensaje; $VentanaPrincipal->fileevent($Socket_, 'readable', [ \&lee_socket ]) +; # MainLoop; # $ConfigDisplay->add("CATEGORIA|SUBCATEGORIA", # -text => "cual", # -image => $IMG_SUBCAT, # -data => 'SUB'); # $VentanaPrincipal->fileevent(\*DELSOCKET, 'readable', [\&despliega +_rmtsrv_conf]); # $SocketHandler = Tk::IO->new(-linecommand => \&lee_socket, # -childcommand => \&cierra_socket); # $SocketHandler->exec(sub { perl ./clntSara.pl excubitor \"CMD=LEE +CAT=*\" }); } sub lee_socket { print "lee_socket\n"; my $conexion = $Socket_->accept(); my $mensaje; while( defined( my $buffer = <$Socket_> ) ) # read from the socket { print "From client: $buffer" ; $mensaje = $mensaje . $buffer ; } close($Socket_); } sub cierra_socket { print "cierra_socket\n"; }
=====================code for the SrvMonica.ini=====================
[SRVMONICACFG] EXCUBITOR=/home/cisic_mty/big_oper/monica-nora/monica/test/clntSara/in +i/excubitor.ini FINANZAS=/home/cisic_mty/big_oper/monica-nora/monica/test/clntSara/ini +/finanzas.ini NXDEV0=/home/cisic_mty/big_oper/monica-nora/monica/test/clntSara/ini/n +xdev0.ini [SRVNORACFG] PROGRAMASRVNORA=/home/cisic_mty/big_oper/monica-nora/monica/bin/SrvNor +a.pl DEPURACION=SI PROGRAMAENVIO=/home/cisic_mty/big_oper/monica-nora/monica/bin/noraClnt +SocketAlarmas.pl PUERTO=9000 HOSTS_VALIDOS=<<EOT 10.72.57.114 10.192.4.234 EOT [SRVSONIACFG] LOGFILE=/home/cisic_mty/big_oper/monica-nora/monica/log/SrvSonia.log PAUSA=60 TIMEOUT=10 [CLNTSARA CONFIGURACION] DEPURACION=SI PUERTO=9001 LOGFILE=/home/cisic_mty/big_oper/monica-nora/monica/test/clntSara/clnt +Sara.log PROGRAMACLIENTE=/home/cisic_mty/big_oper/monica-nora/monica/test/clntS +ara/clntSara.pl [CLNTSARA CTEMONICACFG] MONICASRVADDR2=10.192.4.224 CONNECTIONTIMEOUT=10
=====================code for the finanzas.ini=====================
#################################################### # FINANZAS #################################################### [FINANZAS] ENVIARALARMA=SI LOGFILE=/home/cisic_mty/big_oper/monica-nora/monica/log/finanzas.log CATEGORIAS=<<EOT INFORMIX SISTOP APLICACION MONICA EOT [MONICA] ENVIARALARMA=SI SUBCATEGORIAS=<<EOT SONIA EOT [SONIA] PING=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT [INFORMIX] ENVIARALARMA=SI SUBCATEGORIAS=<<EOT FINANZAS_TCP PROCESOS EOT [SISTOP] ENVIARALARMA=SI SUBCATEGORIAS=<<EOT FSYSTEM1 FSYSTEM2 MEMORIA EOT [APLICACION] ENVIARALARMA=SI SUBCATEGORIAS=<<EOT WEBSERVER SCOTIABANK EOT #---------- INSTANCIA FINANZAS_TCP ----------------- [PROCESOS] ONTAPE=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=1 EOT [FINANZAS_TCP] STATUS=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT SEGV=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=3/100 EOT ASF=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=1/100 EOT CHD=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=1/100 EOT DBSP=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=2/100 EOT LOGS=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=5/100 EOT #---------- SISTEMA OPERATIVO FS1 ------------------ [FSYSTEM1] /=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=70/100 EOT /VAR=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=70/100 EOT #---------- SISTEMA OPERATIVO FS2 ------------------ [FSYSTEM2] /USR=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=90/100 EOT /HOME=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=85/100 EOT /HERRAMIENTAS=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=85/100 EOT /USERS=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=95/100 EOT /OPT=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=85/100 EOT /FICHAS=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=85/100 EOT /USER=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=90/100 EOT /RESPALDO=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=85/100 EOT /OXLEY=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=85/100 EOT /EXCLUSIVO=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=85/100 EOT /DBEXPORTS=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=85/100 EOT /ONTAPES=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=85/100 EOT /VAR/CRASH=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=85/100 EOT #---------- MEMORIA -------------------------------- [MEMORIA] RAM=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=99/100 EOT SWAP=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=70/100 EOT #---------- APLICACION WEBSERVER ------------------- [WEBSERVER] ADMSERV=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT AUTO_ERR=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT CONSDISP=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT CAT_CTA=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT CECOBE=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT HERMES=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT INTRACTA=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT CTRLPAGO=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT SICOR=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT GASOLIN=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT EGRCAP=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT CONECAU=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT #---------- APLICACION SCOTIABANK ------------------ [SCOTIABANK] ARCHIVO=<<EOT ENVIARALARMA=SI GRUPOS=Operaciones,SupervisoresCISIC RANGO=0 EOT

Edit: g0n - readmore tags and formatting

Replies are listed 'Best First'.
Re: perl/tk sockets and fileevent
by bowei_99 (Friar) on Mar 30, 2006 at 08:29 UTC
    A couple things:
    1. You don't have to be an expert in html, but please at least put a <p> at the end of each paragraph.
    2. If you have a lot of formatting, you could write your message in a WSYWIG editor like MS Word, save as html, and paste the html (not great, but better than the hard to read posting you put up)
    3. When you post and hit the preview button, proofread the results first.
    4. Post the relevant chunks of your code, as well as the specific error messages you received.
    5. You say you've tried what people have suggested here. What specifically have you tried, and what were the results you got? For example, what posts did you read, and what specific steps did you take?
    I can see that you may not know where to start for the last point. So, some debugging tips:
    1. Learn to use at least a subset of the perl debugger. Start it by typing perl -d, and at the prompt, type h.
    2. Put in debugging statements in various key parts of your code where you're wondering about a value of a variable, e.g. your socket variable. Use one of the following:
      warn "variable is $variable - $!\n"; carp "variable is $variable - $!\n"; croak "variable is $variable - $!\n";
    For the last two (carp and croak), you'll need to put Use Carp; in your code. carp will give an error message, but not quit, croak will do the same and quit.

    -- Burvil

Re: perl/tk sockets and fileevent
by zentara (Cardinal) on Mar 30, 2006 at 11:47 UTC
    but the Sara server only gets the message AFTER i abort the GUI client

    That is a big clue.

    To bring the other monks up to date, I was privately contacted by email about this and proposed that the problem is in his client's socket sub, where he has socket code which will block the gui.

    sub lee_socket { print "lee_socket\n"; my $conexion = $Socket_->accept(); my $mensaje; while( defined( my $buffer = <$Socket_> ) ) # read from the socket { print "From client: $buffer" ; $mensaje = $mensaje . $buffer ; } close($Socket_); }

    I sent him fileevent code to replace this, but he hasn't responded as to whether it worked or not. The code was part of a simpler example, which wasn't obscured by the spaghetti complexity of the ini files, and long mexican variable names.

    $mw ->fileevent($socket, readable => sub { my $line = <$socket>; unless (defined $line) { $mw->fileevent($socket => readable => ''); return; } $log->insert(end => $line); });

    My advice, if you want to get people to answer this, is to present a simpler example. With all the complex ini files, and the need to create special files on my system, just to test your script, I will just think " hope someone knows this" and move on. Please try to remake your example code, to be a self contained server and client, which runs on localhost, and demonstrates your problem. Get rid of the ini crap and hardwire in the values, so all we have to do is start the server, and client and see what happens.

    If you can't take the time to simplify(and clarify) your problem, why should we?


    I'm not really a human, but I play one on earth. flash japh
      ZenTara, You're quite right. When I was pasting the whole code, I tought the same objection you've justifiedly raised here. But at the moment didnt have time for anything else. I am currently working in writing a super compressed version of both scripts, in addition to other chores my boss gives me every half hour or so. Didnt mean to disrespect you or The Monks valuable time by not posting a proper question. On the contrary, I do know everybody has other duties to take care of and I'm grateful you devote time to my question. Anyway, this code you're posting here I had not seen and will try it. Just a question, though, the socket object in it....is it supposed to be extracted from the acceptor method of the socket? Or is it the socket object itself? Thanks in advance for you attention.
        Well the code was from a complete example set which I attached to my email response to your question. I include it below in the readmore, in case you lost the attachments, or some other mailer-incompatibility problems. It is a basic server, and a Tk client. The client sends what is typed in the bottom entry box, and displays the return in the top text box. It is basically what you want to do. You can see that it is basically very simple, when chopped down to just network and Tk code. The fileevent just takes the socket itself, and watches it for when it is readable. When it is, it prints it out. But fileevent will NOT block the rest of the script, like a while loop will. fileevent is basically Tk's version of IO::Select, but adapted to work with the event loop.

        I'm not really a human, but I play one on earth. flash japh