Założenie jest takie, ażeby utworzyć skrypt w bashu, który automatycznie i cyklicznie będzie tworzył kopię zapasową bazy danych MySQL, a następnie będzie ją wysyłał na odrębny serwer FTP bez potrzeby ingerencji użytkownika. Serwer na który będzie backup wysyłany to oddzielna maszyna, wymagająca logowania. Aby uniknąć potrzeby podawania hasła w skrypcie, wykorzystać można „autoprzedstawiania” się przy użyciu pliku .netrc. Plik ten znajduje się w katalogu głównym użytkownika i uniksowy program ftp wykorzystuje go do przedstawiania się innym komputerom. Więcej informacji o .netrc tutaj.
Tak więc na początek należy w katalogu /root utworzyć plik .netrc (backup będzie wykonywany przez użytkownika root).
cd /root vi .netrc machine XX.XX.XX.XX login backuper password P@$$w0rd
Jak widać struktura jest dość prosta, po słowie machine należy najpierw podać nazwę komputera/hosta, następnie login i hasło (jawnie). Teraz przy próbie połączenia przez ftp z podanym hostem, zostanie mu podany automatycznie login i hasło, jeśli wymaga uwierzytelniania.
Utworzyłem również oddzielny katalog jako tymczasowe miejsce do którego tworzony jest backup.
mkdir /tmp/mybackup
Katalog utworzony jest wewnątrz /tmp. Katalog ten jak sama nazwa wskazuje jest tymczasowy, przy każdym uruchomieniu jest czyszczony albo jak też w przypadku mojej konfiguracji sam co kilka dni usuwa starsze pliki, tak więc nie ma obaw o zapchanie dysku w przyszłości.
Sam skrypt wygląda następująco:
#! /bin/bash
# ---- Skrypt robiący backup bazy danych -----
# nazwa bazy danych
DB=mydatabase_tobackup
# nazwa pliku z data w nazwie
DATE=`date +%Y%m%d_%H%M`
FILE="db-$DB-$DATE"
# ---- MySQL ------
HOST=localhost
# uzytkownik bazy danych
USER=user-backup
# hasło do bazy danych
PASS=P@$$w0rd
# ---- FTP ------
# nazwa hosta i port do serwera FTP
FTPHOST="XX.XX.XX.XX 6022"
# --- end of settings ----
cd /tmp/backup
echo -e "\n\n"
echo "# Backp bazy danych"
echo "# --------------------------------------"
echo -ne " > Zrzut bazy danych ($DB)..."
mysqldump -h $HOST --user=$USER --password=$PASS $DB > $FILE.sql
if [ $? -eq 0 ]; then
echo "OK"
else
echo "ERROR $?"
fi
echo -ne " > Kompresowanie..."
tar -czf $FILE.tgz $FILE.sql
if [ $? -eq 0 ]; then
echo "OK"
else
echo "ERROR $?"
fi
echo -ne " > Wysyłanie na serwer docelowy..."
ftp <<EOF
open $FTPHOST
cd /DB_BACKUP
put $FILE.tgz $FILE.tgz
bye
EOF
if [ $? -ne 0 ]; then
ret="ERROR $?"
else
ret="OK"
fi
echo $ret
echo -e "\n\n"
# END
Dane do logowania podawane są tutaj w postaci jawnej, dlatego najlepiej jest wykorzystywać do tego celu oddzielnego użytkownika, który będzie wykonywał tylko zrzut bazy danych, bez praw do modyfikacji czy usuwania danych. Zgodnie z informacjami znalezionymi tutaj, powinno to wyglądać mniej więcej tak:
GRANT SHOW DATABASES, SELECT, LOCK TABLES, RELOAD ON *.* to user-backup@localhost IDENTIFIED BY 'P@$$w0rd'; FLUSH PRIVILEGES;
Generalny plan działania skryptu:
- Zrzut wybranej bazy danych do pliku przy użyciu mysqldump.
- Skompresowanie pliku
- Wysłanie na docelowy serwer FTP
Pozostaje jeszcze umieszczenie skryptu w zadaniach crona. Można wrzucić plik skryptu do katalogu /etc/cron.daily/, bądź dodać wpis do crontab.
crontab -e ... 30 3 * * * sh /root/scripts/mybackup.sh
W tym wypadku skrypt uruchamiany jest codziennie o godzinie 3:30. Należy obrać taki czas, kiedy serwer jest najmniej wykorzystywany. Na czas tworzenia zrzutu bazy jest ona blokowana, a przy dużej ilości danych może to chwilę potrwać.
Dodatkowo skrypt ma wyrzucać na ekran (echo) informacje o przebiegu procesu. W przypadku, gdy jest on uruchamiany z crona, wszystko co „wyrzuci” skrypt przesyłane jest na e-mail administratora, tak więc rano w pracy 😉 widać czy wysyłanie kopii się powiodło czy też nie.
Jak można wysłać na inny serwer FTP nie podając loginu i hasła do konta? Sam port i adres nie wystarczy.