check_megaraid_sas nagios plugin explanation - perl

Can anyone explain following piece of code in https://github.com/simondeziel/custom-nagios-plugins/blob/master/plugins/check_megaraid_sas . (line num 220-223)
Why this code is there
} elsif ( $slotnumber != 255 ) {
$pdbad++;
$status = 'CRITICAL';
}

It makes sense to look at the complete section:
PDISKS: while (<PDLIST>) {
if ( m/Slot Number\s*:\s*(\d+)/ ) {
$slotnumber = $1;
$pdcount++;
} elsif ( m/(\w+) Error Count\s*:\s*(\d+)/ ) {
if ( $1 eq 'Media') {
$mediaerrors += $2;
} else {
$othererrors += $2;
}
} elsif ( m/Predictive Failure Count\s*:\s*(\d+)/ ) {
$prederrors += $1;
} elsif ( m/Firmware state\s*:\s*(\w+)/ ) {
$fwstate = $1;
if ( $fwstate eq 'Hotspare' ) {
$hotsparecount++;
} elsif ( $fwstate eq 'Online' ) {
# Do nothing
} elsif ( $fwstate eq 'Unconfigured' ) {
# A drive not in anything, or a non drive device
$pdcount--;
} elsif ( $slotnumber != 255 ) {
$pdbad++;
$status = 'CRITICAL';
}
}
} #PDISKS
That section loops over a list of PDs (Primary Disks?), and I assume that this file / program output contains a human readable status for every attached device. The code looks at every line and performs some actions depending on the content of that line:
$slotnumber is assigned whenever there is Slot Number : ... in the contents of PDLIST. From looking at the logic, if there is a Firmware state line that is not Hotspare, Online or Unconfigured, and the $slotnumber is not 255, then something went horribly wrong and the status is considered CRITICAL. The number of bad PDs ($pdbad) is then increased by one.

Related

How to cluster based on ssdeep?

Hi I am trying to find the groups out of files based on ssdeep.
I have generated ssdeep of files and kept it in csv file.
I am parsing the file in perl script as follows:
foreach( #all_lines )
{
chomp;
my $line = $_;
my #split_array = split(/,/, $line);
my $md5 = $split_array[1];
my $ssdeep = $split_array[4];
my $blk_size = (split(/:/, $ssdeep))[0];
if( $blk_size ne "")
{
my $cluster_id = check_In_Cluster($ssdeep);
print WFp "$cluster_id,$md5,$ssdeep\n";
}
}
This also checks whether the ssdeep is present in previously clustered group and if not creates new group.
Code for chec_In_Cluster
my $ssdeep = shift;
my $cmp_result;
if( $cluster_cnt > 0 ) {
$cmp_result = ssdeep_compare( $MRU_ssdeep, $ssdeep );
if( $cmp_result > 85 ) {
return $MRU_cnt;
}
}
my $d = int($cluster_cnt/4);
my $thr1 = threads->create(\&check, 0, $d, $ssdeep);
my $thr2 = threads->create(\&check, $d, 2*$d, $ssdeep);
my $thr3 = threads->create(\&check, 2*$d, 3*$d, $ssdeep);
my $thr4 = threads->create(\&check, 3*$d, $cluster_cnt, $ssdeep);
my ($ret1, $ret2, $ret3, $ret4);
$ret1 = $thr1->join();
$ret2 = $thr2->join();
$ret3 = $thr3->join();
$ret4 = $thr4->join();
if($ret1 != -1) {
$MRU_ssdeep = $ssdeep;
$MRU_cnt = $ret1;
return $MRU_cnt;
} elsif($ret2 != -1) {
$MRU_ssdeep = $ssdeep;
$MRU_cnt = $ret2;
return $MRU_cnt;
} elsif($ret3 != -1) {
$MRU_ssdeep = $ssdeep;
$MRU_cnt = $ret3;
return $MRU_cnt;
} elsif($ret4 != -1) {
$MRU_ssdeep = $ssdeep;
$MRU_cnt = $ret4;
return $MRU_cnt;
} else {
$cluster_base[$cluster_cnt] = $ssdeep;
$MRU_ssdeep = $ssdeep;
$MRU_cnt = $cluster_cnt;
$cluster_cnt++;
return $MRU_cnt;
}
and the code for chech:
sub check($$$) {
my $from = shift;
my $to = shift;
my $ssdeep = shift;
for( my $icnt = $from; $icnt < $to; $icnt++ ) {
my $cmp_result = ssdeep_compare( $cluster_base[$icnt], $ssdeep );
if( $cmp_result > 85 ) {
return $icnt;
}
}
return -1;
}
But this process takes very much time( for 20-30MB csv file it takes 8-9Hours).
I have also tried using multithreading while checking in Cluster but not much help i got from this.
Since their is no need of csv parser like Text::CSV (because of less operation on csv) i didn't used it.
can anybody please solve my issue? Is it possible to use hadoop or some other frameworks for grouping based on ssdeep?
There is a hint from Optimizing ssDeep for use at scale (2015-11-27).
Depends on your purpose, loop and match SSDEEP in different chunk size will create a N x (N-1) hash comparison. Unless you need to find partial contents, otherwise, avoid it.
It is possible to breakdown of the hash index in step 1 as suggested in the article. This is a better way for partial contents match with different chunk size.
It is possible to reduce SSDEEP hash by grouping similar hash by generate a "distance cousin" hash.

socks 5 proxy on Perl

I am new in Perl and trying to understand this cod in Link : http://codepaste.ru/1374/but I have some problem in understanding this part of code:
while($client || $target) {
my $rin = "";
vec($rin, fileno($client), 1) = 1 if $client;
vec($rin, fileno($target), 1) = 1 if $target;
my($rout, $eout);
select($rout = $rin, undef, $eout = $rin, 120);
if (!$rout && !$eout) { return; }
my $cbuffer = "";
my $tbuffer = "";
if ($client && (vec($eout, fileno($client), 1) || vec($rout, fileno($client), 1))) {
my $result = sysread($client, $tbuffer, 1024);
if (!defined($result) || !$result) { return; }
}
if ($target && (vec($eout, fileno($target), 1) || vec($rout, fileno($target), 1))) {
my $result = sysread($target, $cbuffer, 1024);
if (!defined($result) || !$result) { return; }
}
if ($fh && $tbuffer) { print $fh $tbuffer; }
while (my $len = length($tbuffer)) {
my $res = syswrite($target, $tbuffer, $len);
if ($res > 0) { $tbuffer = substr($tbuffer, $res); } else { return; }
}
while (my $len = length($cbuffer)) {
my $res = syswrite($client, $cbuffer, $len);
if ($res > 0) { $cbuffer = substr($cbuffer, $res); } else { return; }
}
}
can any body explain to me exactly whats happen in these lines:
vec($rin, fileno($client), 1) = 1 if $client;
vec($rin, fileno($target), 1) = 1 if $target;
and
select($rout = $rin, undef, $eout = $rin, 120);
Basically, the select operator is used to find which of your file descriptors are ready (readable, writable or there's an error condition). It will wait until one of the file descriptors is ready, or timeout.
select RBITS, WBITS, EBITS, TIMEOUT
RBITS is a bit mask, usually stored as a string, representing a set of file descriptors that select will wait for readability. Each bit of RBITS represent a file descriptor, and the offset of the file descriptor in this bit mask should the file descriptor number in system. Thus, you could use vec to generate this bit mask.
vec EXPR, OFFSET, BITS
The vec function provides storage of lists of unsigned integers. EXPR is a bit string, OFFSET is the offset of bit in EXPR, and BITS specifies the width of each element you're reading from / writing to EXPR.
So these 2 lines:
vec($rin, fileno($client), 1) = 1;
vec($rin, fileno($target), 1) = 1;
They made up a bit mask string $rin with setting the bit whose offset equals the file descriptor number of $client, as well as the one of $target.
Put it into select operator:
select($rout = $rin, undef, $eout = $rin, 120);
Then select will monitor the readability of the two file handlers ($client and $target), if one of them is ready, select will return. Or it will return after 120s if no one is ready.
WBITS, EBITS use the same methodology. So you could infer that the above select line will also return when the two file handler have any exceptions.

How do I return a value if the prepare statement fails in the below code?

sub loadFileRecon {
my $self = shift;
my $days = shift;
if($days eq '') {
$days = 1;
}
my $insert = $self->{rba}->rbdb->prepare(q{
insert into rba.filerecon (
filename,
records,
start_dtm,
file_type,
managed_file_id,
mf_dtm,
processed_tidemark,
mm_records,
mm_dropped,
mm_erred,
mm_duplicate,
file_source
)
select
i.filename,
i.records,
i.file_dtm start_dtm,
i.file_type,
mf.managed_file_id,
mf.created_dtm mf_dtm,
NULL,
i.orig_records,
i.dropped,
i.erred,
i.duplicate,
i.file_source
from rba.mmfilestats i, managedfile mf, filelog fl
where
i.filename = fl.file_name and
trunc(i.file_dtm) = trunc(sysdate - ?) and
mf.managed_file_id = fl.managed_file_id
}) or die $DBI::errstr;
$insert->execute($days);
$insert->finish;
$self->{rba}->rbdb->commit;
my $update = $self->{rba}->rbdb->prepare(q{
update rba.filerecon fr
set processed_tidemark = (
select processed_tidemark
from jobhasfile j
where j.managed_file_id = fr.managed_file_id
)
where
trunc(start_dtm) = trunc(sysdate - ?) and
processed_tidemark is null
});
$update->execute($days);
$insert->finish;
$self->{rba}->rbdb->commit;
}
If the prepare statement above fails due to table or view not existing, then it should return a value to perl module
you are telling your program to die if the prepare returns false:
}) or die $DBI::errstr;
replace that with what you're looking for:
}) or return $somevalue;
or remove the or entirely and check the value of your statement handle;
my $insert = $self->{rba}->rbdb->prepare(q{
...
});
return $somevalue if ( !$insert );
What you need to do is return the DBI::errstr. Do not die on error.
So do something like this (starting at your prepare and ending with your where but getting rid of the "or die"):
...prepare( ......
where
i.filename = fl.file_name and
trunc(i.file_dtm) = trunc(sysdate - ?) and
mf.managed_file_id = fl.managed_file_id
});
if ($DBI::errstr) {
# oops something is wrong
print $DBI::errstr;
call_error($DBI::errstr);
}
Good luck
Your post of the errorlog shows that your error is raised at point of execute not at the point of prepare.
So this what you do AFTER the execute:
#your execute statement first
$insert->execute($days);
#Now the check on the execute
if ($DBI::errstr) {
# oops something is wrong
return -1;
}
Please let me know if this works

Perl sub doesn't want to work with passed objects as parameters

I pass two Date::Manip::Date objects, perfectly valid dates to my sub:
sub get_duration {
my $duration;
my #val;
my $from = $_[0]->new_date();
my $to = $_[1]->new_date();
# $from->parse("2012-03-06");
# $to->parse("2012-03-07");
print $from . " ".$to. "<-- <br />";
my #f = $from->value();
if ($f[0] == 2012) {
$from->config("ConfigFile",$HOLIDAYS_2012);
} elsif ($f[0] == 2013) {
$from->config("ConfigFile",$HOLIDAYS_2013);
} elsif ($f[0] == 2014) {
$from->config("ConfigFile",$HOLIDAYS_2014);
} elsif ($f[0] == 2015) {
$from->config("ConfigFile",$HOLIDAYS_2015);
}
my #t = $to->value();
if ($t[0] == 2012) {
$to->config("ConfigFile",$HOLIDAYS_2012);
} elsif ($t[0] == 2013) {
$to->config("ConfigFile",$HOLIDAYS_2013);
} elsif ($t[0] == 2014) {
$to->config("ConfigFile",$HOLIDAYS_2014);
} elsif ($t[0] == 2015) {
$to->config("ConfigFile",$HOLIDAYS_2015);
}
print "from " . #f ." to ". #t."<br>";
my $delta = $from->calc($to, "business");
print $from->calc($to, "business") . " <-";
#val = $delta->value();
if ($to->is_business_day()) {
$duration = $val[3]+1;
} else {
$duration = $val[3];
}
return $duration;
}
I get the output
Date::Manip::Date=HASH(0xacdf7a0) Date::Manip::Date=HASH(0xacdfb50)<--
from 0 to 0
<-
Software error:
Can't call method "value" on an undefined value at '#val = $delta->value();'
That is the two dates are passed all right, I got NO errors when it tries to set their config files, Regardless, the value arrays #t and #f are empty and it breaks down as soon as I try to get the delta.
However if I uncomment the two lines
$from->parse("2012-03-06");
$to->parse("2012-03-07");
(hence ignoring the parameters)
It works just fine as intended.
There's something I'm missing about passing objects in Perl I suspect?
Firstly
&get_overlap_duration($saved[$i][5], $saved[$i][6], $saved[$i][7], $saved[$i][8])
Is called
I've printed the #saved values and they're correct, they're strings:
2012-03-06, 2012-03-08, 2012-03-05, 2012-03-07
Then inside get_overlap_duration those strings are
my $from1 = new Date::Manip::Date;
my $to1 = new Date::Manip::Date;
my $from2 = new Date::Manip::Date;
my $to2 = new Date::Manip::Date;
$from1->parse($_[0]);
$to1->parse($_[1]);
$from2->parse($_[2]);
$to2->parse($_[3]);
Then there's there is a call for get_duration for instance $duration = get_duration($from2, $to1);
I've checked the server error log there were no complaints apart from the software error displayed in the browser.
The problem is that on the following line:
my $delta = $from->calc($to, "business");
It's not returning a valid object. Which likely means that something in the calc() function is failing. Since "business" is not a valid date. And if you read the Date::Manip::Calc man page, the mode parameter is only legal when you pass in two date objects before that and you've only passed one.

insert_id mysqli

I'm trying to return the inserted id from a mysql INSERT query. Each time I run the function I get 0 as the result. Can someone please explain at what point I can retrieve the value because although the script below executes I cannot retireve the inserted id. Probably done something stupid.
<?php
public function execSQL($sql, $params, $close){
$mysqli = new mysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
$stmt = $mysqli->prepare($sql) or die ("Failed to prepared the statement!");
call_user_func_array(array($stmt, 'bind_param'), $this->refValues($params));
$this->insert_id($this->connection);
$stmt->execute();
if($close){
$result = $mysqli->affected_rows;
} else {
$meta = $stmt->result_metadata();
while ( $field = $meta->fetch_field() ) {
$parameters[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $this->refValues($parameters));
while ( $stmt->fetch() ) {
$x = array();
foreach( $row as $key => $val ) {
$x[$key] = $val;
}
$results[] = $x;
}
$result = $results;
}
$stmt->close();
$mysqli->close();
return $result;
}
?>
Check $mysqli->insert_id after executing insert query.