14

Does anybody know a clean PHP-based solution that can backup remote web sites using FTP?

Must haves:

  • Recursive FTP backups
  • Possible to run through a cron job
  • Easy to configure (easy adding of multiple sites)
  • Local storage of backup files is sufficient

Would be nice:

  • Backed up sites are stored as zip files
  • A nice interface to manage things
  • Provides notification when backup has succeeded or failed
  • Does incremental backups
  • Does MySQL Database backups

I need this to be PHP based because it's going to be used on shared hosting packages that do not allow usage of the standard GNU/Linux tools.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • 9
    Why involve PHP at all? `rsync` meets all of your "must have" requirements. Also, how do you plan to both use zip files and incremental backups? – user229044 Jan 01 '11 at 22:34
  • I agree with @meagar, php seems like a poor choice for something like this. Also, local storage of backups don't help when the machine completely fails. – Chris Henry Jan 01 '11 at 22:50
  • @meagar this is for a reciprocal backup solution between two shared web hosts, so only PHP (well, and maybe Perl) is an option. @Chris by "local" I mean local on the server the backup script runs on, not the remote server that is being backed up – Pekka Jan 01 '11 at 23:01
  • @pekka Is rsync not available on the host? – user229044 Jan 02 '11 at 03:29
  • @meagar It may be on one of the packages, but I can't rely on it on the other one. Still, if all else fails, that's an interesting alternative for at least the one host. – Pekka Jan 02 '11 at 10:32
  • @meagar - How's rsync liable to cope with a live database? (Simply copying the files isn't going to be epic from a referential integrity perspective.) – John Parker Jan 02 '11 at 10:40
  • @middaparka true, but that could be sorted by a PHP script doing a dump on the remote server and then rsyncing. – Pekka Jan 02 '11 at 10:41
  • @Pekka - True. To be honest, I suspect you'll need to write a custom script to handle this task anyway. (I've had to go a similar route in the past.) – John Parker Jan 02 '11 at 10:43
  • @midda yeah, that's well possible. Too bad there doesn't seem to be an industry-standard FOSS solution for this - PHP is admittedly not the best tool for this, but it would be a great relief for many people running small to medium-sized web sites to have the possibility. – Pekka Jan 02 '11 at 10:45
  • @middaparka You'd want to `mysql_dump` the database into some sub-folder of the directory you're backing up, not simply copy the MySQL data files... – user229044 Jan 02 '11 at 16:19
  • @Pekka I don't think there's an "industry standard" beyond cron + rsync because implementing incremental timed backups with rsync and cron is trivially easy. We're talking a two line cron job to backup the database and then rsync the directory across the network. – user229044 Jan 02 '11 at 16:21
  • are you just using these free sites as storage or hosting an website on it? – space ranger Aug 13 '12 at 07:59
  • @space not sure what you mean by "free" sites? Neither of the sites I'm backing up to (or from) is free, they're just hosting packages with limited functionality. – Pekka Aug 13 '12 at 08:22
  • oh my mistake I backup my files using the dropbox api with an php wrapper around it but its only for my ftp storage accs – space ranger Aug 13 '12 at 08:28

5 Answers5

2

I have done something like this in a cron job PHP script before. Not sure if it is the best way, but it certainly works.

$backup_file = '/home/example/sql_backup/mo_'.date('Y-m-d').'.sql.gz';
$command = '/usr/bin/mysqldump -c -h'.DB_HOST.' -u'.DB_USER.' -p'.DB_PASS.' --default-character-set=latin1 -N '.DB_NAME.' | gzip > '.$backup_file;
exec($command);

You could then exec an sftp to the remote server.

You could do the file folders similarly using exec() and linux zipping.

dqhendricks
  • 19,030
  • 11
  • 50
  • 83
  • i use this mainly to give the users of the system a way to roll back to a previous state of the database from a custom php database backup manager. – dqhendricks Jan 13 '11 at 23:53
2

I coded this to handle the FTP backups, not sure if it fits your specific needs tho:

class Backup
{
    public $ftp = null;
    public $files = array();

    public function FTP($host, $user = null, $pass = null, $port = 21, $path = '/')
    {
        if ((extension_loaded('ftp') === true) && (extension_loaded('zip') === true))
        {
            $this->ftp = ftp_connect($host, $port, 5);

            if (is_resource($this->ftp) === true)
            {
                if (ftp_login($this->ftp, $user, $pass) === true)
                {
                    $zip = new ZipArchive();

                    if (is_object($zip) === true)
                    {
                        ftp_pasv($this->ftp, true);

                        if ($zip->open(sprintf('./%s_%s.zip', $host, date('YmdHis', time())), ZIPARCHIVE::CREATE) === true)
                        {
                            $this->FTP_Map($path);

                            while (($file = array_shift($this->files)) !== null)
                            {
                                if (preg_match('~/$~', $file) > 0)
                                {
                                    $zip->addEmptyDir(preg_replace('~^[\\/]+~', '', $file));
                                }

                                else
                                {
                                    $stream = tempnam(sys_get_temp_dir(), __CLASS__);

                                    if (is_file($stream) === true)
                                    {
                                        if (ftp_get($this->ftp, $stream, $file, FTP_BINARY, 0) === true)
                                        {
                                            $zip->addFromString(preg_replace('~^[\\/]+~', '', $file), file_get_contents($stream));
                                        }

                                        unlink($stream);
                                    }
                                }
                            }
                        }

                        $zip->close();
                    }
                }

                ftp_close($this->ftp);
            }
        }

        return false;
    }

    public function FTP_Map($path = '/')
    {
        if (is_resource($this->ftp) === true)
        {
            $files = ftp_nlist($this->ftp, ltrim($path, '/'));

            if (is_array($files) === true)
            {
                foreach ($files as $file)
                {
                    if (@ftp_chdir($this->ftp, $file) !== true)
                    {
                        $this->files[] = sprintf('/%s/%s', trim($path, '\\/'), trim($file, '\\/'));
                    }

                    else if (ftp_cdup($this->ftp) === true)
                    {
                        if (array_push($this->files, sprintf('/%s/%s/', trim($path, '\\/'), trim($file, '\\/'))) > 0)
                        {
                            $this->FTP_Map(sprintf('/%s/%s/', trim($path, '\\/'), trim($file, '\\/')));
                        }
                    }
                }

                return true;
            }
        }

        return false;
    }
}

Usage:

$Backup = new Backup();

$Backup->FTP('demo.wftpserver.com', 'demo-user', 'demo-user', 21, '/text/');

For MySQL backups, would SELECT INTO OUTFILE do it?

Alix Axel
  • 151,645
  • 95
  • 393
  • 500
1

I actually wrote an article w/ included scripts on how I accomplished this using PHP, Bash and some other pieces of open source software to send out the pre-formatted email notifications about the backups.

http://codeuniversity.com/scripts/scr1

My requirements were fairly similar although there is no FTP involved. It's all done locally. Give it a look. Perhaps you may find it useful.

1

I’m using myRepono, in addition to what you have mentioned, if performs fast and automatic backups and it’s very stable and secure.

kumo99
  • 133
  • 2
  • 15
0

While your shared hosting may not provide many tools, it must provide at least some, it might be worth asking your host what they provide or recommend for backups. Do you want to back up to a pretty much identical host. (at least in terms of software)

To run rsync successfully it only has to be running on one machine, the other doesn't need to even know that rysnc exists, it also doesn't matter which one of the machines is running it (backup or primary host).

Do you have cli access to the server to install packages or php modules? If you don't then all bets are off as the chances are that your php install won't include any of the necessary packagesn to begin to think about attempting this from php.

I would reccommend a non php solution like rysnc or a bash script of some kind. Although you could wrap the process in a php wrapper to manage it.

James Butler
  • 3,852
  • 1
  • 26
  • 38