Perl issue with script

Im using a script for Nagios that runs a query in oracle and returns a number. The script can be found at http://nagiosexchange.altinity.org/nagiosexchange/check_oracle_generic/check_oracle_generic. When this script is run command line with all the correct flag definitions, it returns the correct out put. But when nagios runs it automatically, there is an error that shows up in the web interface. The error is below:

**ePN failed to compile /usr/local/nagios/libexec/check_oracle_generic: "Global symbol "$SID" requires explicit package name at (eval 1) line 74,

Ive read several different forums where it says to add main:: to the line at 74 which looks like:

if (!$SID || !$dbuser || !$dbpassword || !$w || !$c || !$q)
      {    # this is line 74

And ive tried this and added it to several other places, while it does return a different error, it still doesnt work.

Ive checked the LD library paths for nagios and root, added the paths to the /etc/init.d/httpd and /etc/sysconfig/httpd.


The other weird thing is is if i put the command line arguments in a shell script wrapper, it works as well. Problem with this it doesnt return the status codes nagios needs to alert.

So can someone whos great with perl please help me out with this? Thanks!
linuxpigAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Adam314Commented:
Can you post more of the script.
0
linuxpigAuthor Commented:
Click the link in my original post, it will show you the entire script.
0
Adam314Commented:
Add this after line 30:
    use vars qw($SID $dbuser $dbpassword $w $c $q);
0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

linuxpigAuthor Commented:
Didnt work, it returns the following error instead:

**ePN failed to compile /usr/lib64/nagios/plugins/check_oracle_generic: "Global symbol "$h" requires explicit package name at (eval 10) line 83,
Performance Data:      Global symbol "$dbhandle" requires explicit package name at (eval 10) line 100.
0
Adam314Commented:
When nagios exectues this, does it use the #! line to determine how to handle the file?  Or do you specify how to process the file and options somewhere?  It looks like perl is being run with the strict pragma, but this isn't in this file.

You can solve this error by hadding a use vars statement similar to above with the undefined variable names, or modifying the previous use vars statement to include these:
    use vars qw($h $dbhandle);

Note that if perl isn't being run with the -s switch, the program would have to be modified to handle the command line arguments.  If nagios isn't using the #! line to process the file, it's possible it isn't using the -s switch.
0
linuxpigAuthor Commented:
If you click on the link in the original post, you will see the code and see that it is using the -s flag. I appreciate the input but it seems like people are just submitting guesses. Im looking for a legitimate thread of troubleshooting here.
0
Adam314Commented:
It use vars statement will solve this problem.  As I don't have nagios, I can't test any of my suggestions.

What I meant by my previous comment, is that it appears that nagios is not executing the script exactly as it appears, but is doing something else - like using the eval function to process the script.

Did you add the use vars statement?  Do you get any errors?
0
linuxpigAuthor Commented:
Yes it continued to error.
0
Adam314Commented:
What is the new error?
0
linuxpigAuthor Commented:
**ePN failed to compile etc..., Since this seems like it will never end, Is there way of just taking this awful perl script and write a shell script that will do the same thing? It seems like the way to go at this point.
0
Adam314Commented:
Not a shell script, but you could write a new perl script.  What do you need the script to do?  How do you want it to get it's information (such as SID, username, password) - through command line parameters, environment variables, have them hard-coded?

Does it need to return specific values, as this script does?
0
linuxpigAuthor Commented:
Yes it needs to do exactly what this bad script can.
0
Adam314Commented:
You will need to install the Getopt::Long module, if it isn't already installed.  If it isn't, you'll get an error similar to "Can't locate Getopt/Long.pm in @INC".  To solve this problem install the module by running this as root:
    perl -MCPAN -e 'install Getopt::Long'
or  cpan Getopt::Long

#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use DBI;
###############################################
# Usage : perl -s check_cmd_adoc -SID=<SID> -dbuser=<dbuser> -dbpassword=<dbpassword> -w=<warning> -c=<critical> -q=<query>
#  -SID        : Oracle SID
#  -dbuser     : Oracle user
#  -dbpassword : Oracle password
#  -w          : amount for warning
#  -c          : amount for critical
#  -q          : SQL query
 
my ($SID, $dbuser, $dbpassword, $w, $c, $q);
 
use constant UNKNOWN => 3;
use constant CRITICAL => 2;
use constant WARNING => 1;
use constant OK => 0;
 
my $USAGE = "Usage: $0 -SID=<sid> -dbuser=<dbuser> -dbpassword=<dbpassword> -w=<warning> -c=<critical> -q=<query>\n";
 
GetOptions(
  "SID=s"    => \$SID,
  "dbuser=s" => \$dbuser,
  "dbpassword=s" => \$dbpassword,
  "w=f"        => \$w,
  "c=f"        => \$c,
  "q=s"        => \$q,
  "h"          => sub {print($USAGE);exit(OK);},
  ) or print($USAGE),exit(UNKNOWN);
 
print($USAGE),exit(UNKNOWN) unless ($SID and $dbuser and $dbpassword and defined($w) and defined($c) and $q);
 
# if you already have a TNS_ADMIN environment variable do not
# comment following line
# otherwise you can uncomment and overwrite the variable if you want
# to specify the tnsnames.ora file directory
#$ENV{TNS_ADMIN} = '/usr/local/instantclient_10_2';
 
 
# establish DB connection
my $dbhandle;
unless($dbhandle = DBI->connect ("dbi:Oracle:$SID", $dbuser, $dbpassword)) {
	print ("CRITICAL: $DBI::errstr");
	exit(CRITICAL);
}
 
# execute query
my $statement = $dbhandle->prepare($q);
unless ($statement->execute()) {
	print("Execution error");
	exit(UNKNOWN);
}
 
# retrieve result
my @row = $statement->fetchrow_array();
$statement->finish();
 
my $exit_code = 0;
if($row[0] >= $c) {
	print "CRITICAL: ";
	exit(CRITICAL);
}
if($row[0] >= $w) {
	print "WARNING: ";
	exit(WARNING);
}
 
print "OK: result = $row[0]";
exit(OK);

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
linuxpigAuthor Commented:
Thanks Adam for the quick response. Will it get around the ePN issue in Nagios the other script had? It tests fine command line but the true test it for Nagios to run it, but i cant test it yet because our network is down. Go figure
0
linuxpigAuthor Commented:
BTW, Adam can you please tell me the differences between your script and the original script. Im curious how you were able to get around the ePN issue incase it happens again
0
Adam314Commented:
Like I mentioned, it appears that Nagios is running the script with eval, rather than starting another perl process - and that Nagios is running the script with the strict pragma.  This pragma requires that all your variables are declared, which was not the case in the original script.  Also, the original script was using the -s switch to perl to get the command line variables, while this script uses the Getopt::Long module.  Other than that, I just used more common coding practices.  You'll notice that this new script is similar to the original.
0
linuxpigAuthor Commented:
Adam, i finally had a chance to run the script, the problem is when an error is happening, the return just says Warning or Critical and not Warning: result = 50 or Critical; result = 60
0
Adam314Commented:

#new line 63:
    print "CRITICAL: result = $row[0]";
 
#new line 67
    print "WARNING: result = $row[0]";

Open in new window

0
linuxpigAuthor Commented:
Mistake, i didnt mean to mark this for deletion
0
linuxpigAuthor Commented:
Let it be known, Adam is the man! Thanks adam
0
linuxpigAuthor Commented:
Adam was great in assisting with this issue which was very critical for me.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Perl

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.