lime icon

Phosphorus and Lime

A Developer's Broadsheet

This blog has been deprecated. Please visit my new blog at klenwell.com/press.
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;
}

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

?>