Perl NetSNMP extension with multiple devices - perl

I have got a machine (Debian based) with some temperature sensors attached to it, and i would like to query them over snmp, from one script. I can work with one sensor ok, but i am struggling when i plug another one in.
What I am trying to do is loop through each device, and give each one an id, then use this ID as part of the OID, then give it a value.
I've never worked with snmp before, and my perl is not great so any help would be much appreciated. Below is my code:
#!/usr/bin/perl
use NetSNMP::agent (':all');
use NetSNMP::ASN qw(ASN_OCTET_STR ASN_INTEGER);
$BASE_OID=".1.3.6.1.4.1.41050";
$dev_id=1;
$string_value;
$integer_value;
sub pimon_handler {
my ($handler, $registration_info, $request_info, $requests) = #_;
my $request;
my $oid_key;
for($request = $requests; $request; $request = $request->next()) {
$oid_key=$BASE_OID . '.' . $dev_id;
my $oid = $request->getOID();
if ($request_info->getMode() == MODE_GET) {
if ($oid == new NetSNMP::OID($oid_key . '.0')) {
$request->setValue(ASN_OCTET_STR, $string_value);
}
elsif ($oid == new NetSNMP::OID($oid_key . '.1')) {
$request->setValue(ASN_INTEGER, $integer_value);
}
} elsif ($request_info->getMode() == MODE_GETNEXT) {
if ($oid == new NetSNMP::OID($oid_key . '.0')) {
$request->setOID($oid_key . '.1');
$request->setValue(ASN_INTEGER, $integer_value);
}
elsif ($oid < new NetSNMP::OID($oid_key . '.0')) {
$request->setOID($oid_key . '.0');
$request->setValue(ASN_OCTET_STR, $string_value);
}
}
}
}
#location of where we are going to find the 1wire devices
#sensors = `cat /sys/bus/w1/devices/w1_bus_master1/w1_master_slaves`;
chomp(#sensors);
#loop through the sensors we find
foreach $line(#sensors) {
#work out the temp we have got. Need to change this for other sensor types
$output = `cat /sys/bus/w1/devices/$line/w1_slave`;
$output =~ /t=(?<temp>\d+)/;
$integer_value = sprintf "%.0f",$+{temp} / 1000;
$string_value = $line;
my $agent = new NetSNMP::agent();
$agent->register("Pimon$looptest", $BASE_OID . '.' . $dev_id,
\&pimon_handler);
print "Dev $dev_id temp $line temp is $integer_value\n";
$dev_id ++;
}

Are you getting any errors or output?
I suspect that your problem lies in and around your reading the data file by shelling-out to cat instead of opening the file and looping over the linewise contents.
Try dumping the value of #sensors. if it is a single entry array, with the only element containing your entire file, then simply switch #sensors to be scalar. then split $sensors into an array and loop over that.
my $sensors = `read something`
chomp $sensors;
my #sensors = split(/\n/, $sensors);
foreach $line (#sensors) {
...

Related

Error in moxiemanager with PHP7

After updating the version from PHP5 to PHP7, an error appears when trying to insert images from the moxiemanager plugin of the tinymce that I have integrated into the project.
just tell me:
Error:
Array to string conversion
After a few hours, I could find the error
Specifically in: /home/user/website/admin/js/vendor/tinymce/plugins/moxiemanager/classes/Util/EventDispatcher.php:118
In the method:
public function dispatch($sender, $name, $args) {
$name = strtolower($name);
if (isset($this->observers[$name])) {
$observers = $this->observers[$name];
$args->setSender($sender);
for ($i = 0, $l = count($observers); $i < $l; $i++) {
$value = $observers[$i][1]->$observers[$i][0]($args);
// Is stopped then break the loop
if ($value === false || $args->isStopped()) {
return $args;
}
}
}
return $args;
}
you must replace the following line:
$value = $observers[$i][1]->$observers[$i][0]($args);
For this:
$value = $observers[$i][1]->{$observers[$i][0]}($args);
PHP7 uses an abstract syntactic tree when analyzing the source files. Indirect access to variables, properties and methods will now be strictly evaluated from left to right.

Perl using Win32::PerfLib

I'm trying to understand Win32::PerfLib better, and I mustn't use Win32::PerfMon.
Two example I have questions about:
First example, is the classic from CPAN:
use Win32::PerfLib;
my $server = "";`enter code here`
Win32::PerfLib::GetCounterNames($server, \%counter);
%r_counter = map { $counter{$_} => $_ } keys %counter;
# retrieve the id for process object
$process_obj = $r_counter{Process};
# retrieve the id for the process ID counter
$process_id = $r_counter{'ID Process'};
# create connection to $server
$perflib = new Win32::PerfLib($server);
$proc_ref = {};
# get the performance data for the process object
$perflib->GetObjectList($process_obj, $proc_ref);
$perflib->Close();
$instance_ref = $proc_ref->{Objects}->{$process_obj}->{Instances};
foreach $p (sort keys %{$instance_ref})
{
$counter_ref = $instance_ref->{$p}->{Counters};
foreach $i (keys %{$counter_ref})
{
if($counter_ref->{$i}->{CounterNameTitleIndex} == $process_id)
{
printf( "% 6d %s\n", $counter_ref->{$i}->{Counter},
$instance_ref->{$p}->{Name}
);
}
}
}
Could someone explain in depth the 4th line?
I didn't understand why we use $_ for and
what it represents, although I read about it
but in this case I don't know. In addition
what's the $counter{$_} => $_ meaning?
Second question is from this code, which gets the cpu %
from perfmon:
use Win32::PerfLib;
($server) = #ARGV;
# only needed for PrintHash subroutine
#Win32::PerfLib::GetCounterNames($server, \%counter);
$processor = 238;
$proctime = 6;
$perflib = new Win32::PerfLib($server);
$proc_ref0 = {};
$proc_ref1 = {};
$perflib->GetObjectList($processor, $proc_ref0);
sleep 5;
$perflib->GetObjectList($processor, $proc_ref1);
$perflib->Close();
$instance_ref0 = $proc_ref0->{Objects}->{$processor}->{Instances};
$instance_ref1 = $proc_ref1->{Objects}->{$processor}->{Instances};
foreach $p (keys %{$instance_ref0})
{
$counter_ref0 = $instance_ref0->{$p}->{Counters};
$counter_ref1 = $instance_ref1->{$p}->{Counters};
foreach $i (keys %{$counter_ref0})
{
next if $instance_ref0->{$p}->{Name} eq "_Total";
if($counter_ref0->{$i}->{CounterNameTitleIndex} == $proctime)
{
$Numerator0 = $counter_ref0->{$i}->{Counter};
$Denominator0 = $proc_ref0->{PerfTime100nSec};
$Numerator1 = $counter_ref1->{$i}->{Counter};
$Denominator1 = $proc_ref1->{PerfTime100nSec};
$proc_time{$p} = (1- (($Numerator1 - $Numerator0) /
($Denominator1 - $Denominator0 ))) * 100;
printf "Instance $p: %.2f\%\n", $proc_time{$p};
}
}
}
Why does the programmer had to use the method "GetObjectList"
Two times and put the sleep method between them?
And why we can't just take the cpu percent like perfmon shows
and we have to make all those calculations?
Thanks in advance,
Fam Pam.
In this code:
Win32::PerfLib::GetCounterNames($server, \%counter);
%r_counter = map { $counter{$_} => $_ } keys %counter;
You are stroing the perfdata in %counter hash. The map in this case creates a reverse hash where the earlier values becomes keys.
Example:
from apple => 'fruit' to fruit => 'apple

for loop with fetchall_arrayref adding to an array

How can I loop through my arrayref and push row data into an array I have?
Here is my code that does it once without a loop but what I want is it to do it for each row and not sure the best approach:
my $data2 = $sth->fetchall_arrayref({});
my $excludeFirstName = $data2 ->[0]->{EXCL_FRSTNAME};
my $excludeLastName = $data2 ->[0]->{EXCL_LASTNAME};
my #excluded;
push (#excluded, $excludeFirstName." ".$excludeLastName);
my #excluded;
for my $row (#$data2) {
push #excluded, "$row->{EXCL_FRSTNAME} $row->{EXCL_LASTNAME}";
}
Or
my #excluded = map { "$row->{EXCL_FRSTNAME} $row->{EXCL_LASTNAME}" } #$data2;
If you don't need $data2 for anything else,
my #excluded;
while (my $row = $sth->fetch_hashref()) {
push #excluded, "$row->{EXCL_FRSTNAME} $row->{EXCL_LASTNAME}";
}
Or
my $sql = 'SELECT CONCAT(EXCL_FRSTNAME, EXCL_LASTNAME) FROM ...';
my $excluded = $dbh->selectcol_arrayref($sql);

Gitweb - name of last person to commit

I'm looking to add the name of the person who made the last commit to each project on the GitWeb project list, so instead of
14 min ago
it says something like
14 min ago (Someone's Name)
I've had a look through gitweb.cgi and found the point where the string is written (line 5488 in mine), but I don't really know how to proceed.
Has anyone already done this? Or can anyone offer a quick solution?
Thanks to simbabque for pointing me to git_get_last_activity. My solution (possibly sub-optimal, let me know if it is):
Change git_get_last_activity to
sub git_get_last_activity {
my ($path) = #_;
my $fd;
$git_dir = "$projectroot/$path";
open($fd, "-|", git_cmd(), 'for-each-ref',
'--format=%(committer)',
'--sort=-committerdate',
'--count=1',
'refs/heads') or return;
my $most_recent = <$fd>;
close $fd or return;
if (defined $most_recent &&
$most_recent =~ / (\d+) [-+][01]\d\d\d$/) {
my $bracket_position = rindex($most_recent, "<");
my $committer_name = substr($most_recent, 0, $bracket_position - 1);
my $timestamp = $1;
my $age = time - $timestamp;
return ($age, age_string($age), $committer_name);
}
return (undef, undef, undef);
}
Then search for where that is called later (should only be once) and change
($pr->{'age'}, $pr->{'age_string'}) = #activity;
to be
($pr->{'age'}, $pr->{'age_string'}, $pr->{'committer'}) = #activity;
Then go to git_project_list_rows and change
(defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n" .
to
(defined $pr->{'age_string'} ? $pr->{'age_string'} . ' (' . $pr->{'committer'} . ')' : "No commits") . "</td>\n" .

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.