if condition using telnet in perl not working - perl

I'm trying to use if condition to check if command has passed, but its not working. Even though the mount has been successful it goes to failed message. When i enter this command, it retruns to the prompt without any message, hence i'm comparing with a "". And when i do a "ls" of destination folder, it shows all contents of source folder. Any help? Is my if condition correct?
my $port = new Net::Telnet->new(Host=>$ip,Port=>$ip_port,Timeout => "$timeout", Dump_Log => "dumplog.log", Errmode=> "return" );
if($port->cmd("mount -t nfs -o nolock <path-of-source-folder> <destination-folder>") eq "")
{
print "Successful\n";
}
else{
print "Failed.\n ";
}

In scalar context, the Net::Telnet cmd method returns 1 on success (not a string). Your check should be something like:
if ($port->cmd("mount -t nfs -o nolock <path-of-source-folder> <destination-folder>") == 1)
{
print "Successful\n";
} else {
print "Failed.\n";
}
If you actually want to collect the output from the mount command and inspect it, you will have to either call it in list context or pass a stringref argument, like so:
my #outlines = $port->cmd("mount ...");
Or:
my $out;
my $ret = $port->cmd("mount ...", [Output => \$out]);
if ($ret == 1)
{
# inspect $out
}
See the Net::Telnet documentation for more.

Your check for the result seems to be wrong. The documenation of Net::Telnet says that
This method sends the command $string, and reads the characters sent back by the command up until and including the matching prompt. It's assumed that the program to which you're sending is some kind of command prompting interpreter such as a shell.
The command $string is automatically appended with the output_record_separator, by default it is "\n". This is similar to someone typing a command and hitting the return key. Set the output_record_separator to change this behavior.
In a scalar context, the characters read from the remote side are discarded and 1 is returned on success.
So you need to check in a scalar context
if ($port->cmd("..") ) {
...
}

Related

Perl to exec a program with arguments containing "#"

Am a newbie in Perl and need help with a small problem
Situation:
I have to execute a command line program through perl.
The arguments to this command line are email addresses
These email addresses are passed to me through another module.
Problem:
I have written the code to create the argument list from these email addresses but am having problem in running exec().
NOTE: If I pass hardcoded strings with escaped "#" character to the exec() as command args,it works perfectly.
Sub creating cmd args map
sub create_cmd_args {
my($self, $msginfo) = #_;
my #gd_args_msg = ('--op1');
my $mf = $msginfo->sender_smtp;
$mf =~ s/#/\\#/ig; ## Tried escaping #, incorrect results.
push #gd_args_msg, '-f="'.$mf.'"';
for my $r (#{$msginfo->per_recip_data}) {
my $recip = $r->recip_addr_smtp;
$recip =~ s/#/\\#/ig; ## Tried escaping #, incorrect results.
push #gd_args_msg, '-r="'.($recip).'"';
}
return #gd_args_msg;
}
Sub that uses this args map to exec the program
sub check {
my($self, $msginfo) = #_;
my $cmd = $g_command;
my #cmd_args = create_cmd_args($self, $msginfo);
exec($cmd, #cmd_args); ### ******* fails here
}
Sample run:
INPUT:
sender_smtp: <ashish#isthisreal.com>
receiver_smtp: <areyouarealperson#somedomain.com>
Could someone please guide me what is wrong here?
As an argument to a command in the shell,
-f="<ashish#isthisreal.com>"
causes the the string
-f=<ashish#isthisreal.com>
to be passed to the program. Your program passes
-f="<ashish\#isthisreal.com>"
to the program. The problem isn't the #; the problem is the " and \ you are adding.
my $mf = $msginfo->sender_smtp;
push #gd_args_msg, "-f=$mf"; # Assuming $mf is <ashish#isthisreal.com>
If you look at the post at Trying to convert Perl to PHP and the code within the md5sum implementation that calls the command line you will see an approach that will save you from needing to worry about escaping characters.

Send request parameters when calling a PHP script via command line

When you run a PHP script through a browser it looks something like
http://somewebsite.com/yourscript?param1=val1&param2=val2.
I am trying to achieve the same thing via command line without having to rewrite the script to accept argv instead of $_REQUEST. Is there a way to do something like this:
php yourscript.php?param1=val1&param2=val2
such that the parameters you send show up in the $_REQUEST variable?
In case you don't want to modify running script, you can specify parameters using in -B parameter to specify code to run before the input file. But in this case you must also add -F tag to specify your input file:
php -B "\$_REQUEST = array('param1' => 'val1', 'param2' => 'val2');" -F yourscript.php
I can't take credit for this but I adopted this in my bootstrap file:
// Concatenate and parse string into $_REQUEST
if (php_sapi_name() === 'cli') {
parse_str(implode('&', array_slice($argv, 1)), $_REQUEST);
}
Upon executing a PHP file from the command line:
php yourscript.php param1=val1 param2=val2
The above will insert the keys and values into $_REQUEST for later retrieval.
No, there is no easy way to achieve that. The web server will split up the request string and pass it into the PHP interpreter, who will then store it in the $_REQUEST array.
If you run from the command line and you want to accept similar parameters, you'll have to parse them yourself. The command line has completely different syntax for passing parameters than HTTP has. You might want to look into getopt.
For a brute force approach that doesn't take user error into account, you can try this snippet:
<?php
foreach( $argv as $argument ) {
if( $argument == $argv[ 0 ] ) continue;
$pair = explode( "=", $argument );
$variableName = substr( $pair[ 0 ], 2 );
$variableValue = $pair[ 1 ];
echo $variableName . " = " . $variableValue . "\n";
// Optionally store the variable in $_REQUEST
$_REQUEST[ $variableName ] = $variableValue;
}
Use it like this:
$ php test.php --param1=val1 --param2=val2
param1 = val1
param2 = val2
I wrote a short function to handle this situation -- if command line arguments are present and the $_REQUEST array is empty (ie, when you're running a script from the command line instead of though a web interface), it looks for command line arguments in key=value pairs,
Argv2Request($argv);
print_r($_REQUEST);
function Argv2Request($argv) {
/*
When $_REQUEST is empty and $argv is defined,
interpret $argv[1]...$argv[n] as key => value pairs
and load them into the $_REQUEST array
This allows the php command line to subsitute for GET/POST values, e.g.
php script.php animal=fish color=red number=1 has_car=true has_star=false
*/
if ($argv !== NULL && sizeof($_REQUEST) == 0) {
$argv0 = array_shift($argv); // first arg is different and is not needed
foreach ($argv as $pair) {
list ($k, $v) = split("=", $pair);
$_REQUEST[$k] = $v;
}
}
}
The sample input suggested in the function's comment is:
php script.php animal=fish color=red number=1 has_car=true has_star=false
which yields the output:
Array
(
[animal] => fish
[color] => red
[number] => 1
[has_car] => true
[has_star] => false
)

What does this perl crash means?

Can someone tell me what this means?
if (not defined $config{'crontab'}) {
die "no crontab defined!";
}
I want to open a file crontab.txt but the perl script crashes at this line and I don't really know any perl.
EDIT 1
It goes like this:
sub main()
{
my %config = %{getCommandLineOptions()};
my $programdir = File::Spec->canonpath ( (fileparse ( Win32::GetFullPathName($PROGRAM_NAME) ))[1] );
my $logdir = File::Spec->catdir ($programdir, 'logs');
$logfile = File::Spec->catfile ($logdir, 'cronw.log');
configureLogger($logfile);
$log = get_logger("cronw::cronService-pl");
# if --exec option supplied, we are being invoked to execute a job
if ($config{exec}) {
execJob(decodeArgs($config{exec}), decodeArgs($config{args}));
return;
}
my $cronfile = $config{'crontab'};
$log->info('starting service');
$log->debug('programdir: '.$programdir);
$log->debug('logfile: '.$logfile);
if (not defined $config{'crontab'}) {
$log->error("no crontab defined!\n");
die "no crontab defined!";
# fixme: crontab detection?
}
$log->debug('crontab: '.$config{'crontab'});
And I'm trying to load this 'crontab.txt' file...
sub getCommandLineOptions()
{
my $clParser = new Getopt::Long::Parser config => ["gnu_getopt", "pass_through"];
my %config = ();
my #parameter = ( 'crontab|cronfile=s',
'exec=s',
'args=s',
'v|verbose'
);
$clParser->getoptions (\%config, #parameter);
if (scalar (#ARGV) != 0) { $config{'unknownParameter'} = $true; }
return \%config;
}
Probably I have to give the script an argument
Probably I have to give the script an argument
I would say so.
$ script --cronfile=somefile
That code looks to see whether there is a key 'crontab' in the hash %config. If not, then it calls die and terminates.
If that's not what you expect to happen, then somewhere else in your script there should be something that is setting $config{'crontab'}, but there is not currently enough information in your question to determine what that might be.
Probably the file path of crontab.txt is expected in %config hash, pointed by the 'crontab' key, but isn't there! If so, a DIRTY solution CAN BE:
$config{'crontab'}='FULLPATH/crontab.txt';
#if (not defined $config{'crontab'}) {
# die "no crontab defined!";
#}
but this may not work because there is something like $config{'prefix'} and what you will try to open is the path represented by the concatenation of both, or just because in $config{'crontab'} is expected any other value than full path!

What would be the best logic to detect if multiple SQL options were left enabled in a config file?

I am trying to figure the best logic to determine if the user of my script has left multiple SQL option enabled in the config file the reason is only one is supported.
The first idea I had was to use a simple variable that was set to either 0,1,2,3 and then read by the script to run the correct subroutine. Then I got to thinking if they was a way to have it done by whether the section existed in the config file, it was possible with the module I am using. But the problem I ran into now is if I have it determining which SQL software to use based on the existence of a certain config section doesn't that mean I have to have logic that says if "this" section and "that" section exist then error out? But then that would mean I would to take into account all combination of all section that pertain. Right?
Was the best way to approach this the first way that I had done it? or is there a better way?
I have included samples of my config file and the unfinished subroutine which the logic would be enclosed in. I would control the existence of the sections by commenting them out in the config file. I am writing in Perl by the way and I am using Config::IniFiles for reading and writing to the INI file.
Any ideas would be very appreciated.
sub sql_option {
if (config_file()->SectionExists('SQLite')) {
sqlite_setup();
} elsif (config_file()->SectionExists('MySQL')) {
mysql_setup();
} elsif (config_file()->SectionExists('PgSQL')) {
pgsql_setup();
} elsif (config_file()->SectionExists('MSSQL')) {
mssql_setup();
} else {
print color 'red';
print "No SQL server option defined!\n";
print color 'reset';
print "\n";
die "Script halted!\n";
}
}
And the INI file:
[ESX]
host=esxi01.solignis.local
;port=
user=root
password=
[SQLite]
db=discovery.db
[MySQL]
host=sql01.solignis.local
;port=
user=root
password=
;[PgSQL]
;host=
;port=
;user=
;password=
;[MSSQL]
;host=
;port=
;user=
;password=
Here's one way of doing it:
my %sql_setup_functions = (
SQLite => \&sqlite_setup,
MySQL => \&mysql_setup,
PgSQL => \&pgsql_setup,
MSSQL => \&mssql_setup,
);
sub sql_option
{
my #engines = grep {
config_file()->SectionExists($_)
} keys %sql_setup_functions;
unless (#engines == 1) {
print color 'red';
if (#engines) {
print "Multiple SQL server options defined!\n";
print " $_\n" for sort #engines;
} else {
print "No SQL server option defined!\n";
}
print color 'reset';
print "\n";
die "Script halted!\n";
} # end unless exactly 1 SQL engine
# Call the setup function for the selected engine:
$sql_setup_functions{$engines[0]}->();
} # end sql_option

Perl Net::SNMP returns noSuchName when snmpwalk works

I am new to perl, but I am trying to write a plug-in for nagios. I have a simple get request that fails, but if I try the same request with snmpwalk it works.
My code is:
#!/usr/bin/perl -w
use strict;
use Net::SNMP;
my $host = '10.10.10.203';
my $community = 'myComm';
my $session;
my $error;
my $response = undef;
($session, $error) = Net::SNMP->session(
-hostname => $host,
-version => 2,
-community =>$community,
-port => 161,
-timeout => 20
);
my $uptimeOID = '1.3.6.1.2.1.1.3.0';
my $myOID = '1.3.6.1.4.1.7933';
if( !defined( $response = $session->get_request($myOID)))
{
if( $session->error_status == 2)
{
my $sessionError = $session->error;
print ("($sessionError) OID not supported ($myOID).\n");
}
}
else
{
print ("$response");
}
If I run this script it will fail saying noSuchName, but if a run:
snmpwalk -v 2c -c myComm 10.10.10.203 1.3.6.1.4.1.7933
I get the response I want. Does anybody know why this wont work?
If I check the uptime OID with this script it will work the way it should.
You've already identified that via the command-line you're doing a "walk" rather than a "get". If there's a specific value you want to "get" in your script, put in the full OID identifying the target.
There's something in a table record that you probably want to get at (and it seems like everything in FASTTRAKIDERAID-MIB is in fact tabular), so a simple get isn't enough. Look at the snmpwalk.pl script that comes with Net::SNMP or see if SNMP::Util can easily provide the functionality you're looking for.
Use get_next_request, not get_request. It will return the first valid oid after the one you pass it.
I found my problem. When I use snmpwalk, it will grab the whole tree and return a value. The perl module will not. It doesn't traverse the tree to the end even thought there is only one thing below it, it just says no.