lime icon

Phosphorus and Lime

A Developer's Broadsheet

This blog has been deprecated. Please visit my new blog at klenwell.com/press.
wikka makeover
I like the wikka wiki engine because it is written in PHP/MySQL and does all the things I want a wiki to do but is a lot smaller than the feature-heavy wikimedia engine.

I also like the philosophy behind its simple look and interface but decided I wanted to change it around a little. The end result actually looks a lot like the wikimedia interface but gives you a few more options in customizing your layout:



Details here:

klenwell.net/is/
klenwell.net redesign
Been redesigning klenwell.net in the in-between times over the last couple weeks. The theme is appropriately wintery. Plan to invest more time in coming year in transforming it into my flagship site.
PHP/MySQL: mysqldump automated backup script
This based on the script I found here:

http://blog.tvlgiao.com/2006/05/09/php-cron-job-backups.html

I've simply cleaned up the code a bit, added some sanity checks, and focused it on databases.

It does the following things:

1) backup 1 or more databases
2) option to do all tables in db or selected ones
3) compress files
4) email compressed files as attachment

It can be called directly from the browser but is best utilized as a cron job.

<?php

$_tx1 = microtime();

// ** Documentation
/*______________________________________________________________________________

AMVC MySQL Backup Script

Last Update: Dec 2006
Author: Tom at klenwell@gmail.com

SUMMARY
A simple mysql backup script designed to do the following things:

- backup 1 or more databases
- option to do all tables in db or selected ones
- compress files
- email compressed files as attachment

NOTES
Requires system() function and your db user must have sufficient privileges

Can be called directly (useful for testing) but intended for cronjob usage

Sample $_CFG['DB'] settings:
1) 'db1' => '*', -> backs up selected table inside the array
2) 'db2' => array('table1', 'table2'), -> backs up all tables in database

Note: keys (database names) must be different -- if duplicated, only the last one
will run

CREDIT
Giao Trinh (http://blog.tvlgiao.com/2006/05/09/php-cron-job-backups.html)

LICENSE
GPL (http://www.opensource.org/licenses/gpl-license.php)

______________________________________________________________________________*/


// *** PRE-SCRIPT (Configuration)
/*____________________________________________________________________________*/

// keep it safe!
$_CFG['db_user'] = '';
$_CFG['db_pass'] = '';
$_CFG['email_to'] = '';
$_CFG['email_subject_prefix'] = date('Ymd') . ' mysqldump';
$_CFG['email_from'] = 'amvc-mysqldump-client';

// databases and tables ( keys=databases, values=array( tables ) or * - all tables )
$_CFG['DB'] = array
(
#'db1' => '*',
#'db2' => array( 'table1', 'table2' ),
);

// Flags
$_FLAG['tar'] = 1; // tar compress?
$_FLAG['debug'] = 0; // outputs command line (with password!)

// path to mysqldump
$_CFG['md_path'] = '/usr/local/bin/mysqldump';

// mysql dump default options (see http://dev.mysql.com/doc/refman/4.1/en/mysqldump.html)
$_CFG['md_opt'] = '--opt --quote-names';


// internal variables
$tbl_cmd = '';
$tbl_list = '';
$_subject = '';

/*============================================================================*/


// *** Backup Script
/*____________________________________________________________________________*/

// sanity check
if ( empty($_CFG['DB']) || !is_array($_CFG['DB']) )
{
trigger_error('no databases set -- please update config settings', E_USER_WARNING);
die(' -> aborting script');
}

// set user and password
if ( !empty($_CFG['db_user']) && !empty($_CFG['db_pass']) )
{
$login_cmd = "-u {$_CFG['db_user']} -p{$_CFG['db_pass']}";
}
else
{
trigger_error('user name or password empty -- please update config settings', E_USER_WARNING);
die(' -> aborting script');
}

foreach ( $_CFG['DB'] as $db_name => $_TABLE )
{
// start timer
$_t1 = microtime();

// set tables
if ( $_TABLE == '*' )
{
$tbl_cmd = '';
}
elseif ( is_array($_TABLE) )
{
$tbl_list = implode(' ', $_TABLE);
$tbl_cmd = " --tables $tbl_list";
}
else
{
trigger_error("invalid table settings for db $db_name, will back up all tables", E_USER_WARNING);
$tbl_cmd = '';
}

// set file name
$_sql_file = $db_name . '.sql';
$_tar_file = $db_name . '.tar.gz';

// build mysqldump command
$sql_cmd = "{$_CFG['md_path']} {$_CFG['md_opt']} $login_cmd -B $db_name{$tbl_cmd} > $_sql_file";
if ( $_FLAG['debug'] ) echo "<p style='font-size:11px; color:#ccc;'>mysql dump command: <code>$sql_cmd</code></p>";

// run mysqldump
system($sql_cmd);

// run tar
if ( $_FLAG['tar'] ) system("tar -zcf $_tar_file $_sql_file");

// mail file as attachment

// which file
$_attach_file = ( $_FLAG['tar'] ) ? $_tar_file : $_sql_file;

// create attachment and mail
if ( !empty($_CFG['email_to']) )
{
$_subject = $_CFG['email_subject_prefix'] . ' for db ' . $db_name . ' : ' . $_attach_file;
mail_attachment($_CFG['email_to'], $_CFG['email_from'], $_subject, '', $_attach_file);
}
else
{
trigger('no email set -- please update config settings', E_USER_WARNING);
}

// remove file
system("rm $_sql_file");
if ( $_FLAG['tar'] ) system ("rm $_tar_file");

// end timer
$_t2 = microtime();
$_t3 = number_format(((substr($_t2,0,9)) + (substr($_t2,-10)) - (substr($_t1,0,9)) - (substr($_t1,-10))),4);
echo "<p>db <b>{$db_name}</b> backed up in <b>{$_t3}</b> s</p>";
}

/*============================================================================*/


// *** Post-Script
/*____________________________________________________________________________*/

$_tx2 = microtime();
$_tx3 = number_format(((substr($_tx2,0,9)) + (substr($_tx2,-10)) - (substr($_tx1,0,9)) - (substr($_tx1,-10))),4);
echo "<p style='color:green;'>backup script completed in $_tx3 s</p>";
echo '<h6>end script</h6>';

/*============================================================================*/



// *** fx mail_attachement
// credit: Giao Trinh (http://blog.tvlgiao.com/2006/05/09/php-cron-job-backups.html)
/*____________________________________________________________________________*/

function mail_attachment($email, $from = '', $subject = '', $body = '', $file = '')
{
$_debug = 0;
$boundary = '-----=' . md5( uniqid ( rand() ) );

if ($file) {
$basename = basename($file);
$message .= "--".$boundary."\n";
$message .= "Content-Type: application/binary; name=\"$basename\"\n";
$message .= "Content-Transfer-Encoding: base64\n";
$message .= "Content-Disposition: attachment; filename=\"$basename\"\n\n";

$content = file_get_contents($file);
$content_encode = chunk_split(base64_encode($content));
$message .= $content_encode . "\n\n";
}

if ($body) {
# Text Version
$message .= "--".$boundary."\n";
$message .= "Content-Type: text/plain; charset=iso-8859-1\n";
$message .= "Content-Transfer-Encoding: 8bit\n";
$message .= "This is a multi-part message in MIME format.\n";
$message .= strip_tags($body)."\n\n";

# HTML Version
$message .= "--".$boundary."\n";
$message .= "Content-Type: text/html; charset=iso-8859-1\n";
$message .= "Content-Transfer-Encoding: 8bit\n";
$message .= $body."\n\n";
}

# Finished
$message .= "--".$boundary."--\n\n"; // finish with two eol's for better security. see

$headers = '';
if ($from)
$headers .= "From: $from" . "\r\n";
$headers .= "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"";
if ( !mail($email, $subject, $message, $headers) )
{
trigger_error('mail failed', E_USER_WARNING);
return 0;
}
if ( $_debug ) echo "<pre>$message\n*************</pre>";
return 1;
}

/*============================================================================*/

?>