These days I needed a script to backup only a part of a customers website using a CRON. Most of the control panels I know allow only a complete website backup and this is not what I needed. While plaaning the script, I thought about a solution for webmaster without full SSH access to their hosting account. A typical situation could be:
First of all we need to create a variable to define the local source directory on your website where you like to start the backup from:
define('BASEPATH', $_SERVER['DOCUMENT_ROOT'].'/');
The next code is to create a new class including the constructor function and some variables used in that class:
class Curl_ftp_backup {
public $basePath, $errors, $ftp_server, $ftp_user_pw , $msg, $email;
public function __construct($ftp_server, $ftp_userpw, $email_adr) {
$this->basePath = BASEPATH;
$this->errors = '';
$this->ftp_server = $ftp_server;
$this->ftp_user_pw = $ftp_userpw;
$this->email = $email_adr;
$this->msg = '';
}
Our class will store file and directories on the remote FTP server, the next function will create a directory if it not already exists:
private function curl_create_ftp_directory($name, $curr_dir = '') {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->ftp_server);
curl_setopt($ch, CURLOPT_USERPWD, $this->ftp_user_pw);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$cmd = array();
if ($curr_dir != '') $cmd[] = 'CWD '.$curr_dir;
$cmd[] = 'MKD '.$name;
curl_setopt($ch, CURLOPT_POSTQUOTE, $cmd);
curl_exec ($ch);
return;
}
The following function will open a file and uploads the data to specified directory on the target server. For each file that is not stored the error number is returned, this information is used later to build up an error string.
private function curl_put_file($path) {
$ch = curl_init();
$fp = fopen($this->basePath.$path, "r");
curl_setopt($ch, CURLOPT_URL, $this->ftp_server.$path);
curl_setopt($ch, CURLOPT_USERPWD, $this->ftp_user_pw);
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($this->basePath.$path));
curl_exec ($ch);
$error = curl_errno($ch);
curl_close ($ch);
if ($error != 0) $this->errors .= $path.PHP_EOL;
return;
}
Now we need a function that will loop through the specified base directory and will switch between directories and files; the previous functions will create the directory or upload the file.
public function backupfiles($directory) {
if ($handle = opendir($this->basePath.$directory)) {
$this->curl_create_ftp_directory($directory);
while (false !== ($file = readdir($handle))) {
if (is_file($this->basePath.$directory.$file) && $file != '.htaccess') {
$this->curl_put_file($directory.$file);
} elseif ($file != '.' && $file != '..' && is_dir($this->basePath.$directory.$file)) {
$this->backupfiles($directory.$file.'/', $directory);
}
}
closedir($handle);
if ($this->errors != '') {
$this->msg = 'Missing files: '.PHP_EOL.$this->errors;
} else {
$this->msg = 'FTP upload successful.';
}
} else {
$this->msg = 'Can't open local directory.';
}
}
public function send_emailmsg() {
if ($this->msg != '') {
$body = PHP_EOL.'Backup result:'.PHP_EOL.PHP_EOL.$this->msg;
mail($this->email, 'Your Backup on '.date('Y-m-d H:i:s'), $body);
}
}
At last there is a tiny function that will send you some short email message about the backup result. You can call the class in your PHP script:
$cb = new Curl_ftp_backup('ftp://ftp.yourserver.com/source_folder/', 'user:password', 'your@email.com');
$cb->backupfiles('includes/');
$cb->send_emailmsg();
Thats all, now you need to create a CRON job for the file that will execute the backup. If your hosting provider doesn’t provide CRON jobs, just google for “free cron jobs”.
Disclaimer:
We tested the script “successful” on two modern Linux web servers with ~100 files between 10kb and 300MB. If you have a backup with a lot of files you should think about a different solution. With every file or directory a new CURL function is called, this could result in a high server load. We are not responsible for any damage and/or data loss as the result off using this script.
Click here to download the PHP class script.
[…] Create custom backups from your website using cURL […]
Great article.
In my opinion, cURL is one of the most under-appreciated features of PHP. It is so powerful.
@corbyboy,
you’re absolutely right, bad enough that the php curl extension is so limited. The curl lib you can use via the command line has much more features. For example you can upload multiple files with one connection
The link to the zip file id not working anymore. I need to download the code. Can you please tell me where can I find the code?
…oeps, I forgot to upload the file. It’s fixed right now!
Well if you are worried about a high server load due to multiple cURL connections, why not write a script that compresses the files into a zip first, then it could move the zip over to the backup server. You could even name the zip with a time stamp so u have various backup versions on your backup server.
Hi Matt,
creating (bigger) zips takes much more server resources…
if my directadmin server is processing the backups the server becomes very slow…
Though DB backup can be taken from web control panel, but this can be in help full in different situations.
Thanks for sharing this.
Hello,
Thanks for creating and sharing such a brilliant and helpful article.
My situation is that I am creating an application for my client, through which he can upload hi website directory to a remote server. I have used your code in building the application.
While testing I came to know that the code is working on only a specific version of CURL. If the CURL version is 7.10, then it doesn’t work. But if the version is 7.17, then the files are uploaded.
My client is having different web servers to host his websites. And the version of CURL is not the same on each one of them.
Can you throw some light on it, as how to make it version independent?
Gurpreet Singh,
I don’t know, is there some information on the cURL website? and do you checked the php manual?