Nawet jeśli nasz dostawca usług hostingowych wykonuje regularny backup danych (o dziwo niektórzy nie robią) warto co jakiś czas samodzielnie wykonać kopię zapasowa danych – różne rzeczy się zdarzają, a przezorny zawsze ubezpieczony. W celu ułatwienia sobie tego zadania warto napisać prosty skrypt tworzący archiwum zawierające kopię bazy danych oraz plików. Przedstawię tutaj przykładowe rozwiązanie do backupu WordPressa.
Do wykonania kopii zapasowej bazy MySQL można użyć programu mysqldump. Wystarczy podać dane dostępowe i nazwę bazy danych, a program dokona zrzutu bazy w postaci zapytań SQL.
Odczyt danych dostępowych
Dane dostępowe do bazy przechowywane są w pliku wp-config.php
, więc zamiast umieszczać je w skrypcie lub podawać ręcznie, możemy je odczytać z tego pliku. Interesują nas następujące linie:
define('DB_NAME', 'nazwaBazy'); define('DB_USER', 'uzytkownik'); define('DB_PASSWORD', 'haslo ab \'cd"ef'); define('DB_HOST', 'mysql.example.net');
Aby odnaleźć konkretną linię można skorzystać z programu grep
. W najprostszy sposób można uzyskać informacje na temat hosta – jego nazwa jest ograniczona apostrofami i nie może ich w sobie zawierać. Zatem możemy użyć programu cut
. Jeśli rozdzielimy linię na części używając apostrofu jako znaku podziału, to czwarte pole będzie zawierało potrzebną informację.
grep DB_HOST wp-config.php | cut -d "'" -f 4
Jednak w nawie bazy danych, użytkownika lub haśle może znaleźć się apostrof. Będzie on poprzedzony znakiem wstecznego ukośnika \
który będzie znakiem ucieczki, a nie częścią interesujących nas danych – trzeba go więc usunąć. Do tych zadań można zastosować edytor strumieniowy sed
(ang. Stream EDitor) a w nim odpowiednie polecenia oparte na wyrażeniach regularnych. W pierwszym kroku pozbywamy się wszystkiego od początku linii do , '
(s/^.*, '//
— s
oznacza zastepowanie), w drugim kroku z końca linii usuwamy ');
(s/');$//
) na koniec zamieniamy wszystkie \'
na '
(s/\\\'/'/g
— g
oznacza globalne, wszystkie wystąpienia).
grep DB_HOST wp-config.php | sed -e "s/^.*, '//;s/');$//;s/\\\'/'/g"
Zatem pobranie danych dostępowych do bazy danych z pliku konfiguracyjnego WordPressa i wykonanie backupu bazy MySQL wyglądać będzie następująco:
mysql_host=$(grep DB_PASSWORD wp-config.php | cut -d "'" -f 4) mysql_baza=$(grep DB_NAME wp-config.php | sed -e "s/^.*, '//;s/');$//;s/\\\'/'/g") mysql_login=$(grep DB_USER wp-config.php | sed -e "s/^.*, '//;s/');$//;s/\\\'/'/g") mysql_haslo=$(grep DB_PASSWORD wp-config.php | sed -e "s/^.*, '//;s/');$//;s/\\\'/'/g") mysqldump -h $mysql_host -u $mysql_login --password="$mysql_haslo" "$mysql_baza" > baza.sql
Bezpieczeństwo
Jednak jeśli inni użytkownicy mogą wyświetlać listę wszystkich procesów w systemie to uruchomienie polecenia mysqldump
wraz z jawnie podanym hasłem (--password=nasze_haslo
) rodzi niebezpieczeństwo jego ujawnienia. Jest na to rada. Dane dostępowe do bazy danych można zapisać w pliku konfiguracyjnym i podczas uruchomienia programu mysqldump
wczytać ten plik (--defaults-file
). Dla pliku warto ustawić uprawnienia umożliwiające odczyt tylko jego właścicielowi. Dodatkowo jeśli w pliku zapiszemy tylko hasło bez nazwy bazy i użytkownika, to wejście w posiadane samego pliku nie będzie wystarczające aby uzyskać dostęp do bazy.
Skrypt bash’a do backupu WordPressa
Kompletny skrypt uwzględniający wszystkie opisane powyżej aspekty będzie wyglądał następująco:
#!/bin/bash #Autor: ioerror.pl ############################# if [ $# == 0 ]; then echo "Użycie: \"$0\" KATALOG_WORDPRESSA" > /dev/stderr exit 10 fi if [ ! -d "$1" ]; then echo "$0: Katalog \"$1\" nie istnieje" > /dev/stderr exit 11 fi plik_konfiguracji="$1/public_html/wp-config.php" if [ ! -f "$plik_konfiguracji" ]; then echo "$0: Plik konfiguracyjny WordPressa \"${plik_konfiguracji}\" nie istnieje" > /dev/stderr exit 12 fi plik_konfiguracji_mysql=$(mktemp -q ./XXXXXXXXXXXX.cnf) if [ $? -ne 0 ]; then echo "$0: Błąd tworzenia pliku tymczasowego" > /dev/stderr exit 13 fi chmod 600 "$plik_konfiguracji_mysql" echo '[mysqldump]' > "$plik_konfiguracji_mysql" data=$(date +%Y-%m-%d) mysql_host=$(grep DB_HOST "$plik_konfiguracji" | cut -d "'" -f 4) mysql_baza=$(grep DB_NAME "$plik_konfiguracji" | sed -e "s/^.*, '//;s/');$//;s/\\\'/'/g") mysql_login=$(grep DB_USER "$plik_konfiguracji" | sed -e "s/^.*, '//;s/');$//;s/\\\'/'/g") echo 'password = ' $(grep DB_PASSWORD "$plik_konfiguracji" | sed -e "s/^.*, '//;s/');$//;s/\\\'/'/g") >> "$plik_konfiguracji_mysql" mysqldump --defaults-file="$plik_konfiguracji_mysql" -h $mysql_host -u $mysql_login "$mysql_baza" > "$1-${data}.sql" if [ $? -ne 0 ]; then echo "$0: Błąd tworzenia zrzutu bazy danych" > /dev/stderr blad=14 else blad=0 tar -czf "$1-${data}.tar.gz" "$1-${data}.sql" $1/public_html if [ $? -ne 0 ]; then echo "$0: Błąd tworzenia archivum tar" > /dev/stderr blad=15 else echo 'Backup wykonany poprawnie' fi fi rm -f "$1-${data}.sql" "$plik_konfiguracji_mysql" if [ $blad -ne 0 ]; then exit $blad fi