Server IP : 195.201.23.43 / Your IP : 3.145.28.3 Web Server : Apache System : Linux webserver2.vercom.be 5.4.0-192-generic #212-Ubuntu SMP Fri Jul 5 09:47:39 UTC 2024 x86_64 User : kdecoratie ( 1041) PHP Version : 7.1.33-63+ubuntu20.04.1+deb.sury.org+1 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /usr/share/webmin/virtual-server/ |
Upload File : |
# Functions for collecting general system info # collect_system_info([manual-refesh-no-cache]) # Returns a hash reference containing system information sub collect_system_info { my ($manual) = @_; &foreign_require("system-status"); local $info = &system_status::get_collected_info($manual); # Memory may come from a custom command if ($config{'mem_cmd'}) { # Get from custom command local $out = &backquote_command($config{'mem_cmd'}); local @lines = split(/\r?\n/, $out); $info->{'mem'} = [ map { $_/1024 } @lines ]; } # System status $info->{'startstop'} = [ &get_startstop_links() ]; # Counts for domains local $dusers = &count_domain_users(); local $daliases = &count_domain_aliases(1); local @doms = &list_visible_domains(); local @doms_all = &list_domains(); local %fcount = map { $_, 0 } @features; $fcount{'doms'} = 0; foreach my $d (@doms) { $fcount{'doms'}++; foreach my $f (@features) { $fcount{$f}++ if ($d->{$f}); } my @dbs = &domain_databases($d); $fcount{'dbs'} += scalar(@dbs); $fcount{'users'} += $dusers->{$d->{'id'}}; $fcount{'aliases'} += $daliases->{$d->{'id'}}; } $info->{'fcount'} = \%fcount; $info->{'ftypes'} = [ "doms", "dns", "web", "ssl", "mail", "dbs", "users", "aliases" ]; local (%fmax, %fextra, %fhide); foreach my $f (@{$info->{'ftypes'}}) { local ($extra, $reason, $max, $hide) = &count_feature($f); $fmax{$f} = $max; $fextra{$f} = $extra; $fhide{$f} = $hide; } $info->{'fmax'} = \%fmax; $info->{'fextra'} = \%fextra; $info->{'fhide'} = \%fhide; # Quota use for domains if (&has_home_quotas()) { local @quota; local $homesize = "a_bsize("home"); local $mailsize = "a_bsize("mail"); local $maxquota = 0; # Work out quotas foreach my $d (@doms) { # If this is a parent domain, sum up quotas if (!$d->{'parent'}) { local ($home, $mail, $dbusage, $quota); if ($config{'show_uquotas'} == 0) { # Domain group quotas ($home, $mail, $dbusage) = &get_domain_quota($d, 1); $quota = $d->{'quota'}; } else { # Just the domain owner local $duser = &get_domain_owner($d, 1, 0, 1); $home = $duser->{'uquota'}; $mail = $duser->{'umquota'}; $dbusage = 0; $quota = $duser->{'quota'} + $duser->{'mquota'}; } local $usage = $home*$homesize + $mail*$mailsize; $maxquota = $usage+$dbusage if ($usage+$dbusage > $maxquota); local $limit = $quota * $homesize; $maxquota = $limit if ($limit > $maxquota); push(@quota, [ $d, $usage, $limit, $dbusage ]); } } $info->{'quota'} = \@quota; $info->{'maxquota'} = $maxquota; } # IP addresses used local (%ipcount, %ipdom); foreach my $d (@doms) { next if ($d->{'alias'}); $ipcount{$d->{'ip'}}++; $ipdom{$d->{'ip'}} ||= $d; if ($d->{'ip6'}) { $ipcount{$d->{'ip6'}}++; $ipdom{$d->{'ip6'}} ||= $d; } } local %doneip; if (keys %ipdom > 1) { local $defip = &get_default_ip(); local $defip6 = &get_default_ip6(); if (defined(&list_resellers)) { foreach my $r (&list_resellers()) { if ($r->{'acl'}->{'defip'}) { $reselip{ $r->{'acl'}->{'defip'}} = $r; } } } if (defined(&list_shared_ips)) { foreach my $ip (&list_shared_ips()) { $sharedip{$ip}++; } } if (defined(&list_shared_ip6s)) { foreach my $ip6 (&list_shared_ip6s()) { $sharedip{$ip6}++; } } local @ips; foreach my $ip ($defip, (sort { $a cmp $b } keys %reselip), (sort { $a cmp $b } keys %ipcount)) { next if ($doneip{$ip}++); push(@ips, [ $ip, $ip eq $defip ? ('def', undef) : $ip eq $defip6 ? ('def', undef) : $reselip{$ip} ? ('reseller', $reselip{$ip}->{'name'}) : $sharedip{$ip} ? ('shared', undef) : ('virt', undef), $ipcount{$ip}, $ipdom{$ip}->{'dom'} ]); } $info->{'ips'} = [ grep { &check_ipaddress($_->[0]) } @ips ]; $info->{'ips6'} = [ grep { &check_ip6address($_->[0]) } @ips ]; } # IP ranges available local $tmpl = &get_template(0); local @ranges = split(/\s+/, $tmpl->{'ranges'}); local @ipranges; local %taken = &interface_ip_addresses(); foreach my $r (@ranges) { $r =~ /^(\d+\.\d+\.\d+)\.(\d+)\-(\d+)$/ || next; local ($base, $s, $e) = ($1, $2, $3); local ($ipcount, $usedcount) = (0, 0); for(my $j=$s; $j<=$e; $j++) { local $try = "$base.$j"; if ($doneip{$try} || $taken{$try}) { $usedcount++; } $ipcount++; } push(@ipranges, [ $r, $ipcount, $usedcount ]); } if (@ipranges) { $info->{'ipranges'} = \@ipranges; } # Program information local @progs; foreach my $f ("virtualmin", @features) { if ($config{$f} || $f eq "virtualmin") { local $ifunc = "sysinfo_$f"; if (defined(&$ifunc)) { push(@progs, &$ifunc()); } } } $info->{'progs'} = \@progs; # Classify Virtualmin-specific packages my @vposs = grep { &is_virtualmin_package($_) } @{$info->{'poss'}}; $info->{'vposs'} = \@vposs; # SSL certificate expiries foreach my $d (@doms_all) { if (!&domain_has_ssl_cert($d)) { # Doesn't even have SSL, so clear cache fields if ($d->{'ssl_cert_expiry'}) { delete($d->{'ssl_cert_expiry_cache'}); delete($d->{'ssl_cert_expiry'}); &save_domain($d); } next; } my @st = stat($d->{'ssl_cert'}); next if (!@st); # Should never happen next if ($d->{'ssl_cert_expiry_cache'} == $st[9]); my $info = &cert_info($d); next if (!$info); $d->{'ssl_cert_expiry_cache'} = $st[9]; my $notafter = &parse_notafter_date($info->{'notafter'}); $d->{'ssl_cert_expiry'} = $notafter; &save_domain($d); } # Domain registration expiries my $now = time(); foreach my $d (@doms_all) { next if (!$d->{'dns'}); next if ($d->{'whois_next'} && $now < $d->{'whois_next'}); # If update called manually from the dashboard using refresh # button return unless status collection is disabled, and if # disabled allow updating records on manual run to prevent # leaving stale records next if ($manual && $config{'collect_interval'} ne 'none'); my ($exp, $err) = &get_whois_expiry($d); $d->{'whois_next'} = $now + 7*24*60*60 + int(rand(24*60*60)); $d->{'whois_last'} = $now; $d->{'whois_err'} = $err; $d->{'whois_expiry'} = $exp; &save_domain($d); } return $info; } # get_collected_info() # Returns the most recently collected system information, or the current info sub get_collected_info { my ($no_cache) = @_; local $infostr = $config{'collect_interval'} eq 'none' ? undef : &read_file_contents($collected_info_file); if ($infostr && $no_cache ne 'no-cache') { local $info = &unserialise_variable($infostr); if (ref($info) eq 'HASH' && keys(%$info) > 0) { return $info; } } return &collect_system_info(); } # save_collected_info(&info) # Save information collected on schedule sub save_collected_info { local ($info) = @_; &open_tempfile(INFO, ">$collected_info_file"); &print_tempfile(INFO, &serialise_variable($info)); &close_tempfile(INFO); } # refresh_startstop_status() # Refresh regularly collected info on status of services sub refresh_startstop_status { local $info = &get_collected_info(); $info->{'startstop'} = [ &get_startstop_links() ]; &save_collected_info($info); } # refresh_possible_packages(&newpackages) # Refresh regularly collected info on available packages. Assumes that # system_status::refresh_possible_packages has already been called. sub refresh_possible_packages { local ($pkgs) = @_; local %pkgs = map { $_, 1 } @$pkgs; local $info = &get_collected_info(); &foreign_require("system-status"); local $sinfo = &system_status::get_collected_info(); $info->{'poss'} = $sinfo->{'poss'}; my @vposs = grep { &is_virtualmin_package($_) } @{$info->{'poss'}}; $info->{'vposs'} = \@vposs; &save_collected_info($info); } # add_historic_collected_info(&info, time) # Add to the collected info log files the current CPU load, memory uses, swap # use, disk use and other info we might want to graph sub add_historic_collected_info { local ($info, $time) = @_; if (!-d $historic_info_dir) { &make_dir($historic_info_dir, 0700); } local @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'}); push(@stats, [ "procs", $info->{'procs'} ]) if ($info->{'procs'}); if ($info->{'mem'}) { push(@stats, [ "memused", ($info->{'mem'}->[0]-$info->{'mem'}->[1])*1024 ]); push(@stats, [ "memtotal", $info->{'mem'}->[0]*1024 ]); if ($info->{'mem'}->[2]) { push(@stats, [ "swapused", ($info->{'mem'}->[2]-$info->{'mem'}->[3])*1024 ]); push(@stats, [ "swaptotal", $info->{'mem'}->[2]*1024 ]); } if ($info->{'mem'}->[4] ne '') { push(@stats, [ "memcached", $info->{'mem'}->[4]*1024 ]); } if ($info->{'mem'}->[5] ne '') { push(@stats, [ "memburst", $info->{'mem'}->[5]*1024 ]); } } if ($info->{'disk_total'}) { push(@stats, [ "diskused", $info->{'disk_total'}-$info->{'disk_free'}, $info->{'disk_total'} ]); } push(@stats, [ "doms", $info->{'fcount'}->{'doms'} ]); push(@stats, [ "users", $info->{'fcount'}->{'users'} ]); push(@stats, [ "aliases", $info->{'fcount'}->{'aliases'} ]); local $qlimit = 0; local $qused = 0; foreach my $q (@{$info->{'quota'}}) { $qlimit += $q->[2]; $qused += $q->[1]+$q->[3]; } push(@stats, [ "quotalimit", $qlimit ]); push(@stats, [ "quotaused", $qused ]); # Get messages processed by procmail since the last collection time local $now = time(); my $hasprocmail = &mail_system_has_procmail(); if (-r $procmail_log_file && $hasprocmail) { # Get last seek position local $lastinfo = &read_file_contents("$historic_info_dir/procmailpos"); local @st = stat($procmail_log_file); local ($lastpos, $lastinode, $lasttime); if (defined($lastinfo)) { ($lastpos, $lastinode, $lasttime) = split(/\s+/, $lastinfo); } else { # For the first run, start at the end of the file $lastpos = $st[7]; $lastinode = $st[1]; $lasttime = time(); } open(PROCMAILLOG, "<".$procmail_log_file); if ($st[1] == $lastinode && $lastpos) { seek(PROCMAILLOG, $lastpos, 0); } else { $lastpos = 0; } local ($mailcount, $spamcount, $viruscount) = (0, 0, 0); while(<PROCMAILLOG>) { $lastpos += length($_); s/\r|\n//g; local %log = map { split(/:/, $_, 2) } split(/\s+/, $_); if ($log{'User'}) { $mailcount++; if ($log{'Mode'} eq 'Spam') { $spamcount++; } elsif ($log{'Mode'} eq 'Virus') { $viruscount++; } } } close(PROCMAILLOG); local $mins = ($now - $lasttime) / 60.0; push(@stats, [ "mailcount", $mins ? $mailcount / $mins : 0 ]); push(@stats, [ "spamcount", $mins ? $spamcount / $mins : 0 ]); push(@stats, [ "viruscount", $mins ? $viruscount / $mins : 0 ]); # Save last seek &open_tempfile(PROCMAILPOS, ">$historic_info_dir/procmailpos"); &print_tempfile(PROCMAILPOS, $lastpos," ",$st[1]," ",$now."\n"); &close_tempfile(PROCMAILPOS); } # Read mail server log to count messages since the last run local $mail_log_file = $config{'bw_maillog'}; $mail_log_file = &get_mail_log() if ($mail_log_file eq "auto"); if ($mail_log_file) { # Get last seek position local ($spamcount, $mailcount) = (0, 0); local $lastinfo = &read_file_contents("$historic_info_dir/maillogpos"); local @st = stat($mail_log_file); local ($lastpos, $lastinode, $lasttime); if (defined($lastinfo)) { ($lastpos, $lastinode, $lasttime) = split(/\s+/, $lastinfo); } else { # For the first run, start at the end of the file $lastpos = $st[7]; $lastinode = $st[1]; $lasttime = time(); } # Read the log, finding number of messages recived, bounced and # greylisted local ($recvcount, $bouncecount, $greycount, $ratecount) = (0, 0, 0); open(MAILLOG, $mail_log_file); if ($mail_log_file !~ /\|$/) { # Seek forwards in the file, unless rotated if ($st[1] == $lastinode && $lastpos && $lastpos <= $st[7]) { seek(MAILLOG, $lastpos, 0); } else { # Rotated, assume starting at the beginning $lastpos = 0; } } my $now = time(); my @tm = localtime($now); my $finaltime = $lasttime; while(<MAILLOG>) { # Extract log entry time /^(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+/ || next; my $ltime = &log_time_to_unix_time($now, $tm[5], $1, $2, $3, $4, $5); next if (!$ltime); next if ($lasttime && $ltime <= $lasttime); $finaltime = $ltime; if (/^(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\S+)\s+(\S+):\s+(\S+):\s+from=(\S+),\s+size=(\d+)/) { # Sendmail or postfix from= line for a new message $recvcount++; } elsif (/^(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\S+)\s+(\S+):\s+(\S+):\s+<(\S+)>\.*\s*(.*)/i) { # Sendmail bounce message $recvcount++; $bouncecount++; } elsif (/^(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\S+)\s+(\S+):\s+(NOQUEUE):\s+(\S+):.*from=(\S+)\s+to=(\S+)/) { # Postfix bounce message $recvcount++; if (/Greylisted/) { $greycount++; } else { $bouncecount++; } } elsif (/^(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\S+).*ratelimit overflow for class/) { # Rate limiting message $ratecount++; } elsif (/^(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\S+).*spam:\s*identified\s+spam/ && !$hasprocmail) { # Classified as spam when procmail delivery isn't used $spamcount++; $mailcount++; } elsif (/^(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\S+).*spam:\s*clean\s+message/ && !$hasprocmail) { # Deliverted normally when procmail delivery isn't used $mailcount++; } } $lastpos = tell(MAILLOG); close(MAILLOG); if ($lastpos <= 0) { $lastpos = $st[7]; } local $mins = ($now - $lasttime) / 60.0; push(@stats, [ "recvcount", $mins ? $recvcount / $mins : 0 ]); push(@stats, [ "bouncecount", $mins ? $bouncecount / $mins : 0 ]); if ($greycount || !&check_postgrey()) { push(@stats, [ "greycount", $mins ? $greycount / $mins : 0 ]); } if ($ratecount) { push(@stats, [ "ratecount", $mins ? $ratecount / $mins : 0 ]); } if ($spamcount) { push(@stats, [ "spamcount", $mins ? $spamcount / $mins : 0 ]); } if ($mailcount) { push(@stats, [ "mailcount", $mins ? $mailcount / $mins : 0 ]); } # Save last seek &open_tempfile(MAILPOS, ">$historic_info_dir/maillogpos"); &print_tempfile(MAILPOS, $lastpos," ",($st[1] || 0)," ", ($finaltime || $now)."\n"); &close_tempfile(MAILPOS); } # 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; if ($config{'collect_ifaces'}) { # From module config @ifaces = split(/\s+/, $config{'collect_ifaces'}); } else { # Get list from net module &foreign_require("net"); if (defined(&net::active_interfaces)) { foreach my $i (&net::active_interfaces()) { if ($i->{'virtual'} eq '' && $i->{'name'} =~ /^(eth|em|eno|ens|enp|enx|enX|ppp|wlan|ath|wlan)/) { push(@ifaces, $i->{'name'}); } } } else { # Not available on this OS? @ifaces = ( "eth0" ); } } @ifaces = &unique(@ifaces); local $ifaces = join(" ", @ifaces); if (&has_command("ifconfig")) { # Get traffic from old ifconfig command foreach my $iname (@ifaces) { local $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; $rxtotal += $rx; $txtotal += $tx; } } else { # Get traffic from /proc/net/dev local $out = &read_file_contents("/proc/net/dev"); foreach my $l (split(/\r?\n/, $out)) { $l =~ s/^\s+//; my @w = split(/[ \t:]+/, $l); if (&indexof($w[0], @ifaces) >= 0) { $rxtotal += $w[1]; $txtotal += $w[9]; } } } # Work out the diff since the last run, if we have it local %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; } push(@stats, [ "rx", $rxscaled, $netcounts{'rx_max'} ]); push(@stats, [ "tx", $txscaled, $netcounts{'tx_max'} ]); } # Save the last counts $netcounts{'rx'} = $rxtotal; $netcounts{'tx'} = $txtotal; $netcounts{'now'} = $now; $netcounts{'ifaces'} = $ifaces; &write_file("$historic_info_dir/netcounts", \%netcounts); } # Get drive temperatures local ($temptotal, $tempcount); foreach my $t (@{$info->{'drivetemps'}}) { $temptotal += $t->{'temp'}; $tempcount++; } if ($temptotal) { push(@stats, [ "drivetemp", $temptotal / $tempcount ]); } # Get CPU temperature local ($temptotal, $tempcount); foreach my $t (@{$info->{'cputemps'}}) { $temptotal += $t->{'temp'}; $tempcount++; } if ($temptotal) { push(@stats, [ "cputemp", $temptotal / $tempcount ]); } # Get IO blocks if ($info->{'io'}) { push(@stats, [ "bin", $info->{'io'}->[0] ]); push(@stats, [ "bout", $info->{'io'}->[1] ]); } # Get CPU user and IO time if ($info->{'cpu'}) { push(@stats, [ "cpuuser", $info->{'cpu'}->[0] ]); push(@stats, [ "cpukernel", $info->{'cpu'}->[1] ]); push(@stats, [ "cpuidle", $info->{'cpu'}->[2] ]); push(@stats, [ "cpuio", $info->{'cpu'}->[3] ]); } # Write to the file foreach my $stat (@stats) { open(HISTORY, ">>$historic_info_dir/$stat->[0]"); print HISTORY $time," ",$stat->[1],"\n"; close(HISTORY); } # Update the file storing the max possible value for each variable local %maxpossible; &read_file("$historic_info_dir/maxes", \%maxpossible); foreach my $stat (@stats) { if ($stat->[2] && $stat->[2] > $maxpossible{$stat->[0]}) { $maxpossible{$stat->[0]} = $stat->[2]; } } &write_file("$historic_info_dir/maxes", \%maxpossible); } # list_historic_collected_info(stat, [start], [end]) # Returns an array of times and values for some stat, within the given # time period sub list_historic_collected_info { local ($stat, $start, $end) = @_; local @rv; local $last_time; local $now = time(); open(HISTORY, "<$historic_info_dir/$stat"); while(<HISTORY>) { chop; local ($time, $value) = split(" ", $_); next if ($time < $last_time || # No time travel or future data $time > $now); if ((!defined($start) || $time >= $start) && (!defined($end) || $time <= $end)) { push(@rv, [ $time, $value ]); } if (defined($end) && $time > $end) { last; # Past the end point } $last_time = $time; } close(HISTORY); return @rv; } # list_all_historic_collected_info([start], [end]) # Returns a hash mapping stats to data within some time period sub list_all_historic_collected_info { local ($start, $end) = @_; foreach my $f (&list_historic_stats()) { local @rv = &list_historic_collected_info($f, $start, $end); $all{$f} = \@rv; } closedir(HISTDIR); return \%all; } # get_historic_maxes() # Returns a hash reference from stats to the max possible values ever seen sub get_historic_maxes { local %maxpossible; &read_file("$historic_info_dir/maxes", \%maxpossible); return \%maxpossible; } # get_historic_first_last(stat) # Returns the Unix time for the first and last stats recorded sub get_historic_first_last { local ($stat) = @_; open(HISTORY, "<$historic_info_dir/$stat") || return (undef, undef); local $first = <HISTORY>; $first || return (undef, undef); chop($first); local ($firsttime, $firstvalue) = split(" ", $first); seek(HISTORY, 2, -256) || seek(HISTORY, 0, 0); while(<HISTORY>) { $last = $_; } close(HISTORY); chop($last); local ($lasttime, $lastvalue) = split(" ", $last); return ($firsttime, $lasttime); } # list_historic_stats() # Returns a list of variables on which we have stats sub list_historic_stats { local @rv; opendir(HISTDIR, $historic_info_dir); foreach my $f (readdir(HISTDIR)) { if ($f =~ /^[a-z]+[0-9]*$/ && $f ne "maxes" && $f ne "procmailpos" && $f ne "netcounts" && $f ne "maillogpos") { push(@rv, $f); } } closedir(HISTDIR); return @rv; } # setup_collectinfo_job() # Creates or updates the collectinfo.pl cron job, based on the schedule # set in the module config. sub setup_collectinfo_job { # Work out correct steps local $step = $config{'collect_interval'}; $step = 5 if (!$step || $step eq 'none'); $step = 60 if ($step > 60); local $offset = int(rand()*$step); local @mins; for(my $i=$offset; $i<60; $i+= $step) { push(@mins, $i); } local $job = &find_cron_script($collect_cron_cmd); if (!$job && $config{'collect_interval'} ne 'none') { # Create, and run for the first time $job = { 'mins' => join(',', @mins), 'hours' => '*', 'days' => '*', 'months' => '*', 'weekdays' => '*', 'user' => 'root', 'active' => 1, 'command' => $collect_cron_cmd }; &setup_cron_script($job); } 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 : @oldmins == 1 ? 60 : $oldmins[1]-$oldmins[0]; if ($step != $oldstep) { $job->{'mins'} = join(',', @mins); &setup_cron_script($job); } } elsif ($job && $config{'collect_interval'} eq 'none') { # No longer wanted, so delete &delete_cron_script($job->{'command'}); } } # restart_collected_services(&info) # If any services are detected as down, try to restart them. Re-check the status # afterwards, and update the info hash. sub restart_collected_services { local ($info) = @_; my $count = 0; foreach my $ss (@{$info->{'startstop'}}) { if (!$ss->{'status'}) { # Down .. need to restart my $err; if (&indexof($ss->{'feature'}, @plugins) < 0) { # Core feature my $sfunc = "start_service_".$ss->{'feature'}; $err = &$sfunc(); } else { # From plugin $err = &plugin_call($ss->{'feature'}, "feature_start_service"); } $count++; } } if ($count) { $info->{'startstop'} = [ &get_startstop_links() ]; } return $count; } my @virtualmin_packages = ( "apache", "postfix", "sendmail", "bind", "procmail", "spamassassin", "logrotate", "webalizer", "mysql", "postgresql", "proftpd", "clamav", "php4", "mailman", "subversion", "python", "ruby", "irb", "rdoc", "rubygems", "openssl", "perl", "php.*", "webmin", "usermin", "fcgid", "awstats", "dovecot", "postgrey", "virtualmin-modules", "kvm", "xen", "nginx.*", "jailkit", ); # is_virtualmin_package(&package) # Returns 1 if some package looks to be one of the Virtualmin deps sub is_virtualmin_package { my ($pkg) = @_; &foreign_require("software"); return 0 if (!defined(&software::update_system_resolve)); foreach my $n (@virtualmin_packages) { my @res = split(/\s+/, &software::update_system_resolve($n)); foreach my $re (@res) { return 1 if ($pkg->{'name'} =~ /^$re$/i); } } return 0; } 1;Private