# http daemon which sends server stats # basicStats, "ss -s" error messages, yum updates # firewall-cmd --permanent --list-all # firewall-cmd --permanent --add-port (YOUR PORT NUMBER)/tcp # firewall-cmd --reload # OR # iptables -I INPUT 1 -m multiport -p tcp --dport (YOUR PORT NUMBER) -j ACCEPT # iptables-save > /etc/sysconfig/iptables # put following in /etc/systemd/system/server-stats-https.service #[Unit] #Description=Server Stats Perl Daemon #After=network.target #[Service] #Type=simple #User=root #ExecStart=/usr/bin/perl /usr/local/bin/server-stats-https.pl #Restart=always #[Install] #WantedBy=multi-user.target # systemctl daemon-reload # systemctl enable server-stats-https.service # systemctl start server-stats-https.service use bytes; use integer; use HTTP::Daemon::SSL; use HTTP::Status; use MIME::Base64; use JSON::XS; use Sys::Statistics::Linux; use Proc::ProcessTable; # update following constants for this server use constant HD => '/dev/YOUR HD'; use constant KEYDIR => '/etc/letsencrypt/live/YOUR DOMAIN'; use constant PATH => '/YOUR SECRET PATH'; use constant ENC_KEY => 'YOUR PASSWORD'; use constant LOCALPORT => YOUR PORT NUMBER; # i use a cron job to update this nightly # 2 2 * * * root yum -q check-updates > /var/log/YUM-CHECK-UPDATES # running yum on the fly is slow and unpredictable use constant YUM_UPDATES => '/var/log/YUM-CHECK-UPDATES'; my $lxs = Sys::Statistics::Linux->new( sysinfo => 1, #cpustats => 1, #procstats => 1, memstats => 1, pgswstats => 1, netstats => 1, sockstats => 1, diskstats => 1, diskusage => 1, loadavg => 1, filestats => 1, #processes => 1, ); my $d = HTTP::Daemon::SSL->new(LocalPort=>LOCALPORT, ReuseAddr => 1, SSL_cert_file => KEYDIR . '/cert.pem', SSL_key_file => KEYDIR . '/privkey.pem', SSL_ca_file => KEYDIR . '/chain.pem') or die; while (my $c = $d->accept) { while (my $r = $c->get_request) { if ($r->method eq 'GET' and $r->uri->path eq PATH) { my $response = HTTP::Response->new(200); $response->header('Content-Type' => 'text/html'); $response->headers->header('Access-Control-Allow-Origin' => '*'); my $stat = $lxs->get; my $basicStats = '
'; $basicStats .= sprintf("
Uptime %s
", $stat->{sysinfo}->{uptime}); $basicStats .= sprintf("
load avg %s %s %s
", $stat->{loadavg}->{avg_1}, $stat->{loadavg}->{avg_5}, $stat->{loadavg}->{avg_15}); $basicStats .= sprintf("
RAM %d\%
", $stat->{memstats}->{realfreeper}); $basicStats .= sprintf("
Swap %d\%
", $stat->{memstats}->{swapusedper}); $basicStats .= sprintf("
%s %d%%
", HD, $stat->diskusage->{HD()}->{usageper}); $basicStats .= sprintf("
inodes %d%%
", ($stat->{filestats}->{infree}/$stat->{filestats}->{inmax}*100)); $basicStats .= '
'; # class=basicStats my $ss = '
ss' . `ss -s` . '
'; my $log = '
journalctl' . `journalctl -n 10` . '
'; my $processes='
Processes'; my $p = Proc::ProcessTable->new(); my @top = sort { $b->{pctcpu} <=> $a->{pctcpu} } @{$p->table}; for (@top[0..9]) { $processes .= sprintf ("%5d %.2f %.2f %s \n", $_->{pid}, ($_->{pctcpu}), $_->{pctmem}, ($_->{exec} or $_->{fname} or $_->{cmndline})); } $processes .= '
'; my $os = '

' . `cat /etc/system-release` . '

'; my $yum = '
Yum Updates' .$os . `head -20 ${\YUM_UPDATES}` .'
'; my %stats = (basic => $basicStats, expanded => $ss .$log .$processes .$yum); $response->content(encode_base64(xxtea_encrypt(encode_json(\%stats), ENC_KEY))); $c->send_response($response); } else { $c->send_error(RC_FORBIDDEN) } } $c->close; undef($c); } # The following code comes from Crypt::XXTEA by Ma Bingyao # https://metacpan.org/pod/Crypt::XXTEA sub xxtea_encrypt { my ($s, $k) = @_; if ($s eq "") { return ""; } my @v = _str2long($s, 1); my @k = _str2long($k, 0); if (@k < 4) { for (my $i = @k; $i < 4; $i++) { $k[$i] = 0; } } my $n = $#v; my $z = $v[$n]; my $y = $v[0]; my $delta = 0x9E3779B9; my $q = 6 + 52 / ($n + 1); my $sum = 0; my $e; my $p; my $mx; while (0 < $q--) { $sum = ($sum + $delta) & 0xffffffff; $e = $sum >> 2 & 3; for ($p = 0; $p < $n; $p++) { $y = $v[$p + 1]; $mx = ((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ (($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)) & 0xffffffff; $z = $v[$p] = ($v[$p] + $mx) & 0xffffffff; } $y = $v[0]; $mx = ((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ (($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)) & 0xffffffff; $z = $v[$n] = ($v[$n] + $mx) & 0xffffffff; } return _long2str(\@v, 0); } sub _long2str { my ($v, $w) = @_; my $len = @{$v}; my $n = ($len - 1) << 2; if ($w) { my $m = $v->[$len - 1]; if (($m < $n - 3) || ($m > $n)) { return 0; } $n = $m; } my @s = (); for (my $i = 0; $i < $len; $i++) { $s[$i] = pack("V", $v->[$i]); } if ($w) { return substr(join('', @s), 0, $n); } else { return join('', @s); } } sub _str2long { my ($s, $w) = @_; my @v = unpack("V*", $s. "\0"x((4 - length($s) % 4) & 3)); if ($w) { $v[@v] = length($s); } return @v; }