# Show general system information
print "<table width=70%>\n";
- # Host and login info
+ # Hostname
print "<tr> <td><b>$text{'right_host'}</b></td>\n";
print "<td>",&get_system_hostname(),"</td> </tr>\n";
+ # Operating system
print "<tr> <td><b>$text{'right_os'}</b></td>\n";
if ($gconfig{'os_version'} eq '*') {
print "<td>$gconfig{'real_os_type'}</td> </tr>\n";
print "<td>$gconfig{'real_os_type'} $gconfig{'real_os_version'}</td> </tr>\n";
}
+ # Webmin version
print "<tr> <td><b>$text{'right_webmin'}</b></td>\n";
print "<td>",&get_webmin_version(),"</td> </tr>\n";
print "<tr> <td><b>$text{'right_time'}</b></td>\n";
print "<td>$tm</td> </tr>\n";
+ # Ask status module for more
+ &foreign_require("system-status");
+ $info = &system_status::get_collected_info();
+
# Kernel and CPU
- $out = &backquote_command(
- "uname -r 2>/dev/null ; uname -m 2>/dev/null ; uname -s 2>/dev/null");
- local ($r, $m, $o) = split(/\r?\n/, $out);
- print "<tr> <td><b>$text{'right_kernel'}</b></td>\n";
- print "<td>",&text('right_kernelon', $o, $r, $m),"</td> </tr>\n";
+ if ($info->{'kernel'}) {
+ print "<tr> <td><b>$text{'right_kernel'}</b></td>\n";
+ print "<td>",&text('right_kernelon',
+ $info->{'kernel'}->{'os'},
+ $info->{'kernel'}->{'version'},
+ $info->{'kernel'}->{'arch'}),"</td> </tr>\n";
+ }
# System uptime
- $out = &backquote_command("LC_ALL='' LANG='' uptime");
- $uptime = undef;
- if ($out =~ /up\s+(\d+)\s+(day|days),\s+(\d+):(\d+)/) {
- # up 198 days, 2:06
- $uptime = &text('right_updays', int($1), int($3), int($4));
- }
- elsif ($out =~ /up\s+(\d+)\s+(day|days),\s+(\d+)\s+min/) {
- # up 198 days, 10 mins
- $uptime = &text('right_updays', int($1), 0, int($3));
+ &foreign_require("proc");
+ my $uptime;
+ my ($d, $h, $m) = &proc::get_system_uptime();
+ if ($d) {
+ $uptime = &text('right_updays', $d, $h, $m);
}
- elsif ($out =~ /up\s+(\d+):(\d+)/) {
- # up 3:10
- $uptime = &text('right_uphours', int($1), int($2));
+ elsif ($m) {
+ $uptime = &text('right_uphours', $h, $m);
}
- elsif ($out =~ /up\s+(\d+)\s+min/) {
- # up 45 mins
- $uptime = &text('right_upmins', int($1));
+ elsif ($m) {
+ $uptime = &text('right_upmins', $m);
}
if ($uptime) {
print "<tr> <td><b>$text{'right_uptime'}</b></td>\n";
}
# Load and memory info
- if (&foreign_check("proc")) {
- &foreign_require("proc", "proc-lib.pl");
- if (defined(&proc::get_cpu_info)) {
- @c = &proc::get_cpu_info();
- if (@c) {
- print "<tr> <td><b>$text{'right_cpu'}</b></td>\n";
- print "<td>",&text('right_load', @c),"</td> </tr>\n";
- }
+ if ($info->{'load'}) {
+ @c = @{$info->{'load'}};
+ if (@c) {
+ print "<tr> <td><b>$text{'right_cpu'}</b></td>\n";
+ print "<td>",&text('right_load', @c),"</td> </tr>\n";
}
- if (defined(&proc::get_memory_info)) {
- @m = &proc::get_memory_info();
- if (@m && $m[0]) {
- print "<tr> <td><b>$text{'right_real'}</b></td>\n";
- print "<td>",&text('right_used',
- &nice_size($m[0]*1024),
- &nice_size(($m[0]-$m[1])*1024)),
- "</td> </tr>\n";
- print "<tr> <td></td>\n";
- print "<td>",&bar_chart($m[0], $m[0]-$m[1], 1),
- "</td> </tr>\n";
- }
-
- if (@m && $m[2]) {
- print "<tr> <td><b>$text{'right_virt'}</b></td>\n";
- print "<td>",&text('right_used',
- &nice_size($m[2]*1024),
- &nice_size(($m[2]-$m[3])*1024)),
- "</td> </tr>\n";
- print "<tr> <td></td>\n";
- print "<td>",&bar_chart($m[2], $m[2]-$m[3], 1),
- "</td> </tr>\n";
- }
+ @m = @{$info->{'mem'}};
+ if (@m && $m[0]) {
+ print "<tr> <td><b>$text{'right_real'}</b></td>\n";
+ print "<td>",&text('right_used',
+ &nice_size($m[0]*1024),
+ &nice_size(($m[0]-$m[1])*1024)),
+ "</td> </tr>\n";
+ print "<tr> <td></td>\n";
+ print "<td>",&bar_chart($m[0], $m[0]-$m[1], 1),
+ "</td> </tr>\n";
}
- #@procs = &proc::list_processes();
- #print "<tr> <td><b>$text{'right_procs'}</b></td>\n";
- #print "<td>",scalar(@procs),"</td> </tr>\n";
- }
-
- # Disk space on local drives
- if (&foreign_check("mount")) {
- &foreign_require("mount", "mount-lib.pl");
- ($total, $free) = &mount::local_disk_space();
- if ($total) {
- print "<tr> <td><b>$text{'right_disk'}</b></td>\n";
+ if (@m && $m[2]) {
+ print "<tr> <td><b>$text{'right_virt'}</b></td>\n";
print "<td>",&text('right_used',
- &nice_size($total),
- &nice_size($total-$free)),"</td> </tr>\n";
+ &nice_size($m[2]*1024),
+ &nice_size(($m[2]-$m[3])*1024)),
+ "</td> </tr>\n";
print "<tr> <td></td>\n";
- print "<td>",&bar_chart($total, $total-$free, 1),
+ print "<td>",&bar_chart($m[2], $m[2]-$m[3], 1),
"</td> </tr>\n";
}
}
+ # Disk space on local drives
+ if ($info->{'disk_total'}) {
+ ($total, $free) = ($info->{'disk_total'}, $info->{'disk_free'});
+ print "<tr> <td><b>$text{'right_disk'}</b></td>\n";
+ print "<td>",&text('right_used',
+ &nice_size($total),
+ &nice_size($total-$free)),"</td> </tr>\n";
+ print "<tr> <td></td>\n";
+ print "<td>",&bar_chart($total, $total-$free, 1),
+ "</td> </tr>\n";
+ }
+
+ # Package updates
+ if ($info->{'poss'}) {
+ print "<tr> <td><b>$text{'right_updates'}</b></td>\n";
+ @poss = @{$info->{'poss'}};
+ @secs = grep { $_->{'security'} } @poss;
+ if (@poss && @secs) {
+ $msg = &text('right_upsec', scalar(@poss),
+ scalar(@secs));
+ }
+ elsif (@poss) {
+ $msg = &text('right_upneed', scalar(@poss));
+ }
+ else {
+ $msg = $text{'right_upok'};
+ }
+ if (&foreign_available("package-updates")) {
+ $msg = "<a href='../package-updates/index.cgi?all=1&mode=updates'>$msg</a>";
+ }
+ print "<td>$msg</td> </tr>\n";
+ }
+
print "</table>\n";
# Check for incorrect OS
&init_config();
$systeminfo_cron_cmd = "$module_config_directory/systeminfo.pl";
$collected_info_file = "$module_config_directory/info";
+$historic_info_dir = "$module_config_directory/history";
# collect_system_info()
# Returns a hash reference containing system information
sub collect_system_info
{
-local $info = { };
+my $info = { };
-# System information
if (&foreign_check("proc")) {
+ # CPU and memory
&foreign_require("proc", "proc-lib.pl");
if (defined(&proc::get_cpu_info)) {
- local @c = &proc::get_cpu_info();
+ my @c = &proc::get_cpu_info();
$info->{'load'} = \@c;
}
- local @procs = &proc::list_processes();
+ my @procs = &proc::list_processes();
$info->{'procs'} = scalar(@procs);
if (defined(&proc::get_memory_info)) {
- local @m = &proc::get_memory_info();
+ my @m = &proc::get_memory_info();
$info->{'mem'} = \@m;
if ($m[0] > 128*1024*1024 && $gconfig{'os_type'} eq 'freebsd') {
# Some Webmin versions overstated memory by a factor
$m[1] /= 1024;
}
}
- if (&foreign_check("mount")) {
- &foreign_require("mount");
- ($info->{'disk_total'}, $info->{'disk_free'}) =
- &mount::local_disk_space();
- }
+
+ # CPU and kernel
+ my ($r, $m, $o) = &proc::get_kernel_info();
+ $info->{'kernel'} = { 'version' => $r,
+ 'arch' => $m,
+ 'os' => $o };
}
-# CPU and kernel
-local $out = &backquote_command(
- "uname -r 2>/dev/null ; uname -m 2>/dev/null ; uname -s 2>/dev/null");
-local ($r, $m, $o) = split(/\r?\n/, $out);
-$info->{'kernel'} = { 'version' => $r,
- 'arch' => $m,
- 'os' => $o };
+# Disk space on local filesystems
+if (&foreign_check("mount")) {
+ &foreign_require("mount");
+ ($info->{'disk_total'}, $info->{'disk_free'}) =
+ &mount::local_disk_space();
+ }
# Available package updates
if (&foreign_check("package-updates") && $config{'collect_pkgs'}) {
&foreign_require("package-updates");
- local @poss = &package_updates::list_possible_updates(2);
+ my @poss = &package_updates::list_possible_updates(2, 1);
$info->{'poss'} = \@poss;
}
# CPU and drive temps
-local @cpu = &get_current_cpu_temps();
+my @cpu = &get_current_cpu_temps();
$info->{'cputemps'} = \@cpu if (@cpu);
-local @drive = &get_current_drive_temps();
+my @drive = &get_current_drive_temps();
$info->{'drivetemps'} = \@drive if (@drive);
return $info;
# Returns the most recently collected system information, or the current info
sub get_collected_info
{
-local $infostr = $config{'collect_interval'} eq 'none' ? undef :
+my $infostr = $config{'collect_interval'} eq 'none' ? undef :
&read_file_contents($collected_info_file);
if ($infostr) {
- local $info = &unserialise_variable($infostr);
+ my $info = &unserialise_variable($infostr);
if (ref($info) eq 'HASH' && keys(%$info) > 0) {
return $info;
}
# Save information collected on schedule
sub save_collected_info
{
-local ($info) = @_;
+my ($info) = @_;
&open_tempfile(INFO, ">$collected_info_file");
&print_tempfile(INFO, &serialise_variable($info));
&close_tempfile(INFO);
# Refresh regularly collected info on status of services
sub refresh_startstop_status
{
-local $info = &get_collected_info();
+my $info = &get_collected_info();
$info->{'startstop'} = [ &get_startstop_links() ];
&save_collected_info($info);
}
# Refresh regularly collected info on available packages
sub refresh_possible_packages
{
-local ($pkgs) = @_;
-local %pkgs = map { $_, 1 } @$pkgs;
-local $info = &get_collected_info();
+my ($pkgs) = @_;
+my %pkgs = map { $_, 1 } @$pkgs;
+my $info = &get_collected_info();
if ($info->{'poss'} && &foreign_check("package-updates")) {
&foreign_require("package-updates");
- local @poss = &package_updates::list_possible_updates(2);
+ my @poss = &package_updates::list_possible_updates(2);
$info->{'poss'} = \@poss;
}
&save_collected_info($info);
# use, disk use and other info we might want to graph
sub add_historic_collected_info
{
-local ($info, $time) = @_;
+my ($info, $time) = @_;
if (!-d $historic_info_dir) {
&make_dir($historic_info_dir, 0700);
}
-local @stats;
+my @stats;
push(@stats, [ "load", $info->{'load'}->[0] ]) if ($info->{'load'});
push(@stats, [ "load5", $info->{'load'}->[1] ]) if ($info->{'load'});
push(@stats, [ "load15", $info->{'load'}->[2] ]) if ($info->{'load'});
# Get network traffic counts since last run
if (&foreign_check("net") && $gconfig{'os_type'} =~ /-linux$/) {
# Get the current byte count
- local $rxtotal = 0;
- local $txtotal = 0;
+ my $rxtotal = 0;
+ my $txtotal = 0;
if ($config{'collect_ifaces'}) {
# From module config
@ifaces = split(/\s+/, $config{'collect_ifaces'});
}
}
}
- local $ifaces = join(" ", @ifaces);
+ my $ifaces = join(" ", @ifaces);
foreach my $iname (@ifaces) {
- local $out = &backquote_command(
+ my $out = &backquote_command(
"LC_ALL='' LANG='' ifconfig ".
quotemeta($iname)." 2>/dev/null");
- local $rx = $out =~ /RX\s+bytes:\s*(\d+)/i ? $1 : undef;
- local $tx = $out =~ /TX\s+bytes:\s*(\d+)/i ? $1 : undef;
+ my $rx = $out =~ /RX\s+bytes:\s*(\d+)/i ? $1 : undef;
+ my $tx = $out =~ /TX\s+bytes:\s*(\d+)/i ? $1 : undef;
$rxtotal += $rx;
$txtotal += $tx;
}
# Work out the diff since the last run, if we have it
- local %netcounts;
+ my %netcounts;
if (&read_file("$historic_info_dir/netcounts", \%netcounts) &&
$netcounts{'rx'} && $netcounts{'tx'} &&
$netcounts{'ifaces'} eq $ifaces &&
$rxtotal >= $netcounts{'rx'} && $txtotal >= $netcounts{'tx'}) {
- local $secs = ($now - $netcounts{'now'}) * 1.0;
- local $rxscaled = ($rxtotal - $netcounts{'rx'}) / $secs;
- local $txscaled = ($txtotal - $netcounts{'tx'}) / $secs;
- if ($rxscaled >= $netcounts{'rx_max'}) {
- $netcounts{'rx_max'} = $rxscaled;
- }
- if ($txscaled >= $netcounts{'tx_max'}) {
- $netcounts{'tx_max'} = $txscaled;
+ my $secs = ($now - $netcounts{'now'}) * 1.0;
+ if ($secs) {
+ my $rxscaled = ($rxtotal - $netcounts{'rx'}) / $secs;
+ my $txscaled = ($txtotal - $netcounts{'tx'}) / $secs;
+ if ($rxscaled >= $netcounts{'rx_max'}) {
+ $netcounts{'rx_max'} = $rxscaled;
+ }
+ if ($txscaled >= $netcounts{'tx_max'}) {
+ $netcounts{'tx_max'} = $txscaled;
+ }
+ push(@stats, [ "rx",$rxscaled, $netcounts{'rx_max'} ]);
+ push(@stats, [ "tx",$txscaled, $netcounts{'tx_max'} ]);
}
- push(@stats, [ "rx", $rxscaled, $netcounts{'rx_max'} ]);
- push(@stats, [ "tx", $txscaled, $netcounts{'tx_max'} ]);
}
# Save the last counts
}
# Get drive temperatures
-local ($temptotal, $tempcount);
+my ($temptotal, $tempcount);
foreach my $t (@{$info->{'drivetemps'}}) {
$temptotal += $t->{'temp'};
$tempcount++;
}
# Get CPU temperature
-local ($temptotal, $tempcount);
+my ($temptotal, $tempcount);
foreach my $t (@{$info->{'cputemps'}}) {
$temptotal += $t->{'temp'};
$tempcount++;
}
# Update the file storing the max possible value for each variable
-local %maxpossible;
+my %maxpossible;
&read_file("$historic_info_dir/maxes", \%maxpossible);
foreach my $stat (@stats) {
if ($stat->[2] && $stat->[2] > $maxpossible{$stat->[0]}) {
# time period
sub list_historic_collected_info
{
-local ($stat, $start, $end) = @_;
-local @rv;
-local $last_time;
-local $now = time();
+my ($stat, $start, $end) = @_;
+my @rv;
+my $last_time;
+my $now = time();
open(HISTORY, "$historic_info_dir/$stat");
while(<HISTORY>) {
chop;
- local ($time, $value) = split(" ", $_);
+ my ($time, $value) = split(" ", $_);
next if ($time < $last_time || # No time travel or future data
$time > $now);
if ((!defined($start) || $time >= $start) &&
# Returns a hash mapping stats to data within some time period
sub list_all_historic_collected_info
{
-local ($start, $end) = @_;
+my ($start, $end) = @_;
foreach my $f (&list_historic_stats()) {
- local @rv = &list_historic_collected_info($f, $start, $end);
+ my @rv = &list_historic_collected_info($f, $start, $end);
$all{$f} = \@rv;
}
closedir(HISTDIR);
# Returns a hash reference from stats to the max possible values ever seen
sub get_historic_maxes
{
-local %maxpossible;
+my %maxpossible;
&read_file("$historic_info_dir/maxes", \%maxpossible);
return \%maxpossible;
}
# Returns the Unix time for the first and last stats recorded
sub get_historic_first_last
{
-local ($stat) = @_;
+my ($stat) = @_;
open(HISTORY, "$historic_info_dir/$stat") || return (undef, undef);
-local $first = <HISTORY>;
+my $first = <HISTORY>;
$first || return (undef, undef);
chop($first);
-local ($firsttime, $firstvalue) = split(" ", $first);
+my ($firsttime, $firstvalue) = split(" ", $first);
seek(HISTORY, 2, -256) || seek(HISTORY, 0, 0);
while(<HISTORY>) {
$last = $_;
}
close(HISTORY);
chop($last);
-local ($lasttime, $lastvalue) = split(" ", $last);
+my ($lasttime, $lastvalue) = split(" ", $last);
return ($firsttime, $lasttime);
}
# Returns a list of variables on which we have stats
sub list_historic_stats
{
-local @rv;
+my @rv;
opendir(HISTDIR, $historic_info_dir);
foreach my $f (readdir(HISTDIR)) {
if ($f =~ /^[a-z]+[0-9]*$/ && $f ne "maxes" && $f ne "procmailpos" &&
&foreign_require("cron");
# Work out correct steps
-local $step = $config{'collect_interval'};
+my $step = $config{'collect_interval'};
$step = 5 if (!$step || $step eq 'none');
-local $offset = int(rand()*$step);
-local @mins;
+my $offset = int(rand()*$step);
+my @mins;
for(my $i=$offset; $i<60; $i+= $step) {
push(@mins, $i);
}
-local $job = &cron::find_cron_job($systeminfo_cron_cmd);
+my $job = &cron::find_cron_job($systeminfo_cron_cmd);
if (!$job && $config{'collect_interval'} ne 'none') {
# Create, and run for the first time
}
elsif ($job && $config{'collect_interval'} ne 'none') {
# Update existing job, if step has changed
- local @oldmins = split(/,/, $job->{'mins'});
- local $oldstep = $oldmins[0] eq '*' ? 1 :
+ my @oldmins = split(/,/, $job->{'mins'});
+ my $oldstep = $oldmins[0] eq '*' ? 1 :
@oldmins == 1 ? 60 :
$oldmins[1]-$oldmins[0];
if ($step != $oldstep) {
# Returns a list of hashes, containing device and temp keys
sub get_current_drive_temps
{
-local @rv;
+my @rv;
if (!$config{'collect_notemp'} &&
&foreign_installed("smart-status")) {
&foreign_require("smart-status");
foreach my $d (&smart_status::list_smart_disks_partitions()) {
- local $st = &smart_status::get_drive_status($d->{'device'}, $d);
+ my $st = &smart_status::get_drive_status($d->{'device'}, $d);
foreach my $a (@{$st->{'attribs'}}) {
if ($a->[0] =~ /^Temperature\s+Celsius$/i &&
$a->[1] > 0) {
# Returns a list of hashes containing core and temp keys
sub get_current_cpu_temps
{
-local @rv;
+my @rv;
if (!$config{'collect_notemp'} &&
$gconfig{'os_type'} =~ /-linux$/ && &has_command("sensors")) {
&open_execute_command(SENSORS, "sensors </dev/null 2>/dev/null", 1);