nixCraft Poll

Topics

How to backup MySQL databases, web server files to a FTP server automatically

Posted by Vivek Gite [Last updated: July 26, 2007]

This is a simple backup solution for people who run their own web server and MySQL server on a dedicated box or VPS. Most dedicated hosting provider provides the backup service using NAS or FTP servers. These service providers will hook you to their redundant centralized storage array over private VLAN. Since I manage couple of boxes, here is my own automated solution. If you just want a shell script, go here (you just need to provided appropriate input and it will generate FTP backup script for you on fly).

Making incremental backups with tar

You can make tape backups. However, sometime tape is not an option. GNU tar allows you to make incremental backups with -g option. For example following command will make incremental backup of /var/www/html, /home, and /etc directories:
# tar -g /var/log/tar-incremental.log -zcvf /backup/today.tar.gz /var/www/html /home /etc

Where,

Making MySQL databases backup

mysqldump is a client program for dumping or backing up mysql databases, tables and data. For example following command displays the list of databases:
$ mysql -u root -h localhost -p -Bse 'show databases'

Output:

Enter password:
brutelog
cake
faqs
mysql
phpads
snews
test
tmp
van
wp

Now you can backup each database with mysqldump command:
$ mysqldump -u root -h localhost -pmypassword faqs | gzip -9 > faqs-db.sql.gz

A simple backup system plan

The main advantage of using FTP or NAS backup is a protection from data loss. You can use various protocols to backup data:

  1. FTP
  2. SSH
  3. RSYNC
  4. Other Commercial solutions

However, I am going to write about FTP backup solution here. The idea is as follows:

Our sample setup

   Your-server     ===>       ftp/nas server
IP:202.54.1.10   ===>       208.111.2.5

Let us assume that your ftp details are as follows:

You will store data as follows:
=> /home/nixcraft/full/mm-dd-yy/files - Full backup
=> /home/nixcraft/incremental/mm-dd-yy/files - Incremental backup

Automating tasks of backup with tar

Now you know how to backup files and mysql databases using tar and mysqldump commands respectively. It is time to write a shell script that will automate entire procedure.

  1. First script will collect all data from both MySQL database server and from file system to temporary directory called /backup using tar command
  2. Next, script will login to ftp server and create a directory structure as discussed above
  3. Script will dump all files from /backup to ftp server
  4. Script will remove temporary backup from /backup
  5. Script will send you an email notification if ftp backups failed due to any reason.

You must have following command installed:

Here is the sample script:

#!/bin/sh
# System + MySQL backup script
# Full backup day - Sun (rest of the day do incremental backup)
# Copyright (c) 2005-2006 nixCraft
# This script is licensed under GNU GPL version 2.0 or above
# Automatically generated by http://bash.cyberciti.biz/backup/wizard-ftp-script.php
# ---------------------------------------------------------------------
### System Setup ###
DIRS="/home /etc /var/www"
BACKUP=/tmp/backup.$$
NOW=$(date +"%d-%m-%Y")
INCFILE="/root/tar-inc-backup.dat"
DAY=$(date +"%a")
FULLBACKUP="Sun"
### MySQL Setup ###
MUSER="admin"
MPASS="mysqladminpassword"
MHOST="localhost"
MYSQL="$(which mysql)"
MYSQLDUMP="$(which mysqldump)"
GZIP="$(which gzip)"
### FTP server Setup ###
FTPD="/home/vivek/incremental"
FTPU="vivek"
FTPP="ftppassword"
FTPS="208.111.11.2"
NCFTP="$(which ncftpput)"
### Other stuff ###
EMAILID="admin@theos.in"
### Start Backup for file system ###
[ ! -d $BACKUP ] && mkdir -p $BACKUP || :
### See if we want to make a full backup ###
if [ "$DAY" == "$FULLBACKUP" ]; then
FTPD="/home/vivek/full"
FILE="fs-full-$NOW.tar.gz"
tar -zcvf $BACKUP/$FILE $DIRS
else
i=$(date +"%Hh%Mm%Ss")
FILE="fs-i-$NOW-$i.tar.gz"
tar -g $INCFILE -zcvf $BACKUP/$FILE $DIRS
fi
### Start MySQL Backup ###
# Get all databases name
DBS="$($MYSQL -u $MUSER -h $MHOST -p$MPASS -Bse 'show databases')"
for db in $DBS
do
FILE=$BACKUP/mysql-$db.$NOW-$(date +"%T").gz
$MYSQLDUMP -u $MUSER -h $MHOST -p$MPASS $db | $GZIP -9 > $FILE
done
### Dump backup using FTP ###
#Start FTP backup using ncftp
ncftp -u"$FTPU" -p"$FTPP" $FTPS< mkdir $FTPD
mkdir $FTPD/$NOW
cd $FTPD/$NOW
lcd $BACKUP
mput *
quit
EOF
### Find out if ftp backup failed or not ###
if [ "$?" == "0" ]; then
rm -f $BACKUP/*
else
T=/tmp/backup.fail
echo "Date: $(date)">$T
echo "Hostname: $(hostname)" >>$T
echo "Backup failed" >>$T
mail -s "BACKUP FAILED" "$EMAILID" <$T
rm -f $T
fi

Setup a cron job

Just add a cron job as per your requirements:
13 0 * * * /home/admin/bin/ftpbackup.sh >/dev/null 2>&1

Generate FTP backup script

Since I setup many Linux boxes, here is my own FTP backup script generator. You just need to provided appropriate input and it will generate FTP backup script for you on fly.

Next time I will write more about this method.

Want to stay up to date with the latest Linux tips, news and announcements? Subscribe to our free e-mail newsletter or RSS feed to get all updates. You can Email this page to a friend.

You may also be interested in other helpful articles:

Discussion on This Article:

  1. Sean Says:

    On the mysqldump, there’s a -A option to do all databases at once (and –opt to make things more efficient). As you get a bigger database, look at mysqlhotcopy, only good for MyIASM tables but it’s a lot faster than mysqldumping.

    Sean

  2. nixcraft Says:

    Sean,

    I agree with you -opt is a nice option that adds locking and does extended insert and other stuff. I will update the script with -opt option.

    -A is good option but I prefer to backup individual database, as it offers the option of restoring individual databases.

    mysqldump –help says –opt option is Enabled by default :) so no need to change script

    Appreciate your post.

  3. SaM Says:

    Why is the size of the files created using mysqldump are far more than the database files itself?

    Rather if someone simply copies all database files to the backup directory..is there any harm…jst a question…

  4. nixcraft Says:

    SaM,

    You need to compress sql files using gunzip or other available utilities.

    mysqldump makes it easy to move data from one server to another.

    Hope this helps

  5. SaM Says:

    Nix,

    You may be right… but I am using a bit un-usual way of backing up tha data.. what I have done is that, I have created the database structure sql file of all that dtabases we are using. And copies the data files on regular basis.

    when it comes to retrieve the data, its a simple copy operation…off-cource need to change the ownership to mysql:mysql.

    In case I need to trash the datanase and recreate the database, i have the sql file of the structures.

  6. nixcraft Says:

    mysqldump also generates database, table structure along with data. Try out mysqldump command any one of the database you will see the difference.

  7. Ugo Bellavance Says:

    This script does ftp and e-mail backups.

  8. Ugo Bellavance Says:

    Sorry, here is the link

    http://worldcommunity.com/opensource/utilities/mysql_backup.html

  9. jishin Says:

    Another good solution for MySQL database backup is “AutoMySQL Backup” . It does all the things you need for daily backup.
    http://members.lycos.co.uk/wipe_out/automysqlbackup/

  10. nixcraft Says:

    jishin,

    Thanks for autmmysqlbackup script link :)

  11. Shawn Says:

    Thanks for the script. I’ll give it a whirl.

  12. dicky Says:

    if i also want to enter into database in this command “$ mysql -u root -h localhost -p -Bse ’show databases’” what can i do??

  13. Charlie Says:

    What about MySQLDumper? (backup, restore, FTP, mail, multipart, …)

    Well the bad thing is the vulnerabilities, like the common XSS thing:
    http://secunia.com/product/12282/?task=advisories

  14. Paul's Time Sink Says:

    Automatic backup to ftp server…

    This page has a pretty simple script for backing up specified directories, and all mysql databases to a ftp server….

  15. shaun Says:

    nixcraft, your script backs-up everything needed for my setup. It was instant success using the generator.

    Thank-you

    Shaun Prince

  16. Chris Says:

    Thanks for the script, is brilliant and does exactly what i need it to do.

    Just one slight real easy thing i’m sure, but how can i set the FTP port rather than using the standard port 21. If i ncftp manually, i can specify the -P option. Is it easy to put in the script?

    Thank you for the script.

  17. jim Says:

    So I backed up my MySQL database. How do I restore it? I have a mybackup.sql.gzip in my home. What do I do to restore it?

    Can I restore it to another machine with the same MySQL Version?

  18. vivek Says:

    Type the following commands restore the same:
    gunzip mybackup.sql.gzip
    mysql -u USER -p dbname < mybackup.sql

    You can copy file mybackup.sql.gzip using scp to another machine:
    scp mybackup.sql.gzip user@machinetwo:/tmp
    Login to machinetwo:
    cd /tmp
    gunzip mybackup.sql.gzip
    mysql -u USER -p dbname < mybackup.sql
    rm mybackup.sql

    Further readings
    (a) How can I restore a backup of a MySQL database?
    (b) Copy MySQL database from one server to another remote server

    HTH

  19. Atasa Rossios Says:

    Hi,
    this is very nice but i get the following errors:
    [: 47: ==: unexpected operator
    at the start of the script
    and
    [: 79: ==: unexpected operator
    at the end

    therefor I always get email with BACKUP FAILED!.\

    Line 47 is “fi”
    and Line 79 is the last “fi” at the very end.

    Thanx

  20. vivek Says:

    Copy and paste script again from wizard

    HTH

  21. Atasa Rossios Says:

    Thanx for the reply but I had more troubles
    with the long names with the mysqldump.
    Filezilla Server did not like the
    (mysql-LongDBname.$NOW-$(date +”%T”).gz) but was very happy when I took out the $(date +”%T”) part, which is fine with me I don’t care for the exact time so much.

    For the unexpected operator Error:
    I have the feeling that the == sign is not the case with “$var1″ == “$var2″.
    Therefore my system was complaining for syntax error(Ubuntu Server 7.04).
    From what I have seen on the net:
    you can say “$var1″ = “$var2″ OR $var1 == $var2.
    I haven’t taste the second option myself.
    But the first behaves very nice.
    Finally I just took out the -g option from tar because I could not restore from a windows machine when I try it.
    7zip could not understand the archive and could not extract the contents.

    Lastly I added a Open Ldap database backup too, and send a mail also in success!. I simply wanna know what is is happening with the backup process.

    Here it is now:

    #!/bin/sh
    ### System Setup ###
    DIRS="/etc /srv/www /var/www /home"
    BACKUP="/tmp/backup.${$}"
    NOW=$(date +%d-%m-%Y)
    INCFILE="/root/tar-inc-backup.dat"
    DAY=$(date +%a)
    FULLBACKUP="Fri"

    ### MySQL Setup ###
    MUSER="user"
    MPASS="passwd"
    MHOST="localhost"

    ### FTP server Setup ###
    FTPD="/backup/Ubuntu-Server/incremental"
    FTPU="user"
    FTPP="passwd"
    FTPS="192.168.2.50"
    NCFTP=$(which ncftpput)

    ### Other stuff ###
    EMAILID="user@domain.com"

    ### Start Backup for file system ###
    [ ! -d $BACKUP ] && mkdir -p $BACKUP || :

    ### See if we want to make a full backup ###
    if [ "$DAY" = "$FULLBACKUP" ];.
    then
    FTPD=”/backup/Ubuntu-Server/full”
    FILE=”fs-full-${NOW}.tar.gz”
    tar -zcvf $BACKUP/$FILE $DIRS
    else
    i=$(date +%Hh%Mm%Ss)
    FILE=”fs-i-${NOW}-${i}.tar.gz”
    tar zcvf $BACKUP/$FILE $DIRS
    fi
    ### Start MySQL Backup ###
    # Get all databases name
    DBS=”$(mysql -u ${MUSER} -h ${MHOST} -p${MPASS} -Bse ’show databases’)”
    for db in $DBS
    do
    FILE=$BACKUP/mysql-$db.$NOW.gz
    mysqldump -u $MUSER -h $MHOST -p$MPASS $db | gzip -9 > $FILE.
    done

    ##Backup the Ldap Directory Database
    slapcat -v -n 1 -l $BACKUP/LdapDirectory.ldif

    ## Dump backup using FTP ###
    #Start FTP backup using ncftp
    ncftp -u$FTPU -p$FTPP $FTPS$T
    echo “Hostname: $(hostname)” >>$T
    echo “Backup succesfully Completed!” >>$T
    mail -s “BACKUP COMPLETED” “$EMAILID” $T
    echo “Hostname: $(hostname)” >>$T
    echo “Backup failed” >>$T
    mail -s “BACKUP FAILED” “$EMAILID”

    Cheers A.

  22. Atasa Rossios Says:

    Sorry Here is the complete script hope this time is posted clear.
    #!/bin/sh
    ### System Setup ###
    DIRS="/etc /srv/www /var/www /home"
    BACKUP="/tmp/backup.${$}"
    NOW=$(date +%d-%m-%Y)
    INCFILE="/root/tar-inc-backup.dat"
    DAY=$(date +%a)
    FULLBACKUP="Fri"

    ### MySQL Setup ###
    MUSER="user"
    MPASS="passwd"
    MHOST="localhost"

    ### FTP server Setup ###
    FTPD="/backup/Ubuntu-Server/incremental"
    FTPU="user"
    FTPP="passwd"
    FTPS="192.168.2.50"
    NCFTP=$(which ncftpput)

    ### Other stuff ###
    EMAILID="user@domain.com"

    ### Start Backup for file system ###
    [ ! -d $BACKUP ] && mkdir -p $BACKUP || :

    ### See if we want to make a full backup ###
    if [ "$DAY" = "$FULLBACKUP" ];.
    then
    FTPD=”/backup/Ubuntu-Server/full”
    FILE=”fs-full-${NOW}.tar.gz”
    tar -zcvf $BACKUP/$FILE $DIRS
    else
    i=$(date +%Hh%Mm%Ss)
    FILE=”fs-i-${NOW}-${i}.tar.gz”
    tar zcvf $BACKUP/$FILE $DIRS
    fi
    ### Start MySQL Backup ###
    # Get all databases name
    DBS=”$(mysql -u ${MUSER} -h ${MHOST} -p${MPASS} -Bse ’show databases’)”
    for db in $DBS
    do
    FILE=$BACKUP/mysql-$db.$NOW.gz
    mysqldump -u $MUSER -h $MHOST -p$MPASS $db | gzip -9 > $FILE.
    done

    ##Backup the Ldpa Directory Database
    slapcat -v -n 1 -l $BACKUP/LdapDirectory.ldif

    ## Dump backup using FTP ###
    #Start FTP backup using ncftp
    ncftp -u$FTPU -p$FTPP $FTPS$T
    echo “Hostname: $(hostname)” >>$T
    echo “Backup succesfully Completed!” >>$T
    mail -s “BACKUP COMPLETED” “$EMAILID” $T
    echo “Hostname: $(hostname)” >>$T
    echo “Backup failed” >>$T
    mail -s “BACKUP FAILED” “$EMAILID”

  23. Atasa Rossios Says:

    However you got the my point!

  24. Atasa Rossios Says:

    maybe cut it in pieces
    #!/bin/sh
    ### System Setup ###
    DIRS="/etc /srv/www /var/www /home"
    BACKUP="/tmp/backup.${$}"
    NOW=$(date +%d-%m-%Y)
    INCFILE="/root/tar-inc-backup.dat"
    DAY=$(date +%a)
    FULLBACKUP="Fri"

    ### MySQL Setup ###
    MUSER="user"
    MPASS="passwd"
    MHOST="localhost"

    ### FTP server Setup ###
    FTPD="/backup/Ubuntu-Server/incremental"
    FTPU="user"
    FTPP="passwd"
    FTPS="192.168.2.50"
    NCFTP=$(which ncftpput)

    ### Other stuff ###
    EMAILID="user@domain.com"

    ### Start Backup for file system ###
    [ ! -d $BACKUP ] && mkdir -p $BACKUP || :

    ### See if we want to make a full backup ###
    if [ "$DAY" = "$FULLBACKUP" ];.
    then
    FTPD=”/backup/Ubuntu-Server/full”
    FILE=”fs-full-${NOW}.tar.gz”
    tar -zcvf $BACKUP/$FILE $DIRS
    else
    i=$(date +%Hh%Mm%Ss)
    FILE=”fs-i-${NOW}-${i}.tar.gz”
    tar zcvf $BACKUP/$FILE $DIRS
    fi

    And the Second part:
    ### Start MySQL Backup ###
    # Get all databases name
    DBS="$(mysql -u ${MUSER} -h ${MHOST} -p${MPASS} -Bse 'show databases')"
    for db in $DBS
    do
    FILE=$BACKUP/mysql-$db.$NOW.gz
    mysqldump -u $MUSER -h $MHOST -p$MPASS $db | gzip -9 > $FILE.
    done

    ##Backup the Ldap Directory Database
    slapcat -v -n 1 -l $BACKUP/LdapDirectory.ldif

    ## Dump backup using FTP ###
    #Start FTP backup using ncftp
    ncftp -u$FTPU -p$FTPP $FTPS

    And the Third Part:
    ### Find out if ftp backup failed or not ###
    if [ "$?"="0" ];.
    then
    rm -f $BACKUP/*
    echo “Date: $(date)”>$T
    echo “Hostname: $(hostname)” >>$T
    echo “Backup succesfully Completed!” >>$T
    mail -s “BACKUP COMPLETED” “$EMAILID” $T
    echo “Hostname: $(hostname)” >>$T
    echo “Backup failed” >>$T
    mail -s “BACKUP FAILED” “$EMAILID”
    Hope now it works to see the hole script.

  25. IAn Says:

    About date localization

    The command DAY=$(date +%a) is sensible to the system language,
    I prefer to use DAY=$(date +%u) to know the number of the day of the week

  26. dk Says:

    I was looking for something like this…

    just one question: to send the email of a failed backup what program do I have installed in my pc?

    Thankyou

  27. vivek Says:

    dk,

    use normal unix mail command

  28. WR Says:

    Thanks for the info.. just wondering, does it work with a regular ftp client? I’m on a shared hosting shell account and it doesn’t look like ncftp is installed.

  29. Kjell Says:

    Hi!

    Thank you for this nice tutorial!!

    I have a setup with 2 HDDs, having the second as active mysql database storage and another partition for this backup script.

    I have modified it to just move the files to the second HDD instead of transfering via FTP and made it so that folders with $NOW are created before moving.

    I am wondering how the $INCFILE works? If i want to restore the “fs” from a week before, do i have to use the initial (bigger) TAR which is in the first folder, or does it work with the smaller ones that are i.e. in the folder of today?

  30. vivek Says:

    You need to restore the last full backup first (
    $FULLBACKUP day), followed by each of the subsequent incremental backups to the present day in the correct order.

  31. kvz Says:

    Here’s a script that can transfer all mysql databases to another server.

  32. Gustavo Hartmann Says:

    Hello,

    When I run this script from the command line it works fine but when I run it as a cron job, the FTP connection seems to drop at some point and not all files are not copied over. The FTP server says “disconnected” so as ncftp client logs.

    It happens all the time and it is a bit weird. Any clues?

    Thanks,G

  33. Chip Says:

    Heelo,

    tks for the script.

    I have a problem when running the script with a cron job, it will do the backup but it will not upload via http://ftp. Any idea why?

    Best regards,
    Nuno

  34. robertvvv Says:

    Why not try to use mysqlhotcopy to make a backup

  35. Berto Says:

    This looks great, but in Ubuntu 7.10, ncftp isn’t working.

    the command
    ncftp -u”$FTPU” -p”$FTPP” $FTPS<

    gives an error:
    wwwbackup.sh: 53: Syntax error: newline unexpected

    If I remove the < at the end, it will log in, but then it won’t send the commands to ncftp (after NCFTP quits, it will try running those commands on my own shell!)

    Are there ny other way to get ncftp to take commands from the shell script?

  36. Berto Says:

    OK I think I solved my problem by using ncftpput*

    I used this line instead of the ncftp lines you have:
    ncftpput -u “$FTPU” -p “$FTPP” -m “$FTPS” $FTPD/$NOW $BACKUP/*

    and commented out the ncftp command through EOF command.

    * by the way, why do you get the path of ncftpput and never use it?

  37. vivek Says:

    Berto,

    It is a bug, I will try to fix it. Thanks for the heads up.

  38. Berto Says:

    Even more information on my humiliations in Ubuntu:

    They made dash the default shell script, not bash!* So you need to specify $!/bin/bash (not $!/bin/sh) for this to work properly. dash also had problems with the equivalency (==) operator at the end.

    This will probably fix the ncftp problems, but since I already have ncftpput working, I’ll keep it.

    *From http://ubuntuforums.org/showthread.php?t=265391

  39. dave Says:

    Firstly, Thank you so much for this script. I’ve learnt so much just from following it through, and it works perfectly on CentOS 4 after installing ncftp.

    Is there a way you can tell it to exclude files? For example, I’ve set it to back up the whole of a certain folder, but there is one sub folder within that I do not want backing up… is this possible?

    Thanks!

  40. Ken Edwards Says:

    Hi,

    I have two questions. I would have multiple databases to back up in most cases, and multiple users assigned to multiple databases. How would that work?

    Many thanks!

    Ken

  41. Randy Keyes Says:

    I am getting an error

    line53: syntax error near unexpected token ‘do
    line53: ‘do

  42. Internet Marketing Legacy Says:

    Very helpful. I’m experimenting with setting up a couple servers of my own, and this script is exactly what I was looking for. Thanks for sharing.

  43. Tim1981 Says:

    You can also use:

    /usr/bin/md5sum -b $BACKUP/* >$BACKUP/backup$NOW-$i.md5

    Between backup and transfer, so you can verify if the files aren’t modified during transfer or something.

  44. Adrian Says:

    This seems to work well, except when I run it it just does incremental backups. Of what, I’m not sure, as there has not been a full backup yet. Invariably it generates just a 48kb file. The database alone should be at least 800kb… Is there any way to force a full backup? How can I check that this script is working properly?

    Thanks,
    Adrian

  45. vivek Says:

    Backup is compressed using gzip; just uncompressed and verify data. By default full backup is made on Sunday; Change FULLBACKUP=”Tue” variable.

  46. wulfman Says:

    thank you for a wonderful script. works perfectly

  47. Chris Says:

    In this:

    if [ "$?" == "0" ]; then

    you are checking the return of ncftp, but it always returns “0″

    I even altered the password to force it to error and still it returned “0″.

    Has anyone confirmed that this will show anything other than “0″?

    I did this to check before the if statement

    echo “Return Code = $?”

  48. Sean Says:

    for some unknown reason if i run the script manually it works as it should. everything is zipped up and sent to the ftp server.

    However if i set up a cron job all the files are zipped up and placed in the /tmp dir (so i know the script is running) but the files are never sent to the ftp server.

    i’ve tried this with several ftp servers etc. etc. with no luck.

  49. oh4real Says:

    Thanks heaps. Clever script. Worked fully once I gave mysql user LOCK privileges. Very helpful.

    Might suggest putting php.txt link up at top of wizard page. I entered dummy info, not wanting to send IPs and logins to php script. I now have the script itself and could generate again.

    Nice work and thanks for sharing.

Leave a Reply

We encourage your comments, and suggestions. But please stay on topic, be polite, and avoid spam. Thank you very much for stopping by our site!

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word

Tags: , , , , , , , , ,

Copyright © 2004-2008 nixCraft. All rights reserved - TOS/Disclaimer - Privacy policy - Sitemap - Powered by Open source software.