Today, I logged into one server to have a rummage and see if I could free up some disk space… on a whim I do an ‘ls’ of /tmp and find a file called ‘att1.txt’. Hmm. Lets take a look – ‘head att1.txt’ gave :
# 0ldW0lf – email@example.com
# – www.atrix-team.org
Ah, pants. Timestamp on the file matches a request to a Zen-cart instance :
... POST http://....../admin/record_company.php/password_forgotten.php?action=insert
... POST http://..../index.php?main_page=products_all/admin/record_company.php/password_forgotten.php?action=insert
... GET /index.php?main_page=products_all/images/6e072.php?site=http://...../index.php?main_page=products_all/images /6e072.php
It turns out there was a security update for Zen-cart sometime ago – see http://www.zen-cart.com/forum/showthread.php?t=130161
Suffice to say the various attackers had left a few files on the filesystem; thanks to ‘find -user www-data’ these were easy to find and remove. Interestingly Zen-Cart suggests you rename the ‘admin’ directory – I wonder how many people don’t (in this case) or do it to e.g. ‘admin.old’ …
Here’s a short python script I must have knocked up some time ago – and totally forgotten – hopefully it’ll be of some use to others….
Purpose: backup all MySQL databases, one in each file with a timestamp on the end. You’ll probably want to have a secondary cron job which does something like :
find /backups/mysql -mtime +5 -print | xargs -r rm
to delete old copies… changing +5 to how ever many days history you wish to have.
Method: Read /etc/mysql/debian.cnf to get login details for MySQL, connect to MySQL and ask it for a list of all databases, go through this list calling mysqldump on each one.
(Last updated: 2012/10/10 – skip trying to backup the performance_schema).
# On Debian, /etc/mysql/debian.cnf contains 'root' a like login and password.
config = ConfigParser.ConfigParser()
username = config.get('client', 'user')
password = config.get('client', 'password')
hostname = config.get('client', 'host')
filestamp = time.strftime('%Y-%m-%d')
# Get a list of databases with :
database_list_command="mysql -u %s -p%s -h %s --silent -N -e 'show databases'" % (username, password, hostname)
for database in os.popen(database_list_command).readlines():
database = database.strip()
if database == 'information_schema':
if database == 'performance_schema':
filename = "/backups/mysql/%s-%s.sql" % (database, filestamp)
os.popen("mysqldump -u %s -p%s -h %s -e --opt -c %s | gzip -c > %s.gz" % (username, password, hostname, database, filename))
Annoyingly the current version of the google-news-sitemap plugin for WordPress (v1.4) doesn’t work with some silly XML namespace error reported by google.
See http://wordpress.org/support/topic/364929 and effectively the ‘patch’ on the Google Support forum thing which works fine (there are two bits of the plugin which need updating – whcih correlate to the two parts mentioned in the posting etc)
Bit annoyed that the fix is so easy – yet the plugin hasn’t been updated yet. Grr.
Sam made some changes to a SOAP service one customer has – and suddenly our automated tests kept failing. “WTF?” we thought.
We persistently got the same error (e.g. Fatal error: SOAP-ERROR: Encoding: object hasn’t ‘SortResults’ property in ….) yet the generated WSDL file (when viewed through a web browser etc) no longer has SortResults in it.
We checked :
- Proxy settings,
- Apache configuration (and restarted Apache)
- svn reverted files
- DNS and more.
Then it turned out the SoapClient PHP object caches the WSDL file by default in e.g. /tmp/wsdl-blahblahblah. (Where blahblahblah looks very much like an md5). And it doesn’t make much of an effort to check it’s validity. Obviously the documentation does state this, but it does seem like the wrong default behaviour to me.
Solution: Add something to the automated tests to delete /tmp/wsdl-*. OR pass into the SoapClient constructor an array of options like :
$client = new SoapClient('http://somewhere/blah.php?wsdl", array(cache_wsdl => WSDL_CACHE_NONE)
Time wasted: Too much.
I don’t normally do anything with WordPress from a work point of view – I’ve always left such work to ‘designer’ types…
Anyway, yesterday I had a referral for someone who has two fairly busy websites (anorak.co.uk / whoateallthepies.tv) sat on a fairly beefy server (8 core, 16g of ram… oh in a few years that’ll be entry level… but I digress)… anyway, they were having performance difficulties with one site – a bit of investigation found the problem to be related to their migration from one server to another – rinetd was directing traffic from the old server, but had filled the filesystem up and was consuming all cpu time …… Easy enough to fix. Job done. Everything started working again.
After a bit more investigation I found that the two sites needed updates applying and plugins upgraded, and they had no backup job in place *doh* …. Clone the site, whizz through the wordpress upgrade routine on the clone, get the customer to OK it (he did) and then we did it on the live server…. and it looked like a success. Until an hour after I’d done the update and the customer realised part of his front page was missing….
Great. Just what I’d hoped to avoid – delving into wordpress’s code.
On opening up the theme’s index.php file it was easy to see where the content should be – add in some debugging on the clone – and “Oh look – that ‘thing’ is empty.. it should contain ‘stuff’….”
Turns out there’s a WP_Query class; and it seems WordPress 2.9.x treats it’s query slightly differently to previous versions – ‘they’ used category_name=blah as a parameter – this no longer works, instead it needed changing to cat=1234 .. bingo, data returned; site fixed; customer happy.
I breathed a big sigh of relief. I was worried that they previous developers had made some weird customisation to wordpress core which I’d have to forward port and debug/fix.
Being the nice chap I am, I also installed xcache onto the server to help PHP out – I suspect they could cut their hardware ‘allocation’ by half and still have ample capacity to serve the sites. A few days with munin running and I’ll know for certain. Perhaps they’ll appreciate the cost saving?