RFC embedded Perl Nagios changes: usability and performance.

Stanley Hopcroft Stanley.Hopcroft at IPAustralia.Gov.AU
Mon Jan 26 02:11:42 CET 2004


Dear Sir,

I am writing to thank you for your letter and congratulate you on the
heroic work that you have put into the HEAD branch.

It seems to me that you are in the midst of a massive undertaking.

Please accept my respect for your work and sincere good wishes for your
projects and your future. No work is wasted. There is bound to be a
great deal of pain in a work of creation like this but I hope that you
are satisfied and that

On Sun, Jan 04, 2004 at 07:09:49PM -0600, Ethan Galstad wrote:
> Hi Stanley -
> 
> Your suggestions certainly sound worth pursuing.  I try to stay as 
> far away as possible from the epn code, but if you submit patches 
> against CVS HEAD (2.x), I'll include them in 2.0.  The one change I 
> did make in 2.0 is add a config file option to unload/reload the epn 
> after a certain number of uses to possibly help cut down on memory 
> leaks (not sure if it will help though).
> 

Patches are against HEAD (default) branch/revision of CVS on 26-Jan-2004
(Sydney/Aust time).

The patch files are

1 cand_checks.c.pat
2 can_utils.c.pat

bash-2.04$ md5 cand_utils.c.pat 
MD5 (cand_utils.c.pat) = 3f55eb749053adbae74bbdcfbe8e31b8
bash-2.04$ md5 cand_checks.c.pat 
MD5 (cand_checks.c.pat) = 34438f484d920889ef27a2b343594ae5
bash-2.04$ 

bash-2.04$ date
Mon Jan 26 11:23:22 EST 2004

bash-2.04$ head -10 ../Changelog 
###################
Nagios Change Log
###################


2.0a1 - ??/??/????
------------------
* Added triggered downtime
* Basic adaptive monitoring features
* Added ability to retain scheduling information
bash-2.04$ 


bash-2.04$ patch < cand_checks.c.pat 
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|--- checks.c.orig      Mon Jan 26 11:08:57 2004
|+++ checks.c   Mon Jan 26 11:13:53 2004
--------------------------
Patching file checks.c using Plan A...
Hunk #1 succeeded at 117.
Hunk #2 succeeded at 275.
Hunk #3 succeeded at 336.
Hunk #4 succeeded at 351.
Hunk #5 succeeded at 373.
done
bash-2.04$ patch < cand_utils.c.pat  
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|--- utils.c.orig       Mon Jan 26 11:09:03 2004
|+++ utils.c    Mon Jan 26 11:14:11 2004
--------------------------
Patching file utils.c using Plan A...
Hunk #1 succeeded at 1828.
Hunk #2 succeeded at 1870.
Hunk #3 succeeded at 1947.
Hunk #4 succeeded at 1962.
Hunk #5 succeeded at 1986.
done

bash-2.04$ head -10 config.status 
#! /bin/sh
# Generated automatically by configure.
# Run this file to recreate the current configuration.
# This directory was configured as follows,
# on host xena.aipo.gov.au:
#
# ./configure  --with-perlcache --enable-embedded-perl
#
# Compiler output produced by configure, useful for debugging
# configure, is in ./config.log if it exists.
bash-2.04$ 

bash-2.04$ make nagios
cd ./base && make
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c broker.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c nebmods.c
nebmods.c: In function `neb_add_module':
nebmods.c:100: warning: assignment makes pointer from integer without a
cast
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c checks.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c config.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c commands.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c events.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c flapping.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c logging.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c notifications.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c sehandlers.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c utils.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o retention-base.o sretention.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o xretention-base.o ../xdata/xrddefault.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o comments-base.o ../common/comments.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o xcomments-base.o ../xdata/xcddefault.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o objects-base.o ../common/objects.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o xobjects-base.o ../xdata/xodtemplate.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o statusdata-base.o ../common/statusdata.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o xstatusdata-base.o ../xdata/xsddefault.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o perfdata-base.o perfdata.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o xperfdata-base.o ../xdata/xpddefault.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o downtime-base.o ../common/downtime.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -c -o xdowntime-base.o ../xdata/xdddefault.c
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -o nagios nagios.c broker.o nebmods.o checks.o
config.o commands.o events.o flapping.o logging.o notifications.o
sehandlers.o utils.o retention-base.o xretention-base.o comments-base.o
xcomments-base.o objects-base.o xobjects-base.o statusdata-base.o
xstatusdata-base.o perfdata-base.o xperfdata-base.o downtime-base.o
xdowntime-base.o   -Wl,-export-dynamic -pthread -Wl,-E  -L/usr/local/lib
/usr/local/lib/perl5/5.6.1/mach/auto/DynaLoader/DynaLoader.a
-L/usr/local/lib/perl5/5.6.1/mach/CORE -lperl -lm -lc -lcrypt -lutil -lm    
/usr/lib/libc_r.so: WARNING!  setkey(3) not present in the system!
/usr/lib/libc_r.so: warning: this program uses gets(), which is unsafe.
/usr/lib/libc_r.so: warning: mktemp() possibly used unsafely; consider
using mkstemp()
/usr/lib/libc_r.so: WARNING!  des_setkey(3) not present in the system!
/usr/lib/libc_r.so: WARNING!  encrypt(3) not present in the system!
/usr/lib/libc_r.so: warning: tmpnam() possibly used unsafely; consider
using mkstemp()
/usr/lib/libc_r.so: warning: this program uses f_prealloc(), which is
not recommended.
/usr/lib/libc_r.so: WARNING!  des_cipher(3) not present in the system!
/usr/lib/libc_r.so: warning: tempnam() possibly used unsafely; consider
using mkstemp()
gcc -g -O2
-DAPPLLIB_EXP="/usr/local/lib/perl5/5.6.1/BSDPAN" -fno-strict-aliasing
-I/usr/local/include  -I/usr/local/lib/perl5/5.6.1/mach/CORE
-DHAVE_CONFIG_H -DNSCORE -o nagiostats nagiostats.c -pthread -lm 
bash-2.04$ 


The changes to p1.pl are too extensive so there is a new p1.pl

<WARNING !>

Compatability notes

1 p1.pl (this one) will _not_ run with unpatched Nags, because this
p1.pl does _not_ return plugin output via file system/temp files.


ePN Patched Nags _must_ have this p1.pl or _no_ plugin output will be
visible.

</WARNING !>

The patches obviously will not apply to 1.x; there are however patches
to 1.2 (1-x-cvs, the gzipped tarball you posted recently) that work
fine.

Ian Holsman asked for a copy of them but I have yet to hear his results.

My results (Nag 1.2/afore mentioed tarball) are fine.

Mini rationale/goals of the changes :-

1 Have Perl plugins return their exit codes and output in memory
(instead of temp files)

2 Have Perl plugins return UNKNOWN status if they fail to run (formerly
CRITICAL; introducing new plugins therefore exposed the user to the risk
of spurious alerts)

3 Have Nag report Perl plugin syntax or run time errors, instead of (No
output!)" in the log and the CGIs.

4 Provide the _option_ of GARRULOUS plugin execution, in which a second
log stream is opened (<path_to_nag/var/User_Chosen_File or default
/usr/local/nagios/var/epn_stderr.log ...!!) and plugins with syntax
errors have the result of eval dumped to it (ie numbered list with error
message).

Not default.

5 Provide the _option_ of DEBUG plugin execution in which the Perl calls
and persistent state are written to the second log stream

Only useful for hacking p1.pl. Not default.

Both 4 and 5 require people to edit the p1.pl text. The unedited
behaviour does no more logging than former ePN (except plugin syntax and
or run time errors appear in Nag log).

6 Provide some POD (Perl online Docco) so that perldoc p1.pl provides
some commentary.

Despite the massive increase in the size of p1.pl, the changes are
really minor and along the lines of 'understand Mr Davies code and
change it slightly'.

The major cause of the size increase is so that the logging options
don't cost a perf hit _unless_ they are chosen (by editing the p1.pl
text). In a nutshell, the 3 logging variants of the original code are
assigned to 3 strings each containing different log leves and _one_ of
these strings is evaluated to get the selected log level. I couldn't
think (probably a good way to end a sentence) of a better way of doing
this.

The docco to p1.pl is not complete and there is some other stuff as well
(a new mini_epn.c/no changes to Perl build, some tests) that will come
later if that is Ok.

I had thought about moving the Persistence stuff to CPAN but there are
some packaging and tech reasons for thinking this a bad idea.

Finally, it really is nice to know there exist people like you, Karl,
Subhendu, Voon and so on that _love_ their work, want it to be good, and
are willing to pay the costs.

I am grateful for your encouragement and patience.

Yours sincerely.


-- 
------------------------------------------------------------------------
Stanley Hopcroft
------------------------------------------------------------------------

'...No man is an island, entire of itself; every man is a piece of the
continent, a part of the main. If a clod be washed away by the sea,
Europe is the less, as well as if a promontory were, as well as if a
manor of thy friend's or of thine own were. Any man's death diminishes
me, because I am involved in mankind; and therefore never send to know
for whom the bell tolls; it tolls for thee...'

from Meditation 17, J Donne.
-------------- next part --------------
--- checks.c.orig	Mon Jan 26 11:08:57 2004
+++ checks.c	Mon Jan 26 11:13:53 2004
@@ -117,10 +117,8 @@
 	int time_is_valid=TRUE;
 #ifdef EMBEDDEDPERL
 	char fname[512];
-	char tmpfname[32];
 	char *args[5] = {"",DO_CLEAN, "", "", NULL };
 	int isperl;
-	int tmpfd;
 #ifdef THREADEDPERL
 	dTHX;
 #endif
@@ -277,7 +275,8 @@
 
 		isperl = TRUE;
 		args[0] = fname;
-		args[2] = tmpfname;
+		/* args[2] no longer required because Perl plugin output is returned from perl_call_pv("Embed::Persistent::run_package" ..) */
+		args[2] = "";
 
 		if(strchr(processed_command,' ')==NULL)
 			args[3]="";
@@ -337,14 +336,13 @@
 
 			/******** BEGIN EMBEDDED PERL INTERPRETER EXECUTION ********/
 #ifdef EMBEDDEDPERL
-			if(isperl==TRUE && use_embedded_perl==TRUE){
+			if(isperl){
 
-				/* generate a temporary filename to which stdout can be redirected. */
-				snprintf(tmpfname,sizeof(tmpfname)-1,"/tmp/embeddedXXXXXX");
-				if((tmpfd=mkstemp(tmpfname))==-1)
-					_exit(STATE_UNKNOWN);
+				SV *plugin_out_sv ;
+				char *perl_plugin_output ;
+				int count ;
 
-				/* execute our previously compiled script  */
+				/* execute our previously compiled script - from perl_call_argv("Embed::Persistent::eval_file",..) */
 				ENTER; 
 				SAVETMPS;
 				PUSHMARK(SP);
@@ -353,9 +351,16 @@
 				XPUSHs(sv_2mortal(newSVpv(args[2],0)));
 				XPUSHs(sv_2mortal(newSVpv(args[3],0)));
 				PUTBACK;
-				perl_call_pv("Embed::Persistent::run_package", G_EVAL);
+				count = perl_call_pv("Embed::Persistent::run_package", G_EVAL | G_ARRAY);
 				SPAGAIN;
-				pclose_result=POPi;
+				plugin_out_sv = POPs;
+				perl_plugin_output = SvPOK(plugin_out_sv) && (SvCUR(plugin_out_sv) > 0) ? savepv(SvPVX(plugin_out_sv))
+													: savepv("(No output!)\n") ;
+				strncpy(plugin_output, perl_plugin_output, sizeof(plugin_output));
+				/* The Perl scalar corresp to pclose_result could contain string or integer.
+				   It is better to let POPi do the dirty work (SvPVOK or SvIOK could be true).
+				 */
+				pclose_result = POPi ;
 				PUTBACK;
 				FREETMPS;
 				LEAVE;
@@ -368,25 +373,8 @@
 #endif
 			                }
 
-				/* read back stdout from script */
-				fp=fopen(tmpfname, "r");
-
-				/* default return string in case nothing was returned */
-				strcpy(plugin_output,"(No output!)");
-
-				/* read output from plugin (which was redirected to temp file) */
-				fgets(plugin_output,sizeof(plugin_output)-1,fp);
-				plugin_output[sizeof(plugin_output)-1]='\x0';
 				strip(plugin_output);
 
-				/* ADDED 01/04/2004 */
-				/* ignore any additional lines of output */
-				while(fgets(temp_buffer,sizeof(temp_buffer)-1,fp));
-
-				/* close and delete temp file */
-				fclose(fp);
-				close(tmpfd);
-				unlink(tmpfname);    
 #ifdef DEBUG1
 				printf("embedded perl plugin output was %d,%s\n",pclose_result, plugin_output);
 #endif
-------------- next part --------------
--- utils.c.orig	Mon Jan 26 11:09:03 2004
+++ utils.c	Mon Jan 26 11:14:11 2004
@@ -1828,10 +1828,8 @@
 	struct timeval start_time,end_time;
 #ifdef EMBEDDEDPERL
 	char fname[1024];
-	char tmpfname[32];
 	char *args[5] = {"",DO_CLEAN, "", "", NULL };
 	int isperl;
-	int tmpfd;
 #ifdef THREADEDPERL
 	dTHX;
 #endif
@@ -1872,7 +1870,7 @@
 
 		isperl = TRUE;
 		args[0] = fname;
-		args[2] = tmpfname;
+		args[2] = "";
 
 		if(strchr(cmd,' ')==NULL)
 			args[3]="";
@@ -1949,14 +1947,13 @@
 		/******** BEGIN EMBEDDED PERL CODE EXECUTION ********/
 
 #ifdef EMBEDDEDPERL
-		if(isperl==TRUE && use_embedded_perl==TRUE){
+		if(isperl){
 
-			/* generate a temporary filename to which stdout can be redirected. */
-			snprintf(tmpfname,sizeof(tmpfname)-1,"/tmp/embeddedXXXXXX");
-			if((tmpfd=mkstemp(tmpfname))==-1)
-				_exit(STATE_UNKNOWN);
+			SV *perl_out_sv ;
+			char *perl_output ;
+			int count ;
 
-			/* execute our previously compiled script  */
+			/* execute our previously compiled script - from perl_call_argv("Embed::Persistent::eval_file",..) */
 			ENTER;
 			SAVETMPS;
 			PUSHMARK(SP);
@@ -1965,9 +1962,19 @@
 			XPUSHs(sv_2mortal(newSVpv(args[2],0)));
 			XPUSHs(sv_2mortal(newSVpv(args[3],0)));
 			PUTBACK;
-			perl_call_pv("Embed::Persistent::run_package", G_EVAL);
+			count = perl_call_pv("Embed::Persistent::run_package", G_EVAL | G_ARRAY);
+			/* count is a debug hook. It should always be two (2), because the persistence framework tries to return two (2) args */
 			SPAGAIN;
-			status = POPi;
+			perl_out_sv = POPs;
+			perl_output = SvPOK(perl_out_sv) && (SvCUR(perl_out_sv) > 0) ? savepv(SvPVX(perl_out_sv))
+										     : savepv("(No output!)\n") ;
+			strncpy(buffer, perl_output, sizeof(buffer));
+			buffer[sizeof(buffer)-1]='\x0';
+			/* The Perl scalar corresp to pclose_result could contain string or integer.
+			   It is better to let POPi do the dirty work (SvPVOK or SvIOK could be true).
+			*/
+			status = POPi ;
+
 			PUTBACK;
 			FREETMPS;
 			LEAVE;                                    
@@ -1979,26 +1986,7 @@
 #endif
 				status=-2;
 			        }
-
-			/* read back stdout from script */
-			fp=fopen(tmpfname,"r");
-
-			/* default return string in case nothing was returned */
-			strcpy(buffer,"(No output!)");
-
-			/* grab output from plugin (which was redirected to the temp file) */
-			fgets(buffer,sizeof(buffer)-1,fp);
-			buffer[sizeof(buffer)-1]='\x0';
 			strip(buffer);
-
-			/* ADDED 01/04/2004 */
-			/* ignore any additional lines of output */
-			while(fgets(temp_buffer,sizeof(temp_buffer)-1,fp));
-
-			/* close and delete temp file */
-			fclose(fp);
-			close(tmpfd);
-			unlink(tmpfname);
 
 			/* report the command status */
 			if(status==-2)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: p1.pl
Type: application/x-perl
Size: 25674 bytes
Desc: not available
URL: <https://www.monitoring-lists.org/archive/developers/attachments/20040126/92a42bff/attachment.bin>


More information about the Developers mailing list