Prosty backup MySQL z pomocą PHP lub Basha

Pisząc strony/systemy korzystające z PHP+MySQL w którymś momencie musimy zaprojektować backup bazy. Oczywiście są do tego gotowe programy, ale po co od razu ściągać jakiś dziwny soft skoro już mamy odpowiednie narzędzia. W przypadku linuxa zaprzęgamy do roboty mysqldumpa,basha oraz crona i trzymamy kilka kopii w tył (np z 7 dni).
Najprostszy sposób:

#!/bin/bash
#############################
# Skrypt do kopii baz MySQL #
#  www.tidnab.nowaruda.net  #
#############################
KATALOG=/root/backup/mysql
cd $KATALOG

if test -f bazy6.tar.gz
then rm bazy6.tar.gz
fi

if test -f bazy5.tar.gz
then mv bazy5.tar.gz bazy6.tar.gz
fi

if test -f bazy4.tar.gz
then mv bazy4.tar.gz bazy5.tar.gz
fi

if test -f bazy3.tar.gz
then mv bazy3.tar.gz bazy4.tar.gz
fi

if test -f bazy2.tar.gz
then mv bazy2.tar.gz bazy3.tar.gz
fi

if test -f bazy1.tar.gz
then mv bazy1.tar.gz bazy2.tar.gz
fi

if test -f bazy.tar.gz
then mv bazy.tar.gz bazy1.tar.gz
fi

clear

echo ''
echo Tworzenie archiwum MYSQL...
echo ''

`/usr/local/mysql/bin/mysqldump -ujacek -ptajnehaslo --all-databases >$KATALOG/mysql_copy.sql`
tar cvfz $KATALOG/bazy.tar.gz $KATALOG/mysql_copy.sql
rm $KATALOG/mysql_copy.sql

Sposób z rotacją według daty pliku:

#!/bin/bash
#############################
# Skrypt do kopii baz MySQL #
#  www.tidnab.nowaruda.net  #
#############################

#katalog docelowy
katalog='/backup/mysql/';
cd $katalog

#z ilu dni mają pozostać kopie
ilosc=5;

#data
data=`date "+%Y%M%d-%H%m%S"`;

#namiary na serwer MySQL
host='192.168.1.140';
login='jacek';
haslo='tajnehaslo';

#Kopia1
baza='sprzet';
/usr/bin/mysqldump -h$host -u$login -p$haslo $baza >$katalog/mysql_$baza'_'$data.sql

#Kopia2
baza='umowy';
/usr/bin/mysqldump -h$host -u$login -p$haslo $baza >$katalog/mysql_$baza'_'$data.sql

####################
# Rotacja backupow #
####################
find -mtime +$ilosc -iname 'mysql_*' -type f -exec rm -rf {} \;

Skrypt dodajemy do crona, tak żeby uruchamiał się raz na dobę i gotowe. Dla większego bezpieczeństwa możemy oczywiście dorobić kopiowanie plików na inny server za pomocą ssh,ftp,smb lub nfs. Jeśli użytkownicy danego systemu, sami chcą robić kopię (np. nie ufają administratorowi :] ), robimy im backup na żądanie za pomocą PHP:

<?php
$backupFile = $dbname . date("Y-m-d-H-i-s") . '.sql';

////////////////////////////
///    Ustawienia bazy   ///
////////////////////////////
$dbhost	=	"localhost";
$dbuser	=	"jacek";
$dbpass	=	"tajnehaslo";
$dbname =	"katalog_1";

system("/usr/local/mysql/bin/mysqldump -u$dbuser -p$dbpass $dbname | gzip > $backupFile");

header ('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$backupFile.'.gz"');
$file=fopen($backupFile,"r");
fpassthru($file);
fclose($file);

//delete temporary files
unlink($backupFile);
?>

Problem pojawia się gdy korzystamy z hostingu i ze względów bezpieczeństwa mamy zablokowaną funkcję system(). W takim przypadku zmuszeni jesteśmy skorzystać z bardziej wyrafinowanych metod. Wykorzystamy do tego klasę PDO. PDO to ujednolicony sterownik oraz preprocesor zapytań umożliwiający komunikację z różnymi systemami baz danych dostępny w PHP od wersji 5.1. Poniżej skrypt opublikowany na łamach czasopisma HACKING9 nr 12/2010:

<?php
try{
///parametry polaczenia z baza
$dbName = 'naszabaza';
$dbHost = 'localhost';
$dbUser = 'jacek';
$dbPass = 'tajnehaslo';
///stworzenie nowego obiektu klasy PDO
$PDO = new PDO("mysql:host=$dbHost;dbname=$dbName", $dbUser, $dbPass, array(PDO::MYSQL_ATTR_INIT_COMMAND =>
"SET NAMES utf8"));
$PDO -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sqlQuery = "SHOW tables FROM " . $dbName;
$sqlResult = $PDO->query($sqlQuery);
///przypisanie naglowka do backupu
$sqlData = "-- Cron Backup --
SET SQL_MODE=\"NO_AUTO_VALUE_ON_ZERO\";
-- Baza: `$dbName`
-- Cron Backup --\n\n";
while ($queryTable = $sqlResult->fetch(PDO::FETCH_ASSOC)){
$sqlTable = $queryTable['Tables_in_' . $dbName];
$sqlQuery = "SHOW CREATE TABLE $sqlTable";
$sqlResultB = $PDO->query($sqlQuery);
$queryTableInfo = $sqlResultB->fetch(PDO::FETCH_ASSOC);
///dodanie naglowkow dla konkretnych tabel
$sqlData .= "\n\n--
-- Struktura dla tabeli `$sqlTable`
--\n\n";
$sqlData .= $queryTableInfo['Create Table'] . ";\n";
$sqlData .= "\n\n--
-- Wartosci tabeli `$sqlTable`
--\n\n";
$sqlQuery = "SELECT * FROM $sqlTable\n";
$sqlResultC = $PDO->query($sqlQuery);
///stworzenie INSERTa dla kazdego rekordu
while ($queryRecord = $sqlResultC->fetch(PDO::FETCH_ASSOC)) {
$sqlData .= "INSERT INTO $sqlTable VALUES (";
$sqlRecord = "";
foreach( $queryRecord as $sqlField => $sqlValue ) {
$sqlRecord .= "'$sqlValue',";
}
$sqlData .= substr( $sqlRecord, 0, -1 );
$sqlData .= ");\n";
}
}
///zapis zrzutu bazy do archiwum GZ
$gzFile = gzopen('backup_'.$dbName.'_'.date('H_i_d_m_y').'.gz','w9');
gzwrite($gzFile, $sqlData);
gzclose($gzFile);
///W przypadku gdy nie mamy obslugi GZIPa musimy uzyc:
///file_put_contents('backup_'.$dbName.'_'.date('H_i_d_m_y').'.sql', $sqlData);
}
catch(PDOException $e){
echo 'Połączenie nie mogło zostać utworzone: ' . $e->getMessage();
}
?>

Podobne: Prosty backup danych

13 thoughts on “Prosty backup MySQL z pomocą PHP lub Basha

  1. witam

    mógłbyś to trochę rozwinąć np: w odniesieniu do konkretnego hostingu np az.pl. chciałbym to wykorzystać na swojej stronie.

    pozdrawiam

  2. Na komercyjnym hostingu może nie zadziałać ponieważ, prawdopodobnie ze względów bezpieczeństwa zablokowana będzie funkcja system(). Wtedy jedynym sposobem jest wystawić bazę na zewnątrz i dokonywać backupu jakimś softem lub dodać polecenie mysqldump do crona i backup będzie się robił sam.

  3. wrzucilem pierwszy skrypt i cron zwraca mi cos takiego:

    : not found
    + KATALOG=/home/du112561/autobackup/baza_mysql_presta
    + cd /home/du112561/autobackup/baza_mysql_presta

    cd: can’t cd to /home/du112561/autobackup/baza_mysql_presta

    +

    : not found
    /home/du112561/baza.sh: 43: Syntax error: end of file unexpected (expecting „fi”)

    oczywiscie katalog ma prawa chmod 777, moze jakas propozycja rozwiazania

  4. no właśnie ścieżki się zgadzają bo już konsultowałem z adminem, poza tym jak użyje polecenia mysqldump z tymi ścieżkami w cron to kopia baza się zapisuje.
    Chyba będe musiał skorzystać z innego sposobu

    pozdrawiam i dzięki za pomoc

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

*

Releated