OK, I was bored so I spent some time on this today :)
Apparently, there is an inbuilt function within WP to allow the site to go into maintenance mode. All there needs to be is a file in the root of the WP install, and it needs to be named .maintenance
- in the same way .htaccess
files get named with a leading period (this designates the file as hidden) and no extension.
So, create the .maintenace
file in the root of your WP install (should be on the same level as wp-config.php
, wp-login.php
etc). In this file add the following:
<?php $upgrading = time(); ?>
this tells WP the site is in maintenance mode. NOTE: with this file in the directory as-is, the site will be inaccessible.
You can modify the look and feel of the maintenance mode message, and even put a timer on it so that the site will come back on after a certain amount of time. See here for more info.
With this in place, check the site to make sure maintenance mode is coming on. If it is, rename .maintenance
to .maintenance_off
. This will be our default state for this file; it will sit there named .maintenance_off
allowing the site to function normally until you want to turn maintenance mode on when it will be renamed to .maintenance
.
I'm already tired of writing maintenance mode, so from here on in I will be referring to maintenance mode as m-m, ok?
So now for the scripts;
On each of your WP installs that you want to be able to turn this on and off with, you will need 2 things:
- the
.maintenance_off
file explained above;
- a php script to do the renaming:
create a file called remote_maint.php
in the root of your WP install, on the same level as your .maintenance_off
file. In it add the following:
<?php
$p=$_GET;
/*
this is just some basic auth; not safe, not secure, but better than nothing.
Change the key to something more complicated. Though, because we're using GET,
even if it's really complicated, it's still not secure. You should really improve
this if you don't want random people putting your WP installs into maintenance mode...
*/
$key='test';
//if mode==on, use turn_on() function otherwise use turn_off() function
($p['mode']=='on')?turn_on($p):turn_off($p);
function turn_on($p){
//if the key in the request matches our key here, rename the file, otherwise set page header as unauthorized
($p['key']==$key)?rename('.maintenance_off','.maintenance'):header("HTTP/1.0 401 Unauthorized");
}
function turn_off($p){
//if the key in the request matches our key here, rename the file, otherwise set page header as unauthorized
($p['key']==$key)?rename('.maintenance','.maintenance_off'):header("HTTP/1.0 401 Unauthorized");
}
?>
OK, as the comments state, the "security" isn't secure. You should improve it... If it's any consolation, if someone did get the key you decide to use, the worst they could do is put your site into m-m.
What this script does is check the request to the page, example:
http://site.com/remote_maint.php?mode=on&key=test
this request would tell the script that the mode is on
and the key is test
. The first ternary operation will see the mode is on
and call the turn_on()
function, sending with it the $_GET
array which has been assigned to the variable $p
. The turn_on()
function will then check the key sent in the request ($p['key']
) against the key set at the top of the script ($key
); if it matches it will rename .maintenance_off
to .maintenance
effectively turning m-m on. If the key does not match the request, it sets the header of the page to 401 Unauthorized
, see below.
With this all in place, time for the Central Command; the code that will be doing the calling. In my testing, I went with jQuery so that it would be possible to turn m-m on and off on multiple sites from the same page without reloading.
On another site, or wherever you want to administer the m-m, create a page called remote_maint_admin.php
(actually it doesn't have to be .php, can be .html, or whatever), and add the following:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Remote Maintenance</title>
<script src="js/jquery.js"></script>
</head>
<body>
<div id='main'>
<fieldset>
<legend>site 1</legend>
<div id='site-1' style='border:0px solid #000'>
Auth key:
<input type="text" id='key-1' size="30"/>
<input type="button" value="Turn on" onClick="change_mode('on','http://site.com/','1');" />
<input type="button" value="Turn off" onClick="change_mode('off','http://site.com/','1');" />
</div>
<br>
<div id='status-1' style='border:1px solid #ccc;color:#666'>Status</div>
</fieldset>
</div>
<script>
function change_mode(mode,url,id){
var key = $('#key-'+id).attr('value');
var url=url+'remote_maint.php?mode='+mode+'&key='+key;
$.ajax({
url:url,
type: 'GET',
complete: function(){
$('#status-'+id).html('<b>Request Completed');
},
});
}
</script>
</body>
change http://site.com/
to your url. To add more sites, copy the main div and repeat it:
<div id='main'>
<fieldset>
<legend>site 2</legend>
<div id='site-2' style='border:0px solid #000'>
Auth key:
<input type="text" id='key-2' size="30"/>
<input type="button" value="Turn on" onClick="change_mode('on','http://site2.com/','2');" />
<input type="button" value="Turn off" onClick="change_mode('off','http://site2.com/','2');" />
</div>
<br>
<div id='status-2' style='border:1px solid #ccc;color:#666'>Status</div>
</fieldset>
</div>
here's another happy little div over here to manage another site
<div id='main'>
<fieldset>
<legend>site 3</legend>
<div id='site-3' style='border:0px solid #000'>
Auth key:
<input type="text" id='key-3' size="30"/>
<input type="button" value="Turn on" onClick="change_mode('on','http://site3.com/','3');" />
<input type="button" value="Turn off" onClick="change_mode('off','http://myothersite.com/','3');" />
</div>
<br>
<div id='status-3' style='border:1px solid #ccc;color:#666'>Status</div>
</fieldset>
</div>
...and change the input id number (e.g. id='key-1'
to id='key-2'
and status id number (e.g. id='status-1'
to id='status-2'
and the javascript call (e.g onClick="change_mode('on','http://site.com/','1');"
to onClick="change_mode('on','http://myothersite.com/','3');"
respectively for each site you want to add...
Now when you enter your key into the textbox and hit Turn on or Turn off, the js will take your key and the mode (depending on which button you hit) and send it to the other server. If the key matches, m-m will be turned on or off, and the div below the buttons will update and say that the request completed. If the key doesn't match, The div below the buttons will still say request completed, though m-m won't change. I was thinking I could update the status div with the returned status code of the page which is why I set the header to 401 if it failed, but because of the same origin policy, cross site request status codes are always returned as 0
. However, if you use a tool like Firebug, you can watch the console there to see if the request actually fails...
HTH