== == Created: Wednesday, July 2nd 2008 == == Modified: Monday, January 12th 2009 == == License: Creative Commons Attribution-Noncommercial 3.0 United States == == License URL: http://creativecommons.org/licenses/by-nc/3.0/us/ == \***** File Info *****/ /*** Changelog ***\ == 1.1.0 == = Public release = == 1.1.1 & 1.1.2 == = Display fix: Fixed minor bugs regarding display of information. = == 1.1.3 == = New Feature: Different e-mail subject, sender, and recipient for Reports and Alerts. = Bug fix: Site monitor would show incorrect information in most cases where more than one site was monitored. = Display fix: E-mail report would show 'MB' in RAM information in a new line. = == 1.1.4 == = New Feature: Added User Agent "MOSMC-PHP" when checking sites. = Bux fix: Minor. Related to services checking. Did not affect functionality. = == 1.1.5 (07/22/2008) == = Bug fix: PHP error. Might be major bug if running through cron. = == 2.0.0 (01/11/2009) == = Update: Re-wrote MOSMC in OOP. = Update: Re-worded some of the comments to make clearer what MOSMC is doing. = Update: Documentation is now more specific, and has been re-worded to make it clearer. = New Feature: Added configuration option: hard drive partition to use for hard drive usage stats. = New Feature: Integrated HTTP authentication. = New Feature: Notification when new MOSMC release is available (optional; See configuration options). = New Feature: Test variables simulating various scenarios have been included. Search for "Testing Variables" in the source. Note: Email and Browser output testing variables are separated. = Bug fix: PHP mail() would not set the Return-Path header properly, often required for SPF. Now fixed, using sender email as return path address. = Bug fix: Service listening check now returns proper results. In limited cases, it would show a service as listening when it wasn't. = Bug fix: Only first word of HTTP status description would be shown. = Bug fix: Now handles DNS errors and cURL errors properly, and when the server hangs connections (an alert is triggered). = Bug fix: When testing sites, a 30 second timeout is used. Previously, MOSMC would seem to hang if a site was not responding. = Security fix: Vulnerability when register_globals is enabled in PHP configuration. = Display fix: Alert SMS output has updated formatting for improved readability. = Misc fix: Cleaned up HTML output formatting. = Misc fix: Cleaned up PHP source code formatting. = == 2.0.1 (01/12/2008) == = Update: Modified about a dozen areas of PHP source code to improve performance, and removed some unnecessary code. = Update: Added updating instructions in documentation. = New Feature: Configuration option ($this->web->auth) allows disabling HTTP authentication on Web console (Not recommended if others can access MOSMC). = Bug fix: In certain software configurations, MOSMC's Web console would fail to run properly. (Direct cause unknown; Work-around added.) = Display/Security fix: If register_globals is enabled, a warning is shown. \*** Changelog ***/ /*** Comments ***\ = MOSMC is pronounced as "moss-em-see". = Feel free to improve upon it, but please let me know what you've done with it. :) \*** Comments ***/ /*** Notes & Usage ***\ == How To Configure Initially == = Go to the area delimited as "Configuration" (the Config class), and insert/modify values as necessary. = For configuration options with arrays (multiple values), such as services and sites, increase the array key (inside the square brackets) by one for each new service/site configured. = Then proceed to use MOSMC via a Web browser, by placing it in a PHP-enabled Web server directory. = For full utilization of MOSMC, it is recommended you set up cron jobs, as detailed later in this documentation. This enables alerts on component failure, as well as periodic reports. = == How to Update == = Just copy the configuration from your old MOSMC file to your new MOSMC file. Wasn't that simple? = Check the changelog for new configuration options, and make sure they are set. = Note: v1.x.x configuration is *not* compatible with v2.x.x configuration. = == General == = Status codes are in ascending order of severity. Higher number, higher severity. = Site monitor links to URL only in case of failure. Otherwise, it doesn't link to the URL being tested. = 'Component' refers to any item that is monitored by MOSMC (such as a specific website or service). = == Cron Jobs // Overview == = Cron jobs can be run to either notify you on failure of a component or to send reports periodically. = There are two types of cron jobs: Those that trigger alerts only on failure (type = failure), and those who send a full report of all monitored components, regardless of their status (type = report) = Additionally, you can set up a cron job to check for updates periodically (optional, of course). = == Setting Up Local Cron Jobs == = Use command 'php /path/to/monitor.php type password' = Example: 'php /path/to/monitor.php failure yourpass' if you wanted to send emails only on component failure = == Setting Up Remote Cron Jobs or On-Demand Reporting == = Use monitor.php?cron=1&type=failure&pass=yourpass if you want to send an email formatted for SMS on component failure with the details of the failing component = Use monitor.php?cron=1&type=report&pass=yourpass if you want to send email with full report regardless of status (Not optimized for SMS) = To send an e-mail, you must to append the password you've set in the configuration to the URL. This prevents others from triggering e-mails. Example: monitor.php?cron=1&type=failure&pass=yourpass = Note: HTTP authentication (username and password) is not required when using web cron jobs. = == Checking for Updates Automatically == = This is optional, but recommended. There are two methods to check for updates: = Add a cron job, either locally ('php /path/to/monitor.php update password'), or remotely (monitor.php?cron=1&type=update&pass=yourpass) = It is recommended that you set your cron job to check once a week, preferably Monday or Tuesday (updates will probably be published on these days) = Note: An e-mail will be sent if an update is available each time you run the cron job. = Note: The Web console may check for updates each time you access it, depending on your configuration. = Note: MOSMC checks updates using cURL from the terminal, when using cron jobs. It checks using an AJAX request when using the Web console. = Note: No information is deliberately sent or stored, other than your current version number. Standard information recorded by Apache logs is saved, but will *NEVER* be used or analyzed whatsoever. = == How MOSMC-PHP Tests Components == = Services: Checks first if services are listening through netstat, then checks if it accepts internal connections, and then checks if it accepts external connections (last two using fsockopen() ). = Sites: Checks HTTP header response using cURL (from the terminal, not the PHP library). = == Disclaimers == = ****====IMPORTANT====**** = MOSMC outputs certain information that can make it easier to target your system for vulnerabilities, such as ports where services are running, and the types of connections accepted by services. = It is highly recommended that your MOSMC script is *ALWAYS* in a location you only know, and that is not easily guessable. = It is highly recommended that your MOSMC script *ALWAYS* be protected by a strong username and password combination. = It is highly recommended that you have register_globals *DISABLED* in your PHP configuration (although MOSMC makes sure only required input is accepted). ****====IMPORTANT====**** = = MOSMC has only been tested using PHP 5.2 on Debian 4.0 (Etch). No guarantee of functionality or reliability is given (although I've tested it extensively, and it seems very reliable). = MOSMC will probably *not* work in PHP 4, as it uses PHP 5 OOP and functions only supported by PHP 5. \*** Notes & Usage ***/ class Config { protected $server, $email, $web, $service, $load, $ram, $fs, $site; public function __construct() { /*** Configuration ***/ //External IP of server to test $this->server->ip = '1234.56.78.90'; //If using MOSMC in a server with a dynamic IP linked to a DNS record, comment the line above and uncomment line below //$this->server->ip = gethostbyname('sub.domain.tld'); //Name of your server $this->server->name = 'Server Name'; //E-mail to send Reports to $this->email->recipient->report = 'reports@yourdomain.tld'; //E-mail to send Alerts to $this->email->recipient->alert = 'alerts@yourdomain.tld'; //E-mail to send Update notifications to (optional) $this->email->recipient->update = 'update@yourdomain.tld'; //E-mail to send Reports from $this->email->sender->report = 'mosmc-report@yourdomain.tld'; //E-mail to send Alerts from $this->email->sender->alert = 'mosmc-alert@yourdomain.tld'; //E-mail to send Update notifcations from (optional) $this->email->sender->update = 'mosmc-update@yourdomain.tld'; //Subject of Report e-mail (Recommended: Default) $this->email->subject->report = $this->server->name.' Report'; //Subject of Alert e-mail (Recommended: Default) $this->email->subject->alert = $this->server->name.' Alert'; //Subject of Update notification e-mail (Recommended: Default) $this->email->subject->update = 'MOSMC Update needed at '.$this->server->name; //E-mail headers for Reports (Recommended: Default) $this->email->header->report = 'From: "MOSMC" <'.$this->email->sender->report.">\r\n"; //E-mail headers for Alerts (Recommended: Default) $this->email->header->alert = 'From: "MOSMC" <'.$this->email->sender->alert.">\r\n"; //E-mail headers for Update notifications (Recommended: Default) $this->email->header->update = 'From: "MOSMC" <'.$this->email->sender->update.">\r\n"; //Set minimum threshold level to send email. Values: 0 = Send on Warning and Max/Alert (recommended); 1 = Send only on Max/Alert $this->email->threshold = 0; //Username used for viewing the Web console. $this->web->username = 'yourUsername'; //Password for viewing the Web console, and sending e-mails. $this->web->password = 'yourVerySecurePassword'; //Set if you want to check for updates automatically when visiting the Web console. 1 = yes (default), 0 = no $this->web->update = 1; //Set if you want to use HTTP authentication on Web console. 1 = enabled (default), 0 = disabled (NOT recommended) $this->web->auth = 1; //Human readable service name $this->service[0]->name = 'httpd'; $this->service[1]->name = 'MySQL'; //Type of connection accepted by service. Type 0 = 'Local service' (only internal connections), type 1 = 'Public service' (internal + external connections) $this->service[0]->type = 1; $this->service[1]->type = 0; //Port service is running on $this->service[0]->port = 80; $this->service[1]->port = 3306; //Statistics Warning and Maximum/Alert thresholds //Load average $this->load->warn = '4.00'; $this->load->max = '8.00'; //RAM $this->ram->warn = 460; $this->ram->max = 512; //Storage (File System) $this->fs->partition = 'sda1'; //As listed in 'df' after /dev/ $this->fs->warn = 8*1024; //8GB (2.0 GB free) $this->fs->max = 10*1024; //10GB (0.0 GB free) //Human readable website name $this->site[0]->name = 'Google'; $this->site[1]->name = 'Slashdot'; //URL of websites to check (You may use alternate ports. Ex: http://domain.tld:8080) $this->site[0]->url = 'http://www.google.com'; $this->site[1]->url = 'http://slashdot.org'; /*** Configuration ***/ } } class Monitor extends Config { protected $version, $get, $services, $sites; private $global, $key; public function __construct() { $this->filterInput(); $this->getArguments(); parent::__construct(); $this->version = '2.0.1'; $this->populateData(); } private function filterInput() { //Lets only grab the input we need foreach(array($_GET, $_SERVER) as $global) { foreach($global as $key => $value) { if($key == 'argv') { $this->get->$key = $value; } elseif($key == 'PHP_AUTH_USER') { $this->get->http->user = $value; } elseif($key == 'PHP_AUTH_PW') { $this->get->http->pass = $value; } elseif($key == 'cron' || $key == 'type' || $key == 'pass') { $this->get->$key = $value; } } } } private function getArguments() { //Check if running cron job. If so, get configuration options from CLI. if(isset($this->get->argv[1])) { $this->get->cron = 1; $this->get->type = strtolower($this->get->argv[1]); $this->get->pass = $this->get->argv[2]; } } private function populateData() { /*** Populate Data Variables ***/ $this->services->count = count($this->service); $this->sites->count = count($this->site); $this->checkServices(); $this->grabStats(); $this->checkSites(); /*** Populate Data Variables ***/ } private function checkServices() { //Check if ports are open for each service for($i=0; $i < $this->services->count; $i++) { $this->service[$i]->status->listen = -1; $this->service[$i]->status->internal = -1; $this->service[$i]->status->external = -1; //Check if services are listening $listenCheck = shell_exec('netstat -l -n | grep ":'.$this->service[$i]->port.' " | wc -l'); //If listening, win if($listenCheck > 0) { $this->service[$i]->status->listen = 0; } //If not listening, fail else { $this->service[$i]->status->listen = 1; } //Check internal connection if service is listening for connections if($this->service[$i]->status->listen == 0) { $fp = @fsockopen('localhost', $this->service[$i]->port, $errno, $errstr, 1); //If internal connection is accepted, win if($fp) { $this->service[$i]->status->internal = 0; } //If internal connection is rejected, fail else { $this->service[$i]->status->internal = 1; } } //Check external connection if internal connection is available if($this->service[$i]->status->internal == 0 && $this->service[$i]->status->listen == 0) { $fp = @fsockopen($this->server->ip, $this->service[$i]->port, $errno, $errstr, 1); //If external connection is accepted, and is supposed to be accepted, win if($fp && $this->service[$i]->type == 1) { $this->service[$i]->status->external = 0; } //If external connection is rejected, and not supposed to be accepted, win elseif(!$fp && $this->service[$i]->type == 0) { $this->service[$i]->status->external = 1; } //If external connection is rejected, and is supposed to be accepted, fail elseif(!$fp && $this->service[$i]->type == 1) { $this->service[$i]->status->external = 2; } //If external connection is accepted, but not supposed to be, fail + alert elseif($fp && $this->service[$i]->type == 0) { $this->service[$i]->status->external = 3; } } } } private function grabStats() { //Grab Uptime + Load Averages $this->uptime = shell_exec('uptime'); //Extract load averages preg_match("/averages?: ([0-9\.]+),[\s]+([0-9\.]+),[\s]+([0-9\.]+)/", $this->uptime, $this->loads); $this->load->status = -1; if($this->load->warn > $this->loads[1] && $this->loads[1] < $this->load->max) { $this->load->status = 0; } elseif($this->load->warn <= $this->loads[1] && $this->loads[1] < $this->load->max) { $this->load->status = 1; } else { $this->load->status = 2; } //Extract uptime $this->uptime = explode(' up ', $this->uptime); $this->uptime = explode(',', $this->uptime[1]); $this->uptime = $this->uptime[0].', '.trim($this->uptime[1]); //Grab number of users logged in $this->users = trim(shell_exec('who | wc -l')); //Grab RAM usage $this->ram->used = trim(shell_exec('free -m | grep "buffers/cache" | awk \'{print $3}\'')); $this->ram->status = -1; if($this->ram->warn > $this->ram->used && $this->ram->used < $this->ram->max) { $this->ram->status = 0; } elseif($this->ram->warn <= $this->ram->used && $this->ram->used < $this->ram->max) { $this->ram->status = 1; } else { $this->ram->status = 2; } //Grab HDD File System usage $this->fs->used = round(shell_exec('df | grep '.$this->fs->partition.' | awk \'{print $3}\'')/1024, 2); $this->fs->status = -1; if($this->fs->warn > $this->fs->used && $this->fs->used < $this->fs->max) { $this->fs->status = 0; } elseif($this->fs->warn <= $this->fs->used && $this->fs->used < $this->fs->max) { $this->fs->status = 1; } else { $this->fs->status = 2; } //Grab number of processes $this->processes = trim(shell_exec('ps aux | wc -l')); $this->processes = $this->processes--; //Grab number of connections $this->conns->tcp = trim(shell_exec('netstat -t | grep tcp | wc -l')); $this->conns->udp = trim(shell_exec('netstat -u | grep udp | wc -l')); } private function checkSites() { //Check if sites are returning HTTP status 200 (OK) or HTTP status 302 (Found) for($i=0; $i < $this->sites->count; $i++) { $this->site[$i]->status = -1; //Grab HTTP Status. The whitespace in the awk command is there as a workaround to a small bug when parsing data w/ awk. $this->site[$i]->http->response = trim(shell_exec('curl '.$this->site[$i]->url." -I -s -m 30 -A 'MOSMC-PHP' | grep HTTP | ".'awk \'{print " "$2" "$3" "$4" "$5" "$6}\'')); $this->site[$i]->http->status = substr($this->site[$i]->http->response, 0, 3); $this->site[$i]->http->desc = trim(substr($this->site[$i]->http->response, 3)); //If headers return HTTP status 200 (OK) or HTTP status 302 (Found), win if($this->site[$i]->http->status == 200 || $this->site[$i]->http->status == 302) { $this->site[$i]->status = 0; } //If DNS cannot be resolved, cURL isn't installed, or server hangs connections, fail elseif($this->site[$i]->http->response == '') { $this->site[$i]->status = 1; $this->site[$i]->http->desc = 'DNS/cURL error or server hangs conn.'; } //If headers return HTTP status other than 200 (OK) or HTTP status 302 (Found), fail else { $this->site[$i]->status = 1; } } } } class BrowserOutput extends Monitor { public function __construct() { parent::__construct(); if($this->get->http->user == $this->web->username && $this->get->http->pass == $this->web->password) { //Do nothing } elseif($this->web->auth) { header('WWW-Authenticate: Basic realm="MOSMC"'); exit('Not authorized.'); } /*** Testing Variables ***/ //These testing variables only affect browser output, not email notifications. //Various service status scenarios //1-Service is not listening, probably because it's down /*$this->service[0]->status->listen = 1; $this->service[0]->status->internal = -1; $this->service[0]->status->external = -1;*/ //2-Service is listening, but rejecting all connections /*$this->service[0]->status->listen = 0; $this->service[0]->status->internal = 1; $this->service[0]->status->external = -1;*/ //3-Service is listening, and rejecting external connections, but supposed to accept them /*$this->service[0]->status->listen = 0; $this->service[0]->status->internal = 0; $this->service[0]->status->external = 2;*/ //4-Service is listening, and accepting external connections, but supposed to reject them /*$this->service[0]->status->listen = 0; $this->service[0]->status->internal = 0; $this->service[0]->status->external = 3;*/ //Various system stats failure scenarios //Trigger warning /*$this->load->status = 1; $this->ram->status = 1; $this->fs->status = 1;*/ //Trigger alert /*$this->load->status = 2; $this->ram->status = 2; $this->fs->status = 2;*/ //Site failure scenario /*$this->site[0]->status = 1; $this->site[0]->http->status = 500; $this->site[0]->http->desc = 'Internal Server Error';*/ /*** Testing Variables ***/ } public function update() { //Send a request to my update checking script $return = shell_exec('curl http://update.thephpjedi.com/mosmc/?version='.$this->version.' -s -m 30 -A "MOSMC Updater"'); //If we get a response, display it if($return != '') { echo $return; } else { echo 'updates=>Error while checking for newer version.|'; } } public function render() { ?> <?php echo $this->server->name; ?> Monitoring Console

server->name; ?> Monitoring Console

server->ip; ?>

Warning!
PHP configuration option "register_globals" is enabled!
This is a serious security risk. It is HIGHLY recommended you disable it.
services(); $this->stats(); $this->sites(); ?> service as $service) { ?> status->listen) { case 0: echo 'status->internal) { case 0: echo 'status->external) { case 0: echo '
Service Port Local Connection External Connection
name; ?> '; echo 'Listening ('.$service->port.')'; break; case 1: echo ''; echo 'Not listening ('.$service->port.')'; break; default: echo ''; echo 'N/A'; } ?> '; echo 'Accepting'; break; case 1: echo ''; echo 'Rejecting'; break; default: echo ''; echo 'N/A'; } ?> '; echo 'Accepting as configured'; break; case 1: echo ''; echo 'Rejecting as configured'; break; case 2: echo ''; echo 'Rejecting; Misconfigured'; break; case 3: echo ''; echo 'Accepting; Misconfigured'; break; default: echo ''; echo 'N/A'; } ?>

load->status) { case 0: echo 'ram->status) { case 0: echo 'fs->status) { case 0: echo '
Stat Type Current Value Warn Threshold Alert Threshold
Load Averages '; echo $this->loads[1].' '.$this->loads[2].' '.$this->loads[3]; break; case 1: echo ''; echo ''.$this->loads[1].' '.$this->loads[2].' '.$this->loads[3].''; break; case 2: echo ''; echo ''.$this->loads[1].' '.$this->loads[2].' '.$this->loads[3].''; break; default: echo ''; echo 'Error'; } ?> load->warn; ?> (1 min avg) load->max; ?> (1 min avg)
Used RAM '; echo $this->ram->used; break; case 1: echo ''; echo ''.$this->ram->used.''; break; case 2: echo ''; echo ''.$this->ram->used.''; break; default: echo ''; echo 'Error'; } ?> MB ram->warn; ?> MB ram->max >= 1024) ? ($this->ram->max/1024).' GB' : $this->ram->max.' MB'; ?>
Used Storage '; echo ($this->fs->used >= 1024) ? round($this->fs->used/1024, 2).' GB' : $this->fs->used.' MB'; break; case 1: echo ''; echo ($this->fs->used >= 1024) ? round($this->fs->used/1024, 2).' GB' : $this->fs->used.' MB'; echo ''; break; case 2: echo ''; echo ($this->fs->used >= 1024) ? round($this->fs->used/1024, 2).' GB' : $this->fs->used.' MB'; echo ''; break; default: echo ''; echo 'Error'; } ?> fs->warn >= 1024) ? round($this->fs->warn/1024, 2).' GB' : $this->fs->warn.' MB'; ?> fs->max >= 1024) ? round($this->fs->max/1024, 2).' GB' : $this->fs->max.' MB'; ?>

Stat Type Current Value Stat Type Current Value
Processes processes; ?> Users Logged In users; ?>
Uptime uptime; ?> TCP/UDP Conns conns->tcp.'/'.$this->conns->udp; ?>

site as $site) { ?> status) { case 0: echo '
Site HTTP Status URL
name; ?> '; echo $site->http->status.' ('.$site->http->desc.')'; break; case 1: echo ''; echo $site->http->status.' ('.$site->http->desc.')'; break; default: echo ''; echo 'N/A'; } ?> status) ? ''.$site->url.'' : $site->url; ?>
service[0]->status->listen = 1; $this->service[0]->status->internal = -1; $this->service[0]->status->external = -1;*/ //2-Service is listening, but rejecting all connections /*$this->service[0]->status->listen = 0; $this->service[0]->status->internal = 1; $this->service[0]->status->external = -1;*/ //3-Service is listening, and rejecting external connections, but supposed to accept them /*$this->service[1]->status->listen = 0; $this->service[1]->status->internal = 0; $this->service[1]->status->external = 2;*/ //4-Service is listening, and accepting external connections, but supposed to reject them /*$this->service[0]->status->listen = 0; $this->service[0]->status->internal = 0; $this->service[0]->status->external = 3;*/ //Various system stats failure scenarios //Trigger warning /*$this->load->status = 1; $this->ram->status = 1; $this->fs->status = 1;*/ //Trigger alert /*$this->load->status = 2; $this->ram->status = 2; $this->fs->status = 2;*/ //Site failure scenario /*$this->site[0]->status = 1; $this->site[0]->http->status = 500; $this->site[0]->http->desc = 'Internal Server Error';*/ /*** Testing Variables ***/ } public function update() { //Send a request to my update checking script $return = shell_exec('curl "http://update.thephpjedi.com/mosmc/?version='.$this->version.'&method=cron" -s -m 30 -A "MOSMC Updater"'); //If we get a response, send it if($return != '') { mail($this->email->recipient->update, $this->email->subject->update, $return, $this->email->header->update, '-f'.$this->email->sender->update); } } public function send() { if($this->web->password == $this->get->pass) { if($this->get->type == 'report') { $this->generateReport(); mail($this->email->recipient->report, $this->email->subject->report, $this->email->output, $this->email->header->report, '-f'.$this->email->sender->report); echo 'Cron job run successfully.'; } elseif($this->get->type == 'failure') { $this->generateAlert(); //Send SMS containing alerts only if threshold includes alerts. if(isset($this->email->alert->trigger) && $this->email->alert->trigger) { mail($this->email->recipient->alert, $this->email->subject->alert, $this->email->output, $this->email->header->alert, '-f'.$this->email->sender->alert); } //Send SMS containing warnings only if threshold includes warnings. elseif((isset($this->email->warning->trigger) && $this->email->warning->trigger) && $this->email->threshold == 0) { mail($this->email->recipient->alert, $this->email->subject->alert, $this->email->output, $this->email->header->alert, '-f'.$this->email->sender->alert); } echo 'Cron job run successfully.'; } } } private function generateReport() { ob_start(); echo '=Services='."\n"; foreach($this->service as $service) { echo $service->name; echo ' | Port: '; switch ($service->status->listen) { case 0: echo 'Up, '; echo 'Listening ('.$service->port.')'; break; case 1: echo 'Down, '; echo 'Not listening ('.$service->port.')'; break; default: echo 'Warning, '; echo 'N/A'; } echo "\n".'Local Connection: '; switch ($service->status->internal) { case 0: echo 'Up, '; echo 'Accepting'; break; case 1: echo 'Down, '; echo 'Rejecting'; break; default: echo 'Warning, '; echo 'N/A'; } echo "\n".'External Connection: '; switch ($service->status->external) { case 0: echo 'Up, '; echo 'Accepting as configured'; break; case 1: echo 'Up, '; echo 'Rejecting as configured'; break; case 2: echo 'Down, '; echo 'Rejecting; Misconfigured'; break; case 3: echo 'Down, '; echo 'Accepting; Misconfigured'; break; default: echo 'Warning, '; echo 'N/A'; } echo "\n\n"; } echo '=System Stats='; echo "\n".'Loads: '; switch ($this->load->status) { case 0: echo 'Up, '; echo $this->loads[1].' '.$this->loads[2].' '.$this->loads[3]; break; case 1: echo 'Warning, '; echo $this->loads[1].' '.$this->loads[2].' '.$this->loads[3]; break; case 2: echo 'Down, '; echo $this->loads[1].' '.$this->loads[2].' '.$this->loads[3]; break; default: echo 'Warning, '; echo 'Error'; } echo "\n".'RAM: '; switch ($this->ram->status) { case 0: echo 'Up, '; echo $this->ram->used.' MB'; break; case 1: echo 'Warning, '; echo $this->ram->used.' MB'; break; case 2: echo 'Down, '; echo $this->ram->used.' MB'; break; default: echo 'Warning, '; echo 'Error'; } echo "\n".'Storage: '; switch ($this->fs->status) { case 0: echo 'Up, '; echo ($this->fs->used >= 1024) ? round($this->fs->used/1024, 2).' GB' : $this->fs->used.' MB'; break; case 1: echo 'Warning, '; echo ($this->fs->used >= 1024) ? round($this->fs->used/1024, 2).' GB' : $this->fs->used.' MB'; break; case 2: echo 'Down, '; echo ($this->fs->used >= 1024) ? round($this->fs->used/1024, 2).' GB' : $this->fs->used.' MB'; break; default: echo 'Warning, '; echo 'Error'; } echo "\n".'Processes: '.$this->processes; echo "\n".'Uptime: '.$this->uptime; echo "\n".'Users Logged In: '.$this->users; echo "\n".'TCP Connections: '.$this->conns->tcp; echo "\n".'UDP Connections: '.$this->conns->udp; echo "\n\n".'=Sites='; foreach($this->site as $site) { echo "\n".$site->name.': '; switch ($site->status) { case 0: echo 'Up, '; echo $site->http->status.' ('.$site->http->desc.')'; break; case 1: echo 'Down, '; echo $site->http->status.' ('.$site->http->desc.')'; break; default: echo 'Warning, '; echo 'Error'; } } $this->email->output = ob_get_clean(); } private function generateAlert() { ob_start(); foreach($this->service as $service) { echo ($service->status->listen >= 1 || $service->status->internal >= 1 || $service->status->external >= 2 || $service->status->listen == -1 || $service->status->internal == -1 || $service->status->external == -1) ? '>'.$service->name : null; echo ($service->status->listen >= 1 || $service->status->listen == -1) ? '|Port:' : null; switch ($service->status->listen) { case 0: break; case 1: echo 'Down:'; echo 'NotListening ('.$service->port.');'; $this->email->alert->trigger = 1; break; default: echo 'Warning:'; echo 'N/A;'; $this->email->warning->trigger = 1; } echo ($service->status->internal >= 1 || $service->status->internal == -1) ? '|LocalConn:' : null; switch ($service->status->internal) { case 0: break; case 1: echo 'Down:'; echo 'Rejecting;'; $this->email->alert->trigger = 1; break; default: echo 'Warning:'; echo 'N/A;'; $this->email->warning->trigger = 1; } echo ($service->status->external >= 2 || $service->status->external == -1) ? '|ExtConn:' : null; switch ($service->status->external) { case 0: break; case 1: break; case 2: echo 'Down:'; echo 'Rejecting,Misconfigured;'; $this->email->alert->trigger = 1; break; case 3: echo 'Down:'; echo 'Accepting,Misconfigured;'; $this->email->alert->trigger = 1; break; default: echo 'Warning:'; echo 'N/A;'; $this->email->warning->trigger = 1; } } echo ($this->load->status >= 1 | $this->load->status == -1) ? '|Loads:' : null; switch ($this->load->status) { case 0: break; case 1: echo 'Warning:'; echo $this->loads[1].' '.$this->loads[2].' '.$this->loads[3].';'; $this->email->warning->trigger = 1; break; case 2: echo 'Down:'; echo $this->loads[1].' '.$this->loads[2].' '.$this->loads[3].';'; $this->email->alert->trigger = 1; break; default: echo 'Warning:'; echo 'Error;'; $this->email->warning->trigger = 1; } echo ($this->ram->status >= 1 || $this->ram->status == -1) ? '|RAM:' : null; switch ($this->ram->status) { case 0: break; case 1: echo 'Warning:'; echo $this->ram->used; $this->email->warning->trigger = 1; break; case 2: echo 'Down:'; echo $this->ram->used; $this->email->alert->trigger = 1; break; default: echo 'Warning:'; echo 'Error;'; $this->email->warning->trigger = 1; } echo ($this->ram->status >= 1 || $this->ram->status == -1) ? 'MB;' : null; echo ($this->fs->status >= 1 || $this->fs->status == -1) ? '|FS:' : null; switch ($this->fs->status) { case 0: break; case 1: echo 'Warning:'; echo ($this->fs->used >= 1024) ? round($this->fs->used/1024, 2).'GB;' : $this->fs->used.'MB;'; $this->email->warning->trigger = 1; break; case 2: echo 'Down:'; echo ($this->fs->used >= 1024) ? round($this->fs->used/1024, 2).'GB;' : $this->fs->used.'MB;'; $this->email->alert->trigger = 1; break; default: echo 'Warning:'; echo 'Error;'; $this->email->warning->trigger = 1; } foreach($this->site as $site) { echo ($site->status >= 1 || $site->status == -1) ? '|'.$site->name.':' : null; switch ($site->status) { case 0: break; case 1: echo 'Down:'; echo $site->http->status.'('.$site->http->desc.');'; $this->email->alert->trigger = 1; break; default: echo 'Warning:'; echo 'Error;'; $this->email->warning->trigger = 1; } } $this->email->output = ob_get_clean(); } } //If running cron job (either through CLI or Web), and type isn't update, send email if needed if((isset($argv[1]) && $argv[1] != 'update') || (isset($_GET['cron']) && $_GET['cron'])) { $email = new EmailOutput(); $email->send(); } //If running cron job (through CLI), and type is update, check for updates, and send email if needed elseif(isset($argv[1]) && $argv[1] == 'update') { $email = new EmailOutput(); $email->update(); } //If checking for updates through AJAX elseif(isset($_GET['update']) && $_GET['update']) { $browser = new BrowserOutput(); $browser->update(); } //If accessing MOSMC directly from browser else { $browser = new BrowserOutput(); $browser->render(); } ?>