Zarejestruj się na BitBay.net
Home > Linux, MySQL, PHP > Prosty backup MySQL z pomocą PHP lub Basha

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

Kategorie:Linux, MySQL, PHP Tagi:, , , ,
  1. kendrix
    Listopad 21st, 2010 at 23:17 | #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. Listopad 23rd, 2010 at 08:23 | #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. kendrix
    Listopad 28th, 2010 at 00:17 | #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. Listopad 28th, 2010 at 20:13 | #4

    Ścieżki dostępu się nie zgadzają lub katalog ma za małe prawa. Proponuję napisać do administratora serwera.

  5. kendrix
    Listopad 29th, 2010 at 12:26 | #5

    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

  6. Grudzień 21st, 2010 at 21:46 | #6

    Zaktualizowałem arta. Skrypt wykorzystujący klasę PDO powinien pomóc.

  7. Picia
    Luty 24th, 2011 at 02:24 | #7

    A jak przywrócić bazę z tak zrobionej kopii?

  8. Marzec 2nd, 2011 at 16:34 | #8

    mysql -u uzytkownik baza1 < baza1_kopia.sql -p

  9. Czerwiec 20th, 2012 at 16:47 | #9

    Ostatni skrypt z PHP-PDO krzaczy się. Kopiowałem bazę z joomli i… zong. Poszło o znaczki podwójnego cudzysłowu.

  10. Scottie
    Sierpień 3rd, 2012 at 11:52 | #10

    A nie lepiej skorzystać z już gotowego rozwiązania? Np. „AutoMySQLBackup” (http://sourceforge.net/projects/automysqlbackup/)

  1. Listopad 18th, 2010 at 19:08 | #1
  2. Sierpień 16th, 2011 at 17:36 | #2

*