We found ourselves recently wanting to better monitor our dedicated Linux servers, specifically Apache and MySQL. There are many paid-for services out there, but with these services being hosted elsewhere they cannot attempt an automatic restart of the affected services. To solve this we have quickly rattled out a PHP script designed to be run from command line, php-cli. It works for us, it may be a solution for you. It is designed to work on our set-ups so there are some assumptions made:
- You have PHP-CLI installed
- You have access to create a new CRONTAB entry
- mail() function works on your box
- It uses fopen(), fwrite() and file_get_contents() to store information in a serialized data file and exec() to restart services
- This has only been tested on our Linux Ubuntu boxes, it may work elsewhere and is basic so probably will.
We will update this in future, but for now you may find it useful, let us know:
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
### Created by Stuart Cross of Motionlab www.motionlab.co.uk - Do what you want with it! (But please keep my name and Motionlab in as credit)
### Simple mysql and Apache status checker
### Restarts services automatically if required.
### Excuse the coding - mostly typed in one hit off-the-cuff
### Place file in root home folder ~/ or in the Path if you wish
### chmod 755 service_monitor.php
### Call with a crontab e.g. (for 5 minute checks)
### */5 * * * * root php ~/service_monitor.php >> /var/log/service_monitor.log
###
### Call more often if you like - but advisable to set $failsBeforeEmail higher e.g. 10
### If this file has to run in 'limited mode' - it's because it cannot use a file as data storage and will therefore run singularly,
### with no memory of previous fails or sent emails.
### So sending an email on every single fail.
###
### This service monitor requires CURL installed on the server, and mail() function to be working
###
### SETTINGS
### Identifier or name of this server - So you know where you got the email from!
$serverName = 'YourServerName';
### Web monitor company name
$coName = 'YourCompany';
### Server admin emails - get email every fail - a heads up before the client if you want.
$adminEmails = array('yourEmail@yourdomain.co.uk');
### All the email addresses that will be informed of the Fail/Restart of Apache
$apacheEmails = array('yourEmail@yourdomain.co.uk','yourclientsemail@theirdomain.co.uk');
###
### All the email addresses that will be informed of the Fail/Restart of MySQL
$mysqlEmails = $apacheEmails;
###
### Mail successful Apache responses (Warning: You will get email every 5 minutes! Use for check on first install)
$onApacheSuccess = false;
### Mail successful MySQL responses (Warning: You will get email every 5 minutes! Use for check on first install)
$onMysqlSuccess = false;
#### Number of fails before sending an email - Minimum of 1
$failsBeforeEmail = 2;
###
#### CHECK MySQL?
$checkMysql = true;
#### CHECK Apache?
$checkApache = true;
###
#### RUN limited (No file access for database)? Can't think of a reason why you would manually set this true
$limitedMode = false;
###
#### Mysql Credentials
$host = 'localhost';
$user = 'service_monitor';
$pass = 'service';
### Apache Test URL - Set this url to a small file that won't disappear - if it is deleted you will get a lot of email and Apache will keep restarting!
$apacheTestUrl = 'http://yourdomain/img/transparent.gif';
### Path to file used for stats keeping - leave it like this to store in the same folder as this script
$dataStore = 'monitor.data';
if(!$limitedMode)
{
### If database file doesn't exist create it
if(!is_file($dataStore))
{
if(!$fh = fopen($dataStore, 'w'))
{
echo("can't create data storage file - Running in limited mode.\r\n");
$limited = true;
}
else
{
$limited = false;
}
$data = array('SM'=>array());
fwrite($fh, serialize($data));
fclose($fh);
}
else
{
### Read database file
if(!$data = file_get_contents($dataStore))
{
echo("can't open data storage file - Running in limited mode.\r\n");
$limited = true;
}
else
{
$limited = false;
$data = unserialize($data);
}
}
}
else
{
$limited = true;
}
### Make sure no-one ignores the instructions!
if($failsBeforeEmail==0)$failsBeforeEmail=1;
### If we have no database file - make a quick fake one
if($limited)$data = array('SM'=>array());
##############################
####### Apache Checker - This is usually kicked off by Apache hitting MaxClients - Or when services restart during the night
##############################
if($checkApache)
{
$ch = curl_init($apacheTestUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($ch);
$status = curl_getinfo($ch);
curl_close($ch);
if($status['http_code']==200)
{
$data['SM']['Apache']['TotalSuccessCounter']++;
if((isset($data['SM']['Apache']['hasFailed']) && $data['SM']['Apache']['hasFailed']==true) && !$limited)
{
$data['SM']['Apache']['hasFailed'] = false;
$data['SM']['Apache']['FailCounter'] = 0;
if($data['SM']['Apache']['EmailSent'] == true)
{
foreach($apacheEmails as $e)
{
mail($e,$coName.' WEB MONITOR: '.$serverName.' Apache Web Server is working correctly again',print_r($status,true)."\r\n\r\n\r\n".$serverName);
}
}
else
{
### Admin heads-up email
foreach($adminEmails as $e)
{
mail($e,'*ADMIN* '.$coName.' WEB MONITOR: '.$serverName.': Apache Web Server is working correctly again.',"The quiet Apache restart seems to have worked"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
}
}
$data['SM']['Apache']['EmailSent'] = false;
echo("\r\n".date('r',mktime()).': Apache is back up!'."\r\n");
}
if($onApacheSuccess)
{
foreach($apacheEmails as $e)
{
mail($e,$coName.' WEB MONITOR: '.$serverName.' Apache Web Server is working correctly',print_r($status,true)."\r\n\r\n\r\n".$serverName);
}
}
echo("\r\n".date('r',mktime()).': Apache connected');
}
else
{
$data['SM']['Apache']['TotalFailCounter']++;
$data['SM']['Apache']['FailCounter']++;
$outputStop = array();
$outputStart = array();
################### TURN OFF WHEN DEBUGGING #########################
exec('apache2ctl -k restart',$outputStop);
#####################################################################
### Admin heads-up email
foreach($adminEmails as $e)
{
mail($e,'*ADMIN* '.$coName.' WEB MONITOR: '.$serverName.': Apache Web Server has been automatically restarted: You should probably check the website is operating correctly.',"THIS IS AN ADVANCED WARNING SENT ON EVERY FAIL, YOU COULD WAIT FOR AN AUTOMATIC RETURN TO SERVICE"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
}
if(($data['SM']['Apache']['FailCounter']==$failsBeforeEmail) || $limited)
{
$data['SM']['Apache']['FailCounter'] = 0;
$data['SM']['Apache']['EmailSent'] = true;
foreach($apacheEmails as $e)
{
### If it hasn't failed on the previous call this is a new Apache outage
if(!$data['SM']['Apache']['hasFailed'] || $limited)
{
mail($e,$coName.' WEB MONITOR: '.$serverName.': Apache Web Server has been automatically restarted: You should probably check the website is operating correctly.',print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
}
else
{
### This is a continuance of an Apache outage
mail($e,$coName.' WEB MONITOR: '.$serverName.': Apache Web Server appears to be STILL down after restart - ADMIN REQUIRED',"Apache has either failed to come back up after restart, or has failed again between checks - ADMIN REQUIRED"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
}
}
}
if(!$data['SM']['Apache']['hasFailed'])$data['SM']['Apache']['hasFailed'] = true;
echo("\r\n".date('r',mktime()).': not connected');
}
}
##############################
####### MySQL Checker
##############################
if($checkMysql)
{
$output = array();
$error = '';
if($db = mysql_connect($host,$user,$pass))
{
$data['SM']['Mysql']['TotalSuccessCounter']++;
if((isset($data['SM']['Mysql']['hasFailed']) && $data['SM']['Mysql']['hasFailed']==true) && !$limited)
{
$data['SM']['Mysql']['hasFailed'] = false;
$data['SM']['Mysql']['FailCounter'] = 0;
if($data['SM']['Apache']['EmailSent'] == true)
{
foreach($mysqlEmails as $e)
{
mail($e,$coName.' WEB MONITOR: '.$serverName.' MySQL Database is working correctly again',print_r($error,true)."\r\n\r\n\r\n".$serverName);
}
}
else
{
### Admin heads-up email
foreach($adminEmails as $e)
{
mail($e,'*ADMIN* '.$coName.' WEB MONITOR: '.$serverName.': MySQL Database is working correctly again.',"The quiet Mysql restart seems to have worked"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
}
}
$data['SM']['Mysql']['EmailSent'] = false;
echo("\r\n".date('r',mktime()).': MySQL is back up!'."\r\n");
}
if($onMysqlSuccess)
{
foreach($mysqlEmails as $e)
{
mail($e,$coName.' WEB MONITOR: '.$serverName.' MySQL Database is working correctly',print_r($error,true)."\r\n\r\n\r\n".print_r($output,true));
}
}
echo("\r\n".date('r',mktime()).': MySQL connected success');
}
else
{
$data['SM']['Mysql']['TotalFailCounter']++;
$data['SM']['Mysql']['FailCounter']++;
$data['SM']['Mysql']['EmailSent'] = true;
$error = mysql_error();
### Admin heads-up email
foreach($adminEmails as $e)
{
mail($e,'*ADMIN* '.$coName.' WEB MONITOR: '.$serverName.': MySql has been automatically restarted: You should probably check the website is operating correctly.',"THIS IS AN ADVANCED WARNING SENT ON EVERY FAIL, YOU COULD WAIT FOR AN AUTOMATIC RETURN TO SERVICE"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
}
################### TURN OFF WHEN DEBUGGING #########################
exec('/etc/init.d/mysql restart',$output);
#####################################################################
if(($data['SM']['Mysql']['FailCounter']==$failsBeforeEmail) || $limited)
{
$data['SM']['Mysql']['FailCounter'] = 0;
foreach($mysqlEmails as $e)
{
### If it hasn't failed on the previous call this is a new MySql outage
if(!$data['SM']['Mysql']['hasFailed'] || $limited)
{
mail($e,$coName.' WEB MONITOR: '.$serverName.': MySQL Database has been automatically restarted. You should probably check the website is operating correctly',print_r($error,true)."\r\n\r\n\r\n".print_r($output,true));
}
else
{
### This is a continuance of a MySql outage - or limited mode
mail($e,$coName.' WEB MONITOR: '.$serverName.': MySql Database appears to be STILL down after restart - ADMIN REQUIRED',"MySql has either failed to come back up after restart, or has failed again between checks - ADMIN REQUIRED"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
}
}
}
if(!$data['SM']['Mysql']['hasFailed'])$data['SM']['Mysql']['hasFailed'] = true;
echo("\r\n".date('r',mktime()).': MySQL not connected - FAIL');
}
}
###Save data for next run
if(!$limited)
{
$fh = fopen($dataStore, 'w');
fwrite($fh, serialize($data));
fclose($fh);
}
die();

The ICO ignore their new Cookie law!
Wednesday, May 25th, 2011Today the law changed in the UK and Europe as a whole with regards cookies. To be enforced by the Information Commissioner’s Office.
In theory all websites must request permission from the user to set a cookie on the users machine unless the cookie is for a service explicitly requested by the user i.e. adding an item to a basket.
I have a few issues with this:
1. Practically all Content Managed sites start a session with a session cookie before the first page has loaded. How do we ask permission for this? Or are we to re-code every site we have built or manage so we don’t set it until we have permission.
2. If the user doesn’t give us permission what should we do? Just leave a popup on screen asking for permission whilst still allowing full function of the site, or kick them off?
3. The ICO have no idea how to be completely compliant yet, EVEN THOUGH THIS IS NOW LAW with regards 3rd party cookies:
“This may be the most challenging area in which to achieve
compliance with the new rules and we are working with industry
and other European data protection authorities to assist in
addressing complexities and finding the right answers.”
4. Should we ask permission to set a cookie to remember the user has been asked permission? I don’t want the same user to keep getting the same request, even though they will every time they use another machine/browser/device or empty their cookies!
5. In theory it is acceptable that permission can be obtained in the web browser, BUT to quote the ICO:
“At present, most browser settings are not sophisticated enough to allow you to assume that the user has given their consent to allow your website to set a cookie”
6. THE BIGGIE! The ICO website itself www.ico.gov.uk sets a session cookie before having my permission. If this is acceptable you have just created another repetitive annoying popup for no reason!
I could imagine some bright spark coming up with this legislation in the 90’s, the early days, but to do it now, when most web sites are dynamic, intelligent and in the true spirit of web 2.0 share information to enhance the user experience seems stupid!
To quote Al Murray, the pub landlord:
“BACK OFF BRUSSELS!”
ICO Document on this subject
Tags: cookie law, cookies, ico, information commissioner's office, law
Posted in Code, Industry Comment | No Comments »