backupL‘une des choses à laquelle on ne pense pas forcément lors de la mise en place d’un site internet est la sauvegarde régulière de ce dernier, pourtant il est très important de penser à mettre en place cette fonction, car un serveur qui crashe ou une erreur est si vite arrivé que dans le cas où on a rien prévu les dégâts peuvent être vraiment importants au point de pouvoir remettre en cause l’ensemble du site.

Le but de ce script est donc de sauvegarder les sources d’un site et de faire une dump de la base de données liée, mais pas seulement, il incorpore quelques options permettant de ne pas surcharger le serveur avec des fichiers obsolètes ou des données non nécessaires.

Code PHP permettant la sauvegarde des sources et de la base de données

Ce script est simple et utilise les variables envoyées par un script CRON tout simplement parce que la tâche de sauvegarde a vocation à être réalisée de manière automatisée, mais il peut être facilement modifié pour être utilisé à partir d’un appel php si besoin.

Pour l’exécution de ce script les deux premiers paramètres sont nécessaire, le troisième est optionnel.

Le données en rouge sont à remplacer avec vos propres données.

Ligne appelée par la tâche CRON avec un script se trouvant dans /home/toto/public_html/backups/ :

/home/toto/public_html/backups/index.php [nom de la base de données] [répertoire à sauvegarder] [répertoires à ignorer séparés par une virgule]

<?php
if ( !isset($argv[1]) || !isset($argv[2]) )
    die();

set_time_limit(0);

/* Variables */
$mysql_server = 'localhost';
$mysql_login = '[login base de données]';
$mysql_passwd = '[mot de passe base de données]';
$mysql_bdd = $argv[1];    
$dir_to_save = $argv[2];
$array = explode(DIRECTORY_SEPARATOR, $dir_to_save);
$root_for_zip = array_pop($array);
$day = Date('N');
echo date('H-i-s') . ' CRON job start' . "\n";
echo date('H-i-s') . ' DB : ' . $mysql_bdd . "\n";
echo date('H-i-s') . ' Directory : ' . $dir_to_save . "\n";
if ( isset($argv[3]) && $day != 1 ) {
    $dirs_not_to_save_array = explode(',', (string) $argv[3]);
    echo date('H-i-s') . ' Excluded : ' . $argv[3] . "\n";
} else {
    $dirs_not_to_save_array = array('');
    echo date('H-i-s') . ' Excluded : none' . "\n";
}
$date = date('Y-m-d_H-i-s');
$db_name_prefix = 'db_' . $date;
$sources_name_prefix = 'sources_' . $date;
$base_directory = dirname(__FILE__) . DIRECTORY_SEPARATOR;

// Delete obsolete files
$directory = $base_directory . $root_for_zip;
if ( $handle = opendir($directory) ) {
    while ( false !== ($file = readdir($handle)) ) {
        if ( $file != '.' && $file != '..' && $file != 'index.php' ) {
            $filelastmodified = filemtime($directory . DIRECTORY_SEPARATOR . $file);
            if( (time() - $filelastmodified) > 6*24*3600 ) {
                unlink($directory . DIRECTORY_SEPARATOR . $file);
                echo date('H-i-s') . ' Deleted : ' . $directory . DIRECTORY_SEPARATOR . $file . "\n";
            }
        }
    }
    closedir($handle); 
}

// DB dump
echo date('H-i-s') . ' DB dump' . "\n";
system('mysqldump --host=' . $mysql_server . ' --user=' . $mysql_login . (( $mysql_passwd)?' --password=' . $mysql_passwd: '') . ' ' . $mysql_bdd . ' > ' . $base_directory . DIRECTORY_SEPARATOR . $root_for_zip . DIRECTORY_SEPARATOR . $db_name_prefix . '.sql');        
system('gzip ' . $base_directory . DIRECTORY_SEPARATOR . $root_for_zip . DIRECTORY_SEPARATOR . $db_name_prefix . '.sql');
echo date('H-i-s') . ' Dump terminated' . "\n";

// Sources save
echo date('H-i-s') . ' Sources save' . "\n";
$zipfile = $base_directory . DIRECTORY_SEPARATOR . $root_for_zip . DIRECTORY_SEPARATOR . $sources_name_prefix . '.zip';
$filenames = array();
    
function browse($dir, &$filenames) {
    global $dirs_not_to_save_array;
    if ( $handle = opendir($dir) ) {
        while (false !== ($file = readdir($handle))) {
            if ( $file != '.' && $file != '..' && is_file($dir . DIRECTORY_SEPARATOR . $file) ) {
                $filenames[] = $dir . DIRECTORY_SEPARATOR . $file;
            } else if ( $file != '.' && $file != '..' && is_dir($dir . DIRECTORY_SEPARATOR . $file) && !in_array($dir . DIRECTORY_SEPARATOR . $file, $dirs_not_to_save_array) ) {
                browse($dir . DIRECTORY_SEPARATOR . $file, $filenames);
            }
        }
        closedir($handle);
    }
    return $filenames;
}
    
browse($dir_to_save, $filenames);

$zip = new ZipArchive();
    
if ( $zip->open($zipfile, ZIPARCHIVE::CREATE) !== true ) {
    die(date('H-i-s') . ' cannot open <' . $zipfile . '>');
}

foreach ( $filenames as $filename ) {            
    $array = explode(DIRECTORY_SEPARATOR, str_replace($dir_to_save, $root_for_zip, $filename));
    array_pop($array);
        
    $counter = 0;
    foreach ( $array AS $dir ) {
        $dir_path = $array[0];
        for ( $cpt = 1; $cpt <= $counter; $cpt ++ ) {
            $dir_path .= DIRECTORY_SEPARATOR . $array[$cpt];
        }

        $zip->addEmptyDir($dir_path);
        
        $counter ++;
    }
    
    if ( !$zip->addFile($filename, str_replace($dir_to_save ,$root_for_zip, $filename)) ) {
        die(date('H-i-s') . ' error on file : ' . str_replace($dir_to_save ,$root_for_zip, $filename));
    }
}

$zip->close();
echo date('H-i-s') . ' Sources saved' . "\n";
echo date('H-i-s') . ' CRON job terminated';

Les petits plus du script

Le script va créé un répertoire portant le nom du dernier répertoire de [répertoire à sauvegarder], de façon à pouvoir sauvegarder les données de plusieurs sites.

Tous les jours sauf le lundi il va ignorer les répertoires de [répertoires à ignorer séparés par une virgule] afin de ne pas surcharger les fichiers avec des données qui ne changent que rarement, ce paramètre est optionnel.

Toutes les semaines, il va supprimer les fichiers (sources et dumps) obsolètes, ça fait donc un historique sur 7 jours ce qui est suffisant en général.

Concernant la périodicité de sauvegarde, c’est la tâche CRON qui va le définir.

Ce script est basique et répond à un besoin qui peut ne pas convenir à tous, mais il permet d’avoir une bonne base afin d’en faire un plus complexe et répondant à des besoins spécifiques si besoin.

Répondre

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

treize + = quatorze