Easily backup relevant data in a 7-day rotation.
The idea is to initially edit the script's variables to fit your situation, then cron it to run daily. Any arbitrary files, directories, and/or MySQL databases may be included in the archive. The resulting backups will automatically rotate on a 7-day basis, without user intervention, by merit of the day of the week in their filenames.
| Application | Information |
|---|---|
| bash | The Bourne Again SHell, available in most if not every distribution of Linux and UNIX (though not always installed by default). |
| gzip or bzip2 | Depending on whether you prefer gzip or bzip2 archives, you'll need either the gzip or bzip2 archiver. |
| pbzip2 or pigz | Optional, but highly recommended on multi-core systems; pbzip2 is a parallel BZIP2 archiver, while pigz does GZIP. |
| mysqldump | Strictly speaking mysqldump is optional, though necessary if you want to perform MySQL database backups. |
Once the requirements are met, you simply need to place the script someplace in your path. There are two ways to accomplish this:
In either case, you will probably need root privileges first, e.g.:
su -
…or:
sudo su -
If you will be copying and pasting the script, use your favorite text editor to create the file in question. In this example, I'll use vim:
vim /usr/local/bin/backatronic.sh
…then paste in the code on this page, save, and exit.1) Finally, make the resulting file executable:
chmod 755 /usr/local/bin/backatronic.sh
Alternately, you could skip the text editor and just grab the file directly:
wget http://tuxhelp.org/pub/scripts/backatronic.sh -O /usr/local/bin/backatronic.sh && chmod 755 /usr/local/bin/backatronic.sh
Or the same, but with curl instead of wget:
curl http://tuxhelp.org/pub/scripts/backatronic.sh > /usr/local/bin/backatronic.sh && chmod 755 /usr/local/bin/backatronic.sh
Usage is easy: just edit the variables in backatronic.sh to meet your needs, then execute the script as the user you've defined in BACKUPUSER. If the processes completes uneventfully, it will exit silently.2) It's recommended to call backatronic.sh with a cron job in order to fully automate your backups.
#!/bin/bash ######################################################### # Backup relevant data in a 7-day rotation # ######################################################### # By Christopher A. Wadge, 09/15/2010 # # # # http://tuxhelp.org/scripts/backatronic # # # # Licensed under the GPL version 3. A copy of the GPL # # version 3 is included with this script. If the file, # # COPYING, is not included, you can find the GPL # # version 3 at the following URL online: # # # # http://www.gnu.org/licenses/gpl-3.0.html # ######################################################### # This script's name: PROGRAM_NAME="backatronic.sh" # Date of last revision: PROGRAM_DATE="10/26/10" ## VARIABLES ## # The following are pre-determined variables that are not answered by the script. ##### ## Executable Paths ## # Compression format (tar.'XXX', e.g. 'gz' or 'bz2'): COMPFORMAT="bz2" # Compression Utility to accomplish the above ('pbzip2' or 'pigz' recommended for multi-core systems): COMPUTIL="/usr/bin/pbzip2" ## Directory Paths ## # Where to keep our temporary files (no trailing slash): TEMPDIR="/tmp" # Arbitrary prefix for temporary mysql working directory: TEMPPREFIX="mysql-temp" # Where to put our finished archives: BACKUPDEST="/var/backups/weekly/" ## Backup Variables ## # Nice priority level for compression (19 to -20, 19 being the lowest): PROCNICE="10" # User as whom to run the archive: BACKUPUSER="root" # Should we backup mysql, or just files? DOMYSQL="true" # What to prefix the archive names with: ARCHPREFIX="`hostname`" # Files or directories for archival (space seperated): FILELIST="" # Databases for archival (one per line): DBLIST=" " # Extra Options to feed to 'mysqldump' if any; # (e.g. username / password if you don't already # have it stored in ~/.my.cnf): XTRAOPTS="" ## !!! Attention Users: Editing below this line is not advised unless you really know what you're doing. ## FUNCTIONS ## # Define each function that we will call in scripting later ##### Error () { echo "[FATAL] Unfortunately we've encountered an error. Now quitting." Delete_Temp exit 1 } Print_Help () { echo "" echo "==== $PROGRAM_NAME ($PROGRAM_DATE) ====" echo "" echo "Description: Backup all relevant data in a 7-day rotation." echo "" echo "Usage: Copy / Edit the script, edit relevant variables." echo " If desired, reference it in a cron job." echo "" echo "Dependancies: 'bzip2' or 'gzip', 'mysqldump'" echo " Optional: 'pbzip2', 'pigz'" echo "" exit 1 } Sanity_Check () { if [ `whoami` != "$BACKUPUSER" ]; then echo "[ERROR] Script must be run as $BACKUPUSER" Error fi if [ ! -e /bin/bash ] ; then echo "[ERROR] It doesn't appear that you have the Bourne Again SHell (aka 'BASH')!" echo " The [over-hyped] 'DASH' shell is too primitive to interpret this script." echo " Please use your package manager to install 'bash' and try again." NOTSANE=1 fi if [ ! -e $COMPUTIL ] ; then echo "[ERROR] The compression utility is not in the expected location: '$COMPUTIL'" echo " If none are installed, 'pigz' is quite fast: http://www.zlib.net/pigz/" echo " Or if you prefer better compression, 'pbzip2': http://compression.ca/pbzip2/" echo " Otherwise, you can correct the path by editing the VARIABLES section of this script." NOTSANE=1 fi if [ ! -z $NOTSANE ] ; then echo "[ERROR] Missing dependencies prevent this script from proceeding!" Error fi } Try_MySQL_Local () { if [ -z "$XTRAOPTS" ] ; then if [ -f $HOME/.my.cnf ] ; then if [ `grep -c password $HOME/.my.cnf` = 1 ] ; then XTRAOPTS="-u`grep ^user $HOME/.my.cnf | awk -F \= '{ print $2 }' | head -1` -p`grep ^password $HOME/.my.cnf | awk -F \= '{ print $2 }' | head -1`" fi fi fi } Create_Temp () { TEMP_PATH="$TEMPDIR/$TEMPPREFIX-`date +%F.%H%M%S`" mkdir -p $TEMP_PATH || $( echo "[ERROR] Unable to create temp directory at $TEMP_PATH" ; Error ) chmod 700 $TEMP_PATH || $( echo "[ERROR] Unable to set secure privileges on temp directory at $TEMP_PATH" ; Delete_Temp & Error ) } Delete_Temp () { rm -rf $TEMP_PATH || echo "[WARNING] Unable to delete temp directory at $TEMP_PATH" } Create_BackupDest () { if [ ! -d $BACKUPDEST ] ; then mkdir -p $BACKUPDEST || $( echo "[ERROR] $BACKUPDEST could not be created or is not a directory." ; Error ) chmod 700 $BACKUPDEST || $( echo "[ERROR] Unable to set secure privileges on backup destination $BACKUPDEST" ; Delete_Temp & Error ) fi } MySQL_Dump () { for db in $DBLIST ; do mysqldump $XTRAOPTS $db > $TEMP_PATH/db-$db-`date +%F`.sql || $( echo "[ERROR] Unable to complete SQL dump of $db" ; Delete_Temp & Error ) ; done } Create_Archive () { if [ " $DOMYSQL " = " true " ] ; then nice -n $PROCNICE tar cPf $BACKUPDEST/$ARCHPREFIX-`date +%a`.tar.$COMPFORMAT \ --use-compress-prog=$COMPUTIL $TEMP_PATH/db*.sql $FILELIST || $( echo "[ERROR] Unable to create $BACKUPDEST/$ARCHPREFIX-`date +%a`.tar.$COMPFORMAT" ; Delete_Temp & Error ) else nice -n $PROCNICE tar cPf $BACKUPDEST/$ARCHPREFIX-`date +%a`.tar.$COMPFORMAT \ --use-compress-prog=$COMPUTIL $FILELIST || $( echo "[ERROR] Unable to create $BACKUPDEST/$ARCHPREFIX-`date +%a`.tar.$COMPFORMAT" ; Delete_Temp & Error ) fi } ## SCRIPTING ## # Here's where we actually do all the work ##### if [ " $@ " = " --help " ] ; then Print_Help fi Sanity_Check if [ " $DOMYSQL " = " true " ] ; then Create_Temp Try_MySQL_Local MySQL_Dump fi Create_BackupDest Create_Archive if [ " $DOMYSQL " = " true " ] ; then Delete_Temp fi exit 0