Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 786
  • Last Modified:

PHP Script to save website backup by day of the month format

Hi,

I have a backup script bkp.php which when run, takes a dump of the website and it's database and stores it into a folder every day of the week.

MyBackup \ Domain \ Day of the Week \ <backup-file>

I want to change it where it should backup every day of the month and save the files in a folder structure like this:

MyBackup \ Domain \ Day of the Month \ <backup-file>

e.g.: MyBackup\website1.com\03\mybackup.tar.gz

Can someone guide what I should change to make this happen?


<?php
/*** BEGIN CONFIG ***/

// WHM CPANEL account details
$reseller = 'cx7.reseller.com';//your reseller url
$whmUser = 'username';//your web host manager user name
$whmPass = 'password';//your web host manager password
$bkUpReseller = false;//backup the reseller account also? (it's not in the listaccts page)
$resellerCpTheme = 'x3';//if you want to back up reseller, we need the reseller cpanel theme


// FTP Details
$destType = 'ftp';//^^^
$destPort = '21';
$destServer = 'ftp.dyndns.org';//only if $destServer = 'ftp' or 'passiveftp'
$destUser = 'username';//only if $destServer = 'ftp' or 'passiveftp'
$destPass = 'password';//only if $destServer = 'ftp' or 'passiveftp'
$destEmail = 'email@email.com';//optional; cpanel will send an email when generation is complete

$logType = 'file';//output a log to 'file' or 'echo' or 'none'(no log)

//add date_timestamp to fileName
$datetimefile = date('l_j_F_Y_his_A');

$logFileName = 'bkup_full_log-'.$datetimefile.'.txt';//can include a path too; only makes sense if $logType = 'file'
//$logFileName = 'bkup_full_log.txt';

$useSsl = false;//if true, requires SSL on your site, or modify this script to use the shared SSL; this hasn't really been tested

/*
A comma-separated list of domain names to backup;
Leave blank to backup all domains found in reseller WHM
If not blank, ONLY the domains listed will be backed up.
If listed, the domains must be listed EXACTLY like they appear on the
list accounts page in WHM, i.e. usually without 'www.'
$domains = 'example1.com,example2.net';
*/

$domains = 'website1.com,website2.com';

/*** END CONFIG ***/

/*** BEGIN MAIN ***/
set_time_limit(0);

$time_start = getMicroTime();

if (!extension_loaded('curl')) 
{
	dl('php_curl.' .PHP_SHLIB_SUFFIX) or die("Could not load curl extension");
}

//Check SSL usage
if($useSsl) 
{
	$protocol = 'https://';
	$cpPort = '2083';
	$whmPort = '2087';
	writeLog("Using SSL.\r\n");
}
else 
{
	$protocol = 'http://';
	$cpPort = '2082';
	$whmPort = '2086';
	writeLog("Not using SSL.\r\n");
}

$domains = trim($domains);
if(!empty($domains))
	{
	$chkDoms = true;
	$domains = explode(',',$domains);
	foreach($domains as $d)
	{
		$domains[] = trim($d);
	}
}
else 
{
	$chkDoms = false;
	$domains = array();
}


//get the WHM 'list accounts' page
writeLog("Retrieving WHM accounts page...\r\n");

$acctsPage = getByCurl("$protocol$reseller:$whmPort/scripts/fetchcsv",$whmUser,$whmPass);

//var_dump($acctsPage);

$accounts = array();
$accounts = explode("\n", trim($acctsPage));
//var_dump($accounts);

$account_records = array();

foreach ($accounts as $row) 
{
	$account_records[] = explode(',', $row);
}

writeLog("Parsing accounts...\r\n");

foreach($account_records as $match) 
{

	$accDom = '';
	$accUser = '';
	$accTheme = '';
	$r = '';
	$fullUrl = '';

	$accDom = strip_tags(trim($match[0]));//domain
	if($chkDoms)
		if(!in_array($accDom,$domains)) continue;
	
	$accUser = strip_tags(trim($match[2]));//username
	$accTheme = strip_tags(trim($match[9]));//cpanel theme

//////////////// Start FTP configuration to put dumps in the form of domain/day
date_default_timezone_set('EST');
$day = strtolower(date('l'));
$dayofweeknumber = strtolower(date('N'));
$dst_dir = 'MyBackup/'.$accDom.'/'.$dayofweeknumber.'-'.$day;
$dir = $dst_dir;

$conn_id = ftp_connect($destServer) or die("Couldn't connect to $destServer");

// try to login
if (@ftp_login($conn_id, $destUser, $destPass))
{
	writeLog("------------------------------\r\n");
	writeLog("Start Backup of $accDom\r\n");
	writeLog("Connected as $destUser @ $destServer\r\n");

	$ar_files = ftp_nlist($conn_id, $dst_dir);

	if (is_array($ar_files))
	{ // makes sure there are files
		for ($i=0;$i<sizeof($ar_files);$i++)
		{ // for each file
			$st_file = basename($ar_files[$i]);

			if($st_file == '.' || $st_file == '..') continue;

			if (ftp_size($conn_id, $dst_dir.'/'.$st_file) == -1)
			{ // check if it is a directory
				WriteLog("Recursive Removing -> \r\n");
				WriteLog($dst_dir."/".$st_file." \r\n");
				ftp_rmAll($conn_id, $dst_dir.'/'.$st_file); // if so, use recursion
			}
			else
			{
				WriteLog("Removing -> \r\n");
				WriteLog($dst_dir."/".$st_file." \r\n");
//				WriteLog("Removed \r\n");

				ftp_delete($conn_id, $dst_dir.'/'.$st_file); // if not, delete the file
			}
		} // end for each
	} // end is_array

	$flag = ftp_rmdir($conn_id, $dst_dir); // delete empty directories
}
else
{
	header ("location : http://localhost/bkp.php");
}

if ( @ftp_chdir( $conn_id, $dir ) )
{
	$original_directory = ftp_pwd( $conn_id );
	// If it is a directory, then change the directory back to the original directory
	ftp_chdir( $conn_id, $original_directory );
}
else
{
	// try to create the directory $dir
	if (ftp_mkdir($conn_id, $dir))
	{
		writeLog("Successfully created ".$dir."\r\n");
	}
	else
	{
		writeLog("There was a problem while creating ".$dir."\r\n");
	}
}

// close the connection
ftp_close($conn_id);


////////////////


	$fullUrl = "$protocol$accDom:$cpPort/frontend/$accTheme/backup/dofullbackup.html";
	
	writeLog("Requesting backup of $accDom...\r\n");
	
// Start POST FIELDS
	$postFields = '';
	$postArray = array();
	$postArray['dest'] = $destType;
	$postArray['server'] = $destServer;
	$postArray['user'] = $destUser;
	$postArray['pass'] = $destPass;
	$postArray['email'] = $destEmail;
	$postArray['port'] = $destPort;
	$postArray['rdir'] = $dir;


	$thingy = '';
	foreach ($postArray as $k=>$v)
	{
		$thingy.= "$k=".utf8_encode($v).'&';
	}

	$postFields = substr($thingy,0,-1);
// End POST FIELDS

	$r =& getByCurl($fullUrl,$accUser,$whmPass,array('CURLOPT_POST'=>$postFields));
	
	if($r === false)
	{
		writeLog("Backup request of $accDom caused an unknown error.\r\n");
	}
	else 
	{
		writeLog("Backup request of $accDom complete.\r\n");
	}

	writeLog("End Backup of $accDom\r\n");
	writeLog("------------------------------\r\n");


}

$time_end = getMicroTime();
$time = $time_end - $time_start;
writeLog("Elapsed time: ".round($time,2)." seconds.\r\n");

/*** BEGIN FUNCTIONS ***/

function getByCurl($url, $user = '', $pass = '',$extra = '') 
{
	global $useSsl;

	$ch = curl_init();
	//tells curl to save result in a variable instead of outputing to page
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_USERPWD, "$user:$pass");
	curl_setopt ($ch, CURLOPT_COOKIEJAR, './cookie.txt');
	curl_setopt ($ch, CURLOPT_FOLLOWLOCATION,1);

	if(!empty($extra) && is_array($extra))
	{
//		echo "<hr>";
//		var_dump($extra);
//		echo "<hr>";
		foreach($extra as $opt=>$val)
		{
			switch($opt)
			{
				case 'CURLOPT_REFERER':
					curl_setopt($ch,CURLOPT_REFERER,$val);
				break;
				case 'CURLOPT_POST':
				case 'CURLOPT_POSTFIELDS':
					curl_setopt($ch,CURLOPT_POST,1);
					curl_setopt($ch,CURLOPT_POSTFIELDS,$val);
				break;
			}
		}
	}

	if($useSsl)
	{
		curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
		curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
	}

	$result = curl_exec($ch);
	curl_close($ch);

	return $result;
}

function writeLog($entry) 
{
	global $logType,$logFileName;

	$method = strtolower($logType);

	$entry = date('r').' - '.$entry;

	if($method == 'file') 
	{
		$fp = fopen($logFileName,'a+');
		fwrite($fp, $entry);
		fclose($fp);
	} 
	elseif($method == 'echo')
	{
		echo nl2br($entry);//browser
		flush();
	}

return;
}

function getMicroTime()
{
	list($usec, $sec) = explode(" ",microtime());
	return ((float)$usec + (float)$sec);
}

$text = file_get_contents($logFileName);

echo $text;

$message = stripslashes($text);

mail("support@email.com","Account Backups for $logFileName",$message);

unlink($logFileName);

?>

Open in new window

0
nainil
Asked:
nainil
1 Solution
 
gr8gonzoConsultantCommented:
Yes. Lines 124 through 126 dictate the filename. Check out the PHP manual page for the date function to see the values you can use
0
 
Mark BradyCommented:
Also, you have an error in your code.

You can remove line 69. you don't need to trim the comma separated domain list here as you are already trimming the array objects after exploding them.

On lines 74 through 77 that function will not work as you expect. I am assuming you want to trim each value in the array? If so, your function is taking each value (domain name) after you explode it and it is trimming the string, then it is adding that trimmed value to your existing array. Using an empty [] after an array name is going to add the new (trimmed) item to the array, not edit an existing item.
To do what you want you need to do this.

for ($i = 0; $i < count($domains); $i ++)
      {
            $domains[$i] = trim($domains[$i]);
      }  

or if you wanted something more robust so you can pass all your arrays through it you could do something like this in a function.

function format_array($array, $explode = false, $delim = false) {
	if ($explode && isset($delim)) $array = explode($delim, $array);
	
	if (is_array($array)) {
		for ($i = 0; $i < count($array); $i ++) {
			$array[$i] = trim($array[$i]);
		}
		return $array;
	}
	
	return false;
}

// use it in one of two ways.
// 1: send in a comma separate list (or separated with some deliminator)

if (!$domains = format_array($list, true, ',')) {
	echo 'Input must be an array or comma separated list';
} else {
	var_dump($domains); // or do whatever you want with it. It is now trimmed
}

// 2: send in an array

if (!$domains = format_array($array)) {
	echo 'Input must be an array or comma separated list';
} else {
	var_dump($domains);
}

Open in new window


So if you had a list of items just set the 2nd parameter to true and the 3rd parameter is the deliminator (ie: ',')
0
 
Ray PaseurCommented:
See http://www.laprbass.com/RAY_temp_nainil.php

The strategy goes a little beyond your problem definition; it includes the year, month and day in the file name.  You will probably find, as I do, that having all of the date information is quite valuable.

<?php // RAY_temp_nainil.php
error_reporting(E_ALL);

$accDom = 'TEST';

// LINE 122 FOLLOWS
/////////////// Start FTP configuration to put dumps in the form of domain/day
date_default_timezone_set('EST');
$day = strtolower(date('l'));
$dayofweeknumber = strtolower(date('N'));
$dst_dir = 'MyBackup/'.$accDom.'/'.$dayofweeknumber.'-'.$day;
$dir = $dst_dir;

// SHOW WHAT IS GENERATED
var_dump($dir);

// WHAT WE WANT IS SOMETHING LIKE THIS...
// MyBackup \ Domain \ Day of the Month \ <backup-file>

// A FUNCTION TO GENERATE A BETTER BACKUP FILE NAME
function backupFileName($domain, $date='TODAY', $basename = 'mybackup.tar.gz')
{
    return
      'MyBackup'
    . DIRECTORY_SEPARATOR
    . $domain
    . DIRECTORY_SEPARATOR
    . date('Y_m_d', strtotime($date))
    . DIRECTORY_SEPARATOR
    . $basename
    ;
}

// TEST THE FUNCTION
var_dump( backupfilename($accDom) );

Open in new window

See also:
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_201-Handling-date-and-time-in-PHP-and-MySQL.html

HTH, ~Ray
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now