| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987 |
- # $Id: 32_SYSSTAT.pm 10567 2016-01-18 21:34:09Z justme1968 $
- package main;
- use strict;
- use warnings;
- use Data::Dumper;
- my $SYSSTAT_hasSysStatistics = 1;
- my $SYSSTAT_hasSNMP = 1;
- my %SYSSTAT_diskTypes = (
- ".1.3.6.1.2.1.25.2.1.1" => 'Other',
- ".1.3.6.1.2.1.25.2.1.2" => 'Ram',
- ".1.3.6.1.2.1.25.2.1.3" => 'VirtualMemory',
- ".1.3.6.1.2.1.25.2.1.4" => 'FixedDisk',
- ".1.3.6.1.2.1.25.2.1.5" => 'RemovableDisk',
- ".1.3.6.1.2.1.25.2.1.6" => 'FloppyDisk',
- ".1.3.6.1.2.1.25.2.1.7" => 'CompactDisk',
- ".1.3.6.1.2.1.25.2.1.8" => 'RamDisk',
- ".1.3.6.1.2.1.25.2.1.9" => 'FlashMemory',
- ".1.3.6.1.2.1.25.2.1.10" => 'NetworkDisk',
- );
- sub
- SYSSTAT_Initialize($)
- {
- my ($hash) = @_;
- eval "use Sys::Statistics::Linux::LoadAVG";
- $SYSSTAT_hasSysStatistics = 0 if($@);
- eval "use Sys::Statistics::Linux::DiskUsage";
- $SYSSTAT_hasSysStatistics = 0 if($@);
- eval "use Net::SNMP";
- $SYSSTAT_hasSNMP = 0 if($@);
- $hash->{DefFn} = "SYSSTAT_Define";
- $hash->{UndefFn} = "SYSSTAT_Undefine";
- $hash->{GetFn} = "SYSSTAT_Get";
- $hash->{AttrFn} = "SYSSTAT_Attr";
- $hash->{AttrList} = "disable:1 disabledForIntervals raspberrycpufreq:1 raspberrytemperature:0,1,2 synologytemperature:0,1,2 stat:1 uptime:1,2 ssh_user ";
- $hash->{AttrList} .= " snmp:1 mibs:textField-long snmpVersion:1,2 snmpCommunity" if( $SYSSTAT_hasSNMP );
- $hash->{AttrList} .= " filesystems showpercent";
- $hash->{AttrList} .= " useregex:1" if( $SYSSTAT_hasSysStatistics );
- $hash->{AttrList} .= " $readingFnAttributes";
- }
- #####################################
- sub
- SYSSTAT_Define($$)
- {
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
- return "Usage: define <name> SYSSTAT [interval [interval_fs [host]]]" if(@a < 2);
- my $interval = 60;
- if(int(@a)>=3) { $interval = $a[2]; }
- if( $interval < 60 ) { $interval = 60; }
- my $interval_fs = $interval * 60;
- if(int(@a)>=4) { $interval_fs = $a[3]; }
- if( $interval_fs < $interval ) { $interval_fs = $interval; }
- if( $interval_fs == $interval ) { $interval_fs = undef; }
- my $host = $a[4] if(int(@a)>=5);;
- delete( $hash->{INTERVAL_FS} );
- delete( $hash->{HOST} );
- $hash->{"HAS_Sys::Statistics"} = $SYSSTAT_hasSysStatistics;
- $hash->{"HAS_Net::SNMP"} = $SYSSTAT_hasSNMP;
- $hash->{STATE} = "Initialized";
- $hash->{INTERVAL} = $interval;
- $hash->{INTERVAL_FS} = $interval_fs if( defined( $interval_fs ) );
- $hash->{HOST} = $host if( defined( $host ) );
- $hash->{interval_fs} = $interval_fs;
- SYSSTAT_InitSys( $hash ) if( $SYSSTAT_hasSysStatistics );
- SYSSTAT_InitSNMP( $hash ) if( $SYSSTAT_hasSNMP );
- RemoveInternalTimer($hash);
- InternalTimer(gettimeofday()+$hash->{INTERVAL}, "SYSSTAT_GetUpdate", $hash, 0);
- return undef;
- }
- sub
- SYSSTAT_InitSys($)
- {
- my ($hash) = @_;
- return if( !$SYSSTAT_hasSysStatistics );
- if( defined($hash->{HOST}) ) {
- my $cmd = qx(which ssh);
- chomp( $cmd );
- my $user = AttrVal($hash->{NAME}, "ssh_user", undef );
- $cmd .= ' ';
- $cmd .= $user."\@" if( defined($user) );
- $cmd .= $hash->{HOST}." df -kP 2>/dev/null";
- $hash->{loadavg} = Sys::Statistics::Linux::LoadAVG->new;
- $hash->{diskusage} = Sys::Statistics::Linux::DiskUsage->new( cmd => { path => '',
- df => $cmd } );
- } else {
- $hash->{loadavg} = Sys::Statistics::Linux::LoadAVG->new;
- $hash->{diskusage} = Sys::Statistics::Linux::DiskUsage->new;
- }
- }
- sub
- SYSSTAT_InitSNMP($)
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- delete( $hash->{session} );
- return if( !$SYSSTAT_hasSNMP );
- my $host = "localhost";
- my $community = "public";
- $host = $hash->{HOST} if( defined($hash->{HOST} ) );
- my ( $session, $error ) = Net::SNMP->session(
- -hostname => $host,
- -community => AttrVal($name,"snmpCommunity","public"),
- -port => 161,
- -version => AttrVal($name,"snmpVersion",1),
- );
- if( $error ) {
- Log3 $name, 2, "$name: $error";
- } elsif ( !defined($session) ) {
- Log3 $name, 2, "$name: can't connect to host $host";
- } else {
- $session->timeout(3);
- $hash->{session} = $session;
- }
- }
- sub
- SYSSTAT_Undefine($$)
- {
- my ($hash, $arg) = @_;
- RemoveInternalTimer($hash);
- return undef;
- }
- sub
- SYSSTAT_Get($@)
- {
- my ($hash, @a) = @_;
- my $name = $a[0];
- return "$name: get needs at least one parameter" if(@a < 2);
- my $cmd= $a[1];
- if($cmd eq "filesystems") {
- my $ret;
- if( $hash->{USE_SNMP} && defined($hash->{session}) ) {
- my $types = SYSSTAT_readOIDs($hash,".1.3.6.1.2.1.25.2.3.1.2");
- my $response = SYSSTAT_readOIDs($hash,".1.3.6.1.2.1.25.2.3.1.3");
- foreach my $oid ( sort { ($a =~/\.(\d+)$/)[0] <=> ($b =~/\.(\d+)$/)[0]} keys %$response ) {
- $ret .= "\n" if( $ret );
- my $id = ($oid =~/\.(\d+)$/)[0];
- $ret .= $id ." <= ". $response->{$oid} ." (". $SYSSTAT_diskTypes{$types->{".1.3.6.1.2.1.25.2.3.1.2.$id"}} .")";
- }
- $ret = "<id> => <filesystem>\n$ret" if( $ret );
- } elsif(defined($hash->{diskusage})) {
- my $filesystems = $hash->{diskusage}->get;
- $ret = "<filesystem> <= <mountpoint>";
- foreach my $filesystem (keys %$filesystems ) {
- $ret .= "\n" if( $ret );
- $ret .= $filesystem ." <= ". $filesystems->{$filesystem}->{mountpoint};
- }
- }
- return $ret;
- } elsif( $cmd eq "update" ) {
- $hash->{LOCAL} = 1;
- SYSSTAT_GetUpdate( $hash );
- delete $hash->{LOCAL};
- return;
- }
- return "Unknown argument $cmd, choose one of update:noArg filesystems:noArg";
- }
- sub
- SYSSTAT_Attr($$$)
- {
- my ($cmd, $name, $attrName, $attrVal) = @_;
- $attrVal= "" unless defined($attrVal);
- my $orig = $attrVal;
- $attrVal = "1" if($attrName eq "snmp");
- $attrVal = "1" if($attrName eq "useregex");
- $attrVal = "1" if($attrName eq "showpercent");
- $attrVal = "1" if($attrName eq "raspberrycpufreq");
- my $hash = $defs{$name};
- if( $attrName eq "filesystems") {
- my @filesystems = split(",",$attrVal);
- @{$hash->{filesystems}} = @filesystems;
- } elsif( $attrName eq "ssh_user") {
- $attr{$name}{$attrName} = $attrVal;
- SYSSTAT_InitSys( $hash ) if( $SYSSTAT_hasSysStatistics );
- } elsif( $attrName eq "snmpVersion" && $SYSSTAT_hasSNMP ) {
- $hash->{$attrName} = $attrVal;
- SYSSTAT_InitSNMP( $hash );
- } elsif( $attrName eq "snmpCommunity" && $SYSSTAT_hasSNMP ) {
- $hash->{$attrName} = $attrVal;
- SYSSTAT_InitSNMP( $hash );
- } elsif ($attrName eq "snmp" && $SYSSTAT_hasSNMP ) {
- if( $cmd eq "set" && $attrVal ne "0" ) {
- $hash->{USE_SNMP} = $attrVal;
- SYSSTAT_InitSNMP( $hash );
- } else {
- delete $hash->{USE_SNMP};
- }
- }
- if( $cmd eq "set" ) {
- if( $orig ne $attrVal ) {
- $attr{$name}{$attrName} = $attrVal;
- return $attrName ." set to ". $attrVal;
- }
- }
- return;
- }
- sub SYSSTAT_getLoadAVG($);
- sub SYSSTAT_getPiTemp($);
- sub SYSSTAT_getUptime($);
- sub
- SYSSTAT_GetUpdate($)
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- if(!$hash->{LOCAL}) {
- RemoveInternalTimer($hash);
- InternalTimer(gettimeofday()+$hash->{INTERVAL}, "SYSSTAT_GetUpdate", $hash, 0);
- return if( IsDisabled($name) > 0 );
- }
- my $load = SYSSTAT_getLoadAVG( $hash );
- readingsBeginUpdate($hash);
- my $state = undef;
- $state = $load->{state} if( defined($load->{state}) );
- $state = $load->{avg_1} . " " . $load->{avg_5} . " " . $load->{avg_15} if( !$state && defined($load->{avg_1}) );
- readingsBulkUpdate($hash,"state",$state);
- readingsBulkUpdate($hash,"load",$load->{avg_1});
- my $do_diskusage = 1;
- if( defined($hash->{INTERVAL_FS} ) ) {
- $do_diskusage = 0;
- $hash->{interval_fs} -= $hash->{INTERVAL};
- if( $hash->{interval_fs} <= 0 ) {
- $do_diskusage = 1;
- $hash->{interval_fs} += $hash->{INTERVAL_FS};
- }
- }
- if( $do_diskusage
- && $#{$hash->{filesystems}} >= 0 ) {
- if( $hash->{USE_SNMP} && defined($hash->{session}) ) {
- my $showpercent = AttrVal($name, "showpercent", "") ne "";
- my @snmpoids = ();
- for my $id (@{$hash->{filesystems}}) {
- push @snmpoids, sprintf( ".1.3.6.1.2.1.25.2.3.1.3.%i", $id );
- push @snmpoids, sprintf( ".1.3.6.1.2.1.25.2.3.1.4.%i", $id ) if( !$showpercent );
- push @snmpoids, sprintf( ".1.3.6.1.2.1.25.2.3.1.5.%i", $id );
- push @snmpoids, sprintf( ".1.3.6.1.2.1.25.2.3.1.6.%i", $id );
- }
- my $response = SYSSTAT_readOIDs($hash,\@snmpoids);
- if( $response ) {
- for my $id (@{$hash->{filesystems}}) {
- my $unit = $response->{sprintf( ".1.3.6.1.2.1.25.2.3.1.4.%i", $id )};
- my $free = $response->{sprintf( ".1.3.6.1.2.1.25.2.3.1.5.%i", $id )} - $response->{sprintf( ".1.3.6.1.2.1.25.2.3.1.6.%i", $id )};
- if( $showpercent ) {
- $free = 100 * $response->{sprintf( ".1.3.6.1.2.1.25.2.3.1.6.%i", $id )} / $response->{sprintf( ".1.3.6.1.2.1.25.2.3.1.5.%i", $id )};
- $free = sprintf( "%.1f", $free );
- } else {
- $free *= $unit;
- }
- my $name = $response->{sprintf( ".1.3.6.1.2.1.25.2.3.1.3.%i", $id )};
- if( $name =~ m/^([[:alpha:]]:\\)/ ) {
- $name = $1;
- $name =~ s.\\./.g;
- } else {
- $name =~ s/ //g;
- }
- readingsBulkUpdate($hash,$name,$free);
- }
- }
- } elsif( defined($hash->{diskusage} ) ) {
- my $usage = $hash->{diskusage}->get;
- my $type = 'free';
- if( AttrVal($name, "showpercent", "") ne "" ) {
- $type = 'usageper';
- }
- if( AttrVal($name, "useregex", "") eq "" ) {
- for my $filesystem (@{$hash->{filesystems}}) {
- my $fs = $usage->{$filesystem};
- readingsBulkUpdate($hash,$fs->{mountpoint},$fs->{$type});
- }
- } else {
- for my $filesystem (@{$hash->{filesystems}}) {
- foreach my $key (keys %$usage) {
- if( $key =~ /$filesystem/ ) {
- my $fs = $usage->{$key};
- readingsBulkUpdate($hash,$fs->{mountpoint},$fs->{$type});
- }
- }
- }
- }
- }
- }
- if( AttrVal($name, "raspberrytemperature", 0) > 0 ) {
- my $temp = SYSSTAT_getPiTemp($hash);
- if( $temp > 0 && $temp < 200 ) {
- if( AttrVal($name, "raspberrytemperature", 0) eq 2 ) {
- $temp = sprintf( "%.1f", (3 * ReadingsVal($name,"temperature",$temp) + $temp ) / 4 );
- }
- readingsBulkUpdate($hash,"temperature",$temp);
- }
- } elsif( AttrVal($name, "synologytemperature", 0) > 0 ) {
- my $temp = SYSSTAT_getSynoTemp($hash);
- if( $temp && $temp > 0 && $temp < 200 ) {
- if( AttrVal($name, "synologytemperature", 0) eq 2 ) {
- $temp = sprintf( "%.1f", (3 * ReadingsVal($name,"temperature",$temp) + $temp ) / 4 );
- }
- readingsBulkUpdate($hash,"temperature",$temp);
- }
- }
- if( $hash->{USE_SNMP} && defined($hash->{session}) ) {
- if( my $mibs = AttrVal($name, "mibs", undef) ) {
- my @snmpoids;
- foreach my $entry (split(/[ ,\n]/, $mibs)) {
- next if( !$entry );
- my($mib,undef) = split(':', $entry );
- next if( !$mib );
- push @snmpoids, $mib;
- }
- my $response = SYSSTAT_readOIDs($hash,\@snmpoids);
- foreach my $entry (split(/[ ,\n]/, $mibs)) {
- next if( !$entry );
- my($mib,$reading) = split(':', $entry );
- next if( !$mib );
- next if( !$reading );
- my $result = $response->{$mib};
- readingsBulkUpdate($hash,$reading,$result);
- }
- }
- }
- if( AttrVal($name, "raspberrycpufreq", 0) > 0 ) {
- my $freq = SYSSTAT_getPiFreq($hash);
- readingsBulkUpdate($hash,"cpufreq",$freq);
- }
- if( AttrVal($name, "stat", 0) > 0 ) {
- my @percent = SYSSTAT_getStat($hash);
- if( @percent ) {
- #my($user,$nice,$system,$idle,$iowait,$irq,$softirq,$steal,$guest,$guest_nice) = @percent;
- readingsBulkUpdate($hash,"user", $percent[0]);
- readingsBulkUpdate($hash,"system", $percent[2]);
- readingsBulkUpdate($hash,"idle", $percent[3]);
- readingsBulkUpdate($hash,"iowait", $percent[4]);
- }
- }
- if( AttrVal($name, "uptime", 0) > 0 ) {
- my $uptime = SYSSTAT_getUptime($hash);
- readingsBulkUpdate($hash,"uptime",$uptime);
- }
- readingsEndUpdate($hash,defined($hash->{LOCAL} ? 0 : 1));
- }
- sub
- SYSSTAT_getLoadAVG($ )
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- if( $hash->{USE_SNMP} && defined($hash->{session}) ) {
- my @snmpoids = ( ".1.3.6.1.4.1.2021.10.1.3.1", ".1.3.6.1.4.1.2021.10.1.3.2", ".1.3.6.1.4.1.2021.10.1.3.3" );
- my $response = SYSSTAT_readOIDs($hash,\@snmpoids);
- if( !$response ) {
- my $response = SYSSTAT_readOIDs($hash,".1.3.6.1.2.1.25.3.3.1.2");
- my $avg = "";
- my %lavg = ();
- my $load = 0;
- foreach my $key (keys %$response) {
- $avg .= "," if( $avg ne "" );
- $avg .= $response->{$key};
- $load += $response->{$key} / 100;
- }
- $lavg{avg_1} = $load if( $avg ne "" );
- $lavg{state} = $avg if( $avg ne "" );
- return \%lavg;
- }
- my %lavg = ();
- $lavg{avg_1} = $response->{".1.3.6.1.4.1.2021.10.1.3.1"};
- $lavg{avg_5} = $response->{".1.3.6.1.4.1.2021.10.1.3.2"};
- $lavg{avg_15} = $response->{".1.3.6.1.4.1.2021.10.1.3.3"};
- return \%lavg;
- }
- return undef if( !defined($hash->{loadavg}) );
- if( defined($hash->{HOST}) ) {
- no strict;
- no warnings 'redefine';
- local *Sys::Statistics::Linux::LoadAVG::get = sub {
- my $self = shift;
- my $class = ref $self;
- my $file = $self->{files};
- my %lavg = ();
- my $cmd = qx(which ssh);
- chomp( $cmd );
- my $user = AttrVal($hash->{NAME}, "ssh_user", undef );
- $cmd .= ' ';
- $cmd .= $user."\@" if( defined($user) );
- $cmd .= $hash->{HOST}." cat /proc/loadavg 2>/dev/null";
- my $fh;
- if( open($fh, "$cmd|" ) ) {
- ( $lavg{avg_1}
- , $lavg{avg_5}
- , $lavg{avg_15}
- ) = (split /\s+/, <$fh>)[0..2];
- close($fh);
- }
- return \%lavg;
- };
- return $hash->{loadavg}->get;
- }
- return $hash->{loadavg}->get;
- }
- sub
- SYSSTAT_readOIDs($$)
- {
- my ($hash,$snmpoids) = @_;
- my $name = $hash->{NAME};
- return undef if( !defined($hash->{session}) );
- my $response;
- if( ref($snmpoids) eq "ARRAY" ) {
- $response = $hash->{session}->get_request( @{$snmpoids} );
- Log3 $name, 4, "$name: got empty result from snmp query ".$hash->{session}->error() if( !$response );
- } else {
- $response = $hash->{session}->get_next_request($snmpoids);
- my @snmpoids = ();
- my @nextid = keys %$response;
- while ( @nextid && $nextid[0] && $nextid[0] =~ m/^$snmpoids/ ) {
- push( @snmpoids, $nextid[0] );
- $response = $hash->{session}->get_next_request( $nextid[0] );
- @nextid = keys %$response;
- }
- $response = $hash->{session}->get_request( @snmpoids );
- #Log3 $name, 4, "$name: got empty result from snmp query ".$hash->{session}->error() if( !$response );
- }
- return $response;
- }
- sub
- SYSSTAT_readCmd($$$)
- {
- my ($hash,$command,$default) = @_;
- my $value = $default;
- if( defined($hash->{HOST}) ) {
- my $cmd = qx(which ssh);
- chomp( $cmd );
- my $user = AttrVal($hash->{NAME}, "ssh_user", undef );
- $cmd .= ' ';
- $cmd .= $user."\@" if( defined($user) );
- $cmd .= $hash->{HOST}." $command 2>/dev/null";
- if( open(my $fh, "$cmd|" ) ) {
- $value = <$fh>;
- close($fh);
- }
- } else {
- if( open( my $fh, "$command|" ) )
- {
- $value = <$fh>;
- close($fh);
- }
- }
- return $value;
- }
- sub
- SYSSTAT_readFile($$$)
- {
- my ($hash,$filename,$default) = @_;
- my $value = $default;
- if( defined($hash->{HOST}) ) {
- my $cmd = qx(which ssh);
- chomp( $cmd );
- my $user = AttrVal($hash->{NAME}, "ssh_user", undef );
- $cmd .= ' ';
- $cmd .= $user."\@" if( defined($user) );
- $cmd .= $hash->{HOST}." cat ". $filename ." 2>/dev/null";
- if( open(my $fh, "$cmd|" ) ) {
- $value = <$fh>;
- close($fh);
- }
- } else {
- if( open( my $fh, '<', $filename ) )
- {
- $value = <$fh>;
- close($fh);
- }
- }
- return $value;
- }
- sub
- SYSSTAT_getPiTemp($)
- {
- my ($hash) = @_;
- my $temp = SYSSTAT_readFile($hash,"/sys/class/thermal/thermal_zone0/temp",-1);
- return $temp / 1000;
- }
- sub
- SYSSTAT_getSynoTemp($)
- {
- my ($hash) = @_;
- my $temp = -1;
- if( $hash->{USE_SNMP} && defined($hash->{session}) ) {
- my @snmpoids = ( ".1.3.6.1.4.1.6574.1.2.0" );
- my $response = SYSSTAT_readOIDs($hash,\@snmpoids);
- $temp = $response->{".1.3.6.1.4.1.6574.1.2.0"};
- }
- return $temp;
- }
- sub
- SYSSTAT_getPiFreq($)
- {
- my ($hash) = @_;
- my $freq = SYSSTAT_readFile($hash,"/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq",0);
- return $freq / 1000;
- }
- sub
- SYSSTAT_getUptime($)
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- if( $hash->{USE_SNMP} && defined($hash->{session}) ) {
- my @snmpoids = ( ".1.3.6.1.2.1.25.1.1.0" );
- my $response = SYSSTAT_readOIDs($hash,\@snmpoids);
- my $uptime = $response->{".1.3.6.1.2.1.25.1.1.0"};
- if( AttrVal($name, "uptime", 0) == 2 ) {
- if( $uptime && $uptime =~ m/(\d+)\s\D+,\s(\d+):(\d+):(\d+)/ ) {
- my $days = $1?$1:0;
- my $hours = $2;
- my $minutes = $3;
- my $seconds = $4;
- $uptime = $days * 24;
- $uptime += $hours;
- $uptime *= 60;
- $uptime += $minutes;
- $uptime *= 60;
- $uptime += $seconds;
- }
- }
- return $uptime;
- }
- my $uptime = SYSSTAT_readFile($hash,"/proc/uptime","");
- if($uptime) {
- $uptime = $1 if ( $uptime && $uptime =~ /^\s*([0-9.]+)\s+([0-9.]+)/ );
- if( AttrVal($name, "uptime", 0) != 2 ) {
- # cut off partial seconds
- $uptime = int( $uptime );
- my $seconds = $uptime % 60;
- $uptime = int($uptime / 60);
- my $minutes = $uptime % 60;
- $uptime = int($uptime / 60);
- my $hours = $uptime % 24;
- my $days = int($uptime / 24);
- $uptime = sprintf( "%d days, %d:%.2d", $days, $hours, $minutes);
- Log3 $name, 4, "$name: uptime returned :$uptime: via proc-uptime file "; # JVI
- }
- # fallback if by any reason parsing /proc/uptime does not work
- } else {
- my $uptime = SYSSTAT_readCmd($hash,"uptime",0);
- ############# match uptime time statement with the different formats seen on linux
- # examples
- # 18:52:21 up 26 days, 21:08, 2 users, load average: 0.04, 0.03, 0.05
- # 18:52:21 up 26 days, 55 min, 1 user, load average: 0.05, 0.05, 0.05
- # 18:52:21 up 55 min, 1 user, load average: 0.05, 0.05, 0.05
- # 18:52:21 up 21:08, 1 user, load average: 0.05, 0.05, 0.05
- #
- # complex expression to match only the time parts of the uptime result
- # $1 is complete up time information of uptime result
- # $2 is # days part of the uptime
- # $3 just the # from the "# days"" part or nothing if no days are given
- # $4 is complete hour/minutes or # min information
- # $5 is hours part if hours:min are given
- # $6 is minutes part if hours:min are given
- # $7 is minutes if # min is given
- $uptime = $1 if ( $uptime && $uptime =~ m/[[:alpha:]]{2}\s*(((\d*)\s*[[:alnum:]]*,?)?\s+((\d+):(\d+)|(\d+)\s+[[:alpha:]]+in[[:alpha:]]*)),?/ );
- $uptime = "0 days, $uptime" if( $uptime && !$2);
- if( AttrVal($name, "uptime", 0) == 2 ) {
- my $days = $3?$3:0;
- my $hours = $5?$5:0;
- my $minutes = $6?$6:$7;
- $uptime = $days * 24;
- $uptime += $hours;
- $uptime *= 60;
- $uptime += $minutes;
- $uptime *= 60;
- }
- Log3 $name, 4, "$name: uptime returned :$uptime: via cmdline "; # JVI
- }
- return $uptime;
- }
- sub
- SYSSTAT_getStat($)
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- if( $hash->{USE_SNMP} && defined($hash->{session}) ) {
- my @snmpoids = ( ".1.3.6.1.4.1.2021.11.9.0", ".1.3.6.1.4.1.2021.11.10.0", ".1.3.6.1.4.1.2021.11.11.0" );
- my $response = SYSSTAT_readOIDs($hash,\@snmpoids);
- my @percent = ( $response->{".1.3.6.1.4.1.2021.11.9.0"}, # user
- undef,
- $response->{".1.3.6.1.4.1.2021.11.10.0"}, # system
- $response->{".1.3.6.1.4.1.2021.11.11.0"} ); # idle
- return @percent;
- }
- my $line = SYSSTAT_readFile($hash,"/proc/stat","");
- #my($user,$nice,$system,$idle,$iowait,$irq,$softirq,$steal,$guest,$guest_nice) = split( " ", $Line );
- my($dummy,@values) = split( " ", $line );
- if( !defined($hash->{values}) ) {
- $hash->{values} = \@values;
- return undef;
- } else {
- my @diff = map { $values[$_] - $hash->{values}->[$_] } 0 .. $#values;
- $hash->{values} = \@values;
- my $sum = 0;
- $sum += $_ for @diff;
- my @percent = map { int($diff[$_]*1000 / $sum)/10 } 0 .. $#values;
- return @percent;
- }
- }
- 1;
- =pod
- =item device
- =begin html
- <a name="SYSSTAT"></a>
- <h3>SYSSTAT</h3>
- <ul>
- Provides system statistics for the host FHEM runs on or a remote Linux system that is reachable by preconfigured passwordless ssh access.<br><br>
- Notes:
- <ul>
- <li>This module needs <code>Sys::Statistics::Linux</code> on Linux.<br>
- It can be installed with '<code>cpan install Sys::Statistics::Linux</code>'<br>
- or on debian with '<code>apt-get install libsys-statistics-linux-perl</code>'</li>
- <li>To monitor a target by snmp <code>Net::SNMP</code> hast to be installed.<br></li>
- <li>To plot the load values the following code can be used:
- <PRE>
- define sysstatlog FileLog /usr/local/FHEM/var/log/sysstat-%Y-%m.log sysstat
- attr sysstatlog nrarchive 1
- define svg_sysstat SVG sysstatlog:sysstat:CURRENT
- attr wl_sysstat label "Load Min: $data{min1}, Max: $data{max1}, Aktuell: $data{currval1}"
- attr wl_sysstat room System
- </PRE></li>
- <li>to match the root filesystem (mount point '/') in diskusage plots use
- '<code>#FileLog 4:/\x3a:0:</code>' or '<code>#FileLog 4:\s..\s:0:</code>'
- and <b>not</b> '<code>#FileLog 4:/:0:</code>' as the later will match all mount points</li>.
- </ul>
- <a name="SYSSTAT_Define"></a>
- <b>Define</b>
- <ul>
- <code>define <name> SYSSTAT [<interval> [<interval_fs>] [<host>]]</code><br>
- <br>
- Defines a SYSSTAT device.<br><br>
- The load is updated every <interval> seconds. The default and minimum is 60.<br><br>
- The diskusage is updated every <interval_fs> seconds. The default is <interval>*60 and the minimum is 60.
- <interval_fs> is only aproximated and works best if <interval_fs> is an integral multiple of <interval>.<br><br>
- If <host> is given it has to be accessible by ssh without the need for a password.
- Examples:
- <ul>
- <code>define sysstat SYSSTAT</code><br>
- <code>define sysstat SYSSTAT 300</code><br>
- <code>define sysstat SYSSTAT 60 600</code><br>
- </ul>
- </ul><br>
- <a name="SYSSTAT_Readings"></a>
- <b>Readings</b>
- <ul>
- <li>load<br>
- the 1 minute load average (for windows targets monitored by snmp aproximated value</li>
- <li>state<br>
- the 1, 5 and 15 minute load averages (or windows targets monitored by snmp the per cpu utilization)</li>
- <li>user,system,idle,iowait<br>
- respective percentage of systemutilization (linux targets only)</li>
- <li><mountpoint><br>
- free bytes for <mountpoint></li>
- </ul><br>
- <a name="SYSSTAT_Get"></a>
- <b>Get</b>
- <ul>
- <code>get <name> <value></code>
- <br><br>
- where <code>value</code> is one of<br><br>
- <li>filesystems<br>
- Lists the filesystems that can be monitored.</li>
- </ul><br>
- <a name="SYSSTAT_Attr"></a>
- <b>Attributes</b>
- <ul>
- <li>disable<br>
- keep timers running but disable collection of statistics.</li>
- <li>filesystems<br>
- List of comma separated filesystems (not mountpoints) that should be monitored.<br>
- Examples:
- <ul>
- <code>attr sysstat filesystems /dev/md0,/dev/md2</code><br>
- <code>attr sysstat filesystems /dev/.*</code><br>
- <code>attr sysstat filesystems 1,3,5</code><br>
- </ul></li></lu>
- <li>disabledForIntervals HH:MM-HH:MM HH:MM-HH-MM...</li>
- <li>mibs<br>
- space separated list of <mib>:<reding> pairs that sould be polled.</li>
- <li>showpercent<br>
- If set the usage is shown in percent. If not set the remaining free space in bytes is shown.</li>
- <li>snmp<br>
- 1 -> use snmp to monitor load, uptime and filesystems (including physical and virtual memory)</li>
- <li>stat<br>
- 1 -> monitor user,system,idle and iowait percentage of system utilization (available only for linux targets)</li>
- <li>raspberrytemperature<br>
- If set and > 0 the raspberry pi on chip termal sensor is read.<br>
- If set to 2 a geometric average over the last 4 values is created.</li>
- <li>synologytemperature<br>
- If set and > 0 the main temperaure of a synology diskstation is read. requires snmp.<br>
- If set to 2 a geometric average over the last 4 values is created.</li>
- <li>raspberrycpufreq<br>
- If set and > 0 the raspberry pi on chip termal sensor is read.</li>
- <li>uptime<br>
- If set and > 0 the system uptime is read.<br>
- If set to 2 the uptime is displayed in seconds.</li>
- <li>useregex<br>
- If set the entries of the filesystems list are treated as regex.</li>
- <li>ssh_user<br>
- The username for ssh remote access.</li>
- <li>snmpVersion</li>
- <li>snmpCommunity</li>
- <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
- </ul>
- </ul>
- =end html
- =begin html_DE
- <a name="SYSSTAT"></a>
- <h3>SYSSTAT</h3>
- <ul>
- Das Modul stellt Systemstatistiken für den Rechner, auf dem FHEM läuft bzw.
- für ein entferntes Linux System, das per vorkonfiguriertem ssh Zugang ohne Passwort
- erreichbar ist, zur Vefügung.<br><br>
- Notes:
- <ul>
- <li>Dieses Modul benötigt <code>Sys::Statistics::Linux</code> für Linux.<br>
- Es kann mit '<code>cpan install Sys::Statistics::Linux</code>'<br>
- bzw. auf Debian mit '<code>apt-get install libsys-statistics-linux-perl</code>'
- installiert werden.</li>
- <li>Um einen Zielrechner mit snmp zu überwachen, muss
- <code>Net::SNMP</code> installiert sein.<br></li>
- <li>Um die Lastwerte zu plotten, kann der folgende Code verwendet werden:
- <pre>
- define sysstatlog FileLog /usr/local/FHEM/var/log/sysstat-%Y-%m.log sysstat
- attr sysstatlog nrarchive 1
- define svg_sysstat SVG sysstatlog:sysstat:CURRENT
- attr wl_sysstat label "Load Min: $data{min1}, Max: $data{max1}, Aktuell: $data{currval1}"
- attr wl_sysstat room System
- </pre></li>
- <li>Um das Wurzel-Dateisystem (Mountpunkt '/') bei Plots der Plattennutzung zu erhalten,
- sollte dieser Code '<code>#FileLog 4:/\x3a:0:</code>' bzw. '<code>#FileLog 4:\s..\s:0:</code>'
- und <b>nicht</b> dieser Code '<code>#FileLog 4:/:0:</code>' verwendet werden, da der letztere
- alle Mountpunkte darstellt.</li>.
- </ul>
- <a name="SYSSTAT_Define"></a>
- <b>Define</b>
- <ul>
- <code>define <name> SYSSTAT [<interval> [<interval_fs>] [<host>]]</code><br>
- <br>
- definiert ein SYSSTAT Device.<br><br>
- Die (Prozessor)last wird alle <interval> Sekunden aktualisiert. Standard bzw. Minimum ist 60.<br><br>
- Die Plattennutzung wird alle <interval_fs> Sekunden aktualisiert. Standardwert ist <interval>*60
- und Minimum ist 60.
- <interval_fs> wird nur angenähert und funktioniert am Besten, wenn <interval_fs>
- ein ganzzahliges Vielfaches von <interval> ist.<br><br>
- Wenn <host> angegeben wird, muss der Zugang per ssh ohne Passwort möglich sein.<br><br>
- Beispiele:
- <ul>
- <code>define sysstat SYSSTAT</code><br>
- <code>define sysstat SYSSTAT 300</code><br>
- <code>define sysstat SYSSTAT 60 600</code>
- </ul>
- </ul><br>
- <a name="SYSSTAT_Readings"></a>
- <b>Readings</b>
- <ul>
- <li>load<br>
- die durchschnittliche (Prozessor)last der letzten 1 Minute (für Windows Rechner mit
- snmp angenähertem Wert)</li>
- <li>state<br>
- die durchschnittliche (Prozessor)last der letzten 1, 5 und 15 Minuten (für Windows
- Rechner die Nutzung pro CPU via snmp ermittelt)</li>
- <li>user, system, idle, iowait<br>
- den Prozentsatz der entsprechenden Systemlast (nur für Linux Systeme)</li>
- <li><mountpoint><br>
- Anzahl der freien Bytes für <mountpoint></li>
- </ul><br>
- <a name="SYSSTAT_Get"></a>
- <b>Get</b>
- <ul>
- <code>get <name> <value></code>
- <br><br>
- Werte für <code>value</code> sind<br><br>
- <li>filesystems<br>
- zeigt die Dateisysteme an, die überwacht werden können.</li>
- </ul><br>
- <a name="SYSSTAT_Attr"></a>
- <b>Attributes</b>
- <ul>
- <li>disable<br>
- lässt die Timer weiterlaufen, aber stoppt die Speicherung der Daten.</li>
- <li>filesystems<br>
- Liste mit Komma getrennten Dateisystemen (nicht Mountpunkten) die überwacht
- werden sollen.<br>
- Beispiele:
- <ul>
- <code>attr sysstat filesystems /dev/md0,/dev/md2</code><br>
- <code>attr sysstat filesystems /dev/.*</code><br>
- <code>attr sysstat filesystems 1,3,5</code><br>
- </ul></li>
- <li>mibs<br>
- Leerzeichen getrennte Liste aus <mib>:<reding> Paaren die abgefragt werden sollen.</li>
- <li>showpercent<br>
- Wenn gesetzt, wird die Nutzung in Prozent angegeben. Wenn nicht gesetzt, wird der verfübare
- Platz in Bytes angezeigt.</li>
- <li>snmp<br>
- 1 -> snmp wird verwendet, um Last, Einschaltzeit und Dateisysteme (inkl. physikalischem und
- virtuellem Speicher) zu überwachen</li>
- <li>stat<br>
- 1 -> überwacht Prozentsatz der user, system, idle und iowait Last
- (nur auf Linux Systemen verfügbar)</li>
- <li>raspberrytemperature<br>
- Wenn gesetzt und > 0 wird der Temperatursensor auf dem Raspberry Pi ausgelesen.<br>
- Wenn Wert 2 ist, wird ein geometrischer Durchschnitt der letzten 4 Werte dargestellt.</li>
- <li>synologytemperature<br>
- Wenn gesetzt und > 0 wird die Temperatur einer Synology Diskstation ausgelesen (erfordert snmp).<br>
- Wenn Wert 2 ist, wird ein geometrischer Durchschnitt der letzten 4 Werte dargestellt.</li>
- <li>raspberrycpufreq<br>
- Wenn gesetzt und > 0 wird die Raspberry Pi CPU Frequenz ausgelesen.</li>
- <li>uptime<br>
- Wenn gesetzt und > 0 wird die Betriebszeit (uptime) des Systems ausgelesen.<br>
- Wenn Wert 2 ist, wird die Betriebszeit (uptime) in Sekunden angezeigt.</li>
- <li>useregex<br>
- Wenn Wert gesetzt, werden die Einträge der Dateisysteme als regex behandelt.</li>
- <li>ssh_user<br>
- Der Username für den ssh Zugang auf dem entfernten Rechner.</li>
- <li>snmpVersion</li>
- <li>snmpCommunity</li>
- <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
- </ul>
- </ul>
- =end html_DE
- =cut
|