You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
4.4 KiB
Perl

#!/usr/bin/perl
use 5.010;
use utf8;
use strict;
use warnings;
use Carp;
use Sys::Filesystem ();
use Filesys::Df qw(df);
use IO::Socket;
my @ignoreformats = qw(
tmpfs sysfs devtmpfs devpts proc binfmt_misc
fusectl fuse.gvfsd-fuse fuse.vmware-vmblock
debugfs securityfs swap iso9660 udf cgroup
hugetlbfs mqueue pstore selinuxfs configfs
nfsd rpc_pipefs tracefs
);
my @ignorepaths = (qr(/var/lib/docker/));
my $color_ok = "#78af78";
my $color_warn = "#ffff00";
my $color_crit = "#ff0000";
my $color_unknown = "#ffa500";
# check_mk based magic df kungfu
sub magic_level {
my ($level, $size) = @_;
my $normsize = 20.0; # GB
my $exp = 0.6;
my $hgb_size = $size / $normsize;
my $felt_size = $hgb_size ** $exp;
my $scale = $felt_size / $hgb_size;
my $new_level = 1 - ((1 - $level) * $scale);
if ($new_level < 0.8) {
$new_level = 0.8;
}
return $new_level;
}
sub conky_fs {
my $fs = Sys::Filesystem->new();
my @filesystems = $fs->filesystems();
# determine longest mount point path
my $mlength = 5;
for my $f (@filesystems) {
my $mount_point = $fs->mount_point($f);
if (length($mount_point) > $mlength) {
$mlength = length($mount_point);
}
}
for my $f (@filesystems) {
my $mount_point = $fs->mount_point($f);
my $format = $fs->format($f);
next if grep { /^$format$/xsm } @ignoreformats;
next if grep { $mount_point =~ $_ } @ignorepaths;
my $df = df($mount_point, 1024); # 1k blocks
my $blocks = $df->{blocks};
if (!defined($blocks)) { $blocks = 1 };
my $size = $blocks/(1024*1024);
my $level_warn = magic_level(0.80, $size) * 100;
my $level_crit = magic_level(0.90, $size) * 100;
# color depends on used percent
my $color = $color_ok;
my $per = $df->{per};
if (!defined($per)) { $per = 100 };
if ($per >= $level_warn) {
$color = $color_warn;
}
if ($per >= $level_crit) {
$color = $color_crit;
}
my $bfree = $df->{bfree};
if (!defined($bfree)) { $bfree = 0 };
printf(" \${color #98c2c7}%-${mlength}s\$color %2.f%% %6.1fGB \${color $color}\${fs_bar 6 %s}\$color\n",
$mount_point,
100 - $per,
$bfree/(1024*1024),
$mount_point
);
}
}
sub conky_hddtemp {
my $color_toocold = "#0000ff";
my $color_toohot = "#ff0000";
my $socket=IO::Socket::INET->new(
PeerAddr => 'localhost', PeerPort=> 7634,
Proto => 'tcp', Type => $IO::Socket::SOCK_STREAM)
or croak "Can't talk to hddtemp";
my $hddtemp_output = <$socket>;
close $socket;
my @hddtemp_output = split /[|]/x, $hddtemp_output;
my $diskcount = $#hddtemp_output/5;
for (my $i = 0; $i < $diskcount; $i++) {
my $dev = $hddtemp_output[$i*5+1];
my $temp = $hddtemp_output[$i*5+3];
my $unit = $hddtemp_output[$i*5+4];
my $color = $color_ok;
if ($temp > 40) {
$color = $color_toohot;
} elsif ($temp < 25) {
$color = $color_toocold;
}
printf " \${color #98c2c7}%s\$color ", $dev;
printf "\${color $color}%02.f°%s\$color\n", $temp, $unit;
}
}
sub conky_mdstat {
open my $fh, "<", "/proc/mdstat";
my $md_current;
my $md_current_state;
my $md_current_mdstat;
my $print_md_current_state = sub {
if (defined $md_current) {
my $color = $color_ok;
my $print_mdstat = 0;
if ($md_current_state =~ /^\[(\d+)\/(\d+)\]\s+\[([U_]+)\]$/xsm) {
my $should = $1;
my $are = $2;
my $states = $3;
if ($are < $should) {
$color = $color_crit;
$print_mdstat = 1;
}
} else {
$color = $color_unknown;
}
printf " \${color #98c2c7}%s\$color \${color $color}%s\$color\n",
"/dev/$md_current", $md_current_state;
if ($print_mdstat) {
printf "\n\${color $color}%s\$color",
$md_current_mdstat;
}
}
};
while (my $line = <$fh>) {
next if $line =~ /^Personalities\s*:/xsmi;
next if $line =~ /^unused\sdevices\s*:/xsmi;
if ($line =~ /^(.*) : /) {
&$print_md_current_state();
$md_current = $1;
$md_current_state = undef;
$md_current_mdstat = undef;
}
if ($line =~ /^\s*\d+\s+blocks(?: super [0-9.]+)? (.*)$/) {
$md_current_state = $1;
}
$md_current_mdstat .= $line;
}
close $fh;
&$print_md_current_state();
}
conky_fs();
conky_hddtemp();
conky_mdstat();
# vim:textwidth=120: