ThingyMaJig

Thingy Ma Jig is the blog of Nicholas Thompson and contains any useful tips, sites and general blog-stuff which are considered interesting or handy!

Connect

LinkedIn GitHub

Topics

announcement 25 apache 3 Apple 1 bash 8 code 7 cool 30 Days Out 8 Dark Basic Pro 4 design 12 doctor who 1 Drupal 74 E4600 1 EOS 400D 3 firefox 2 Flickr 3 free 21 games 5 geek 38 git 2 GreaseMonkey 1 hardware 7 Homebrew 1 How to 37 humour 5 iphone 1 javascript 1 jquery 1 K800i 6 k850i 4 lighttpd 3 linux 33 mac 9 miscellaneous 4 mobile phone 9 music 4 mysql 8 n73 1 n95 1 New Relic 1 Ogre3D 1 OS X 2 performance 3 photos 10 programming 40 Quicksilver 1 review 19 security 3 SEO 6 software 12 svn 2 technology 4 tip 7 tips 10 tv 3 video 3 vim 7 webdev 2 websites 33 wii 1 windows 1 YADS 10

Backing up a Drupal Database: Redux

Posted on 27 April 2009 in
tip linux How to geek Drupal code bash

Back in November last year, I wrote a script which handled backing up a drupal database. There were quite a few comments and I've taken some on board and developed the script on a little further to be more "generic".

One of the main complaints/suggestions about my previous snippet was the hard coded nature of it. The follow script offers far more configuration through the command line itself.

#!/bin/bash

# Define the options for this command
OPTION_SPEC="help,database:,file:,user:,password:,exclude:,exclude-drupal-tables,prefix:"
PARSED_OPTIONS=$(getopt -n "$0" -a -o h --long $OPTION_SPEC -- "$@")
OPTIONS_RET=$?
eval set -- "$PARSED_OPTIONS"

# Define an array of tables to be exluded
DBEXCLUDE=( )

# Define an array of table prefixes
DBPREFIX=( )



# Define a usage help function
usage() {
  cat <<HELP
Usage: `basename $0` --database=DATABASE_NAME [OPTIONS]

Options:
  --database=DATABASE_NAME
  -d DATABASE_NAME            Database to dump

  --file=FILENAME
  -f FILENAME                 Filename you to dump the database to, defaults to DATABASE.sql

  --user=USERNAME
  -u USERNAME                 Username for accessing the database, defaults to the user running the script

  --password=PASSWORD
  -p PASSWORD                 Password for accessing the database, defaults to blank

  --exclude=TABLE_NAME
  -e TABLE_NAME               Name of a table to exclude from the full dump (will do structure only).
                              Multiple excludes can be passed

  --exclude-drupal-tables     Enables a preset of tables which hold temporary/cached data which do not need dumping

  --prefix=PREFIX
  -pr PREFIX                  Optional table prefix.
                              Eg, you might want to exclude a table called "cache" and
                              this table might appear several times with different prefixes
Example:
  drupaldump -d my_database -u joe_bloggs --password=myPassw0rd --file=dump.sql -e cache -e stats -e logs --prefix=foo -pr bar
HELP
}



# Some kind of test on the options... 
if [ $OPTIONS_RET -ne 0 ] || [ $# -le 0 ]; then
  usage;
  exit 1;
fi


# Loop over all the options and pull out settings for the database, user, password, etc
while [ $# -ge 1 ]; do
  case $1 in
    --help | -h )                     usage; exit 1;;
    --database | -d )                 shift; DB="$1";;
    --file | -f )                     shift; DBFILE="$1";;
    --user | -u )                     shift; DBUSER="$1";;
    --password | -p )                 shift; DBPASS="$1";;
    --exclude | -e )                  shift; DBEXCLUDE[${#DBEXCLUDE[*]}]="$1";;
    --exclude-drupal-tables | -edt )  DBEXCLUDE=( "${DBEXCLUDE[@]}" accesslog watchdog sessions cache\(_.+\)? search_\(.+\) devel_\(.+\) );;
    --prefix | -pf )                  shift; DBPREFIX[${#DBPREFIX[*]}]="$1";;
    -- ) shift;;
    * ) echo "ERROR: unknown flag $1"; usage; exit 1;;
  esac

  shift
done


# Get the database from the commandline
if [ ! -n "$DB" ]
then
  # Print an error & usage suggestion
  echo "`basename $0`: Missing database"
  usage; exit 1
fi


# If the database isn't already set, then set it...
if [ ! -n "$DBFILE" ]
then
  # Define the start time - this is used as a filename stub
  START_TIME=$(date +%Y%m%d%H%M);

  # Define a default DB File
  DBFILE="${START_TIME}-${DB}.sql"
fi

# Create an empty file in that place
 > $DBFILE



# Define the username, if it's not already set
if [ ! -n "$DBUSER" ]
then
  DBUSER=""
else
  DBUSER="--user=${DBUSER}"
fi


# Define the password, if it's not already set
if [ ! -n "$DBPASS" ]
then
  DBPASS=""
else
  DBPASS="--password=${DBPASS}"
fi


# Define the default 'structure only' tables
DBEXCLUDE_TABLES=""
ELEMENT_COUNT=${#DBEXCLUDE[@]}
if [ "$ELEMENT_COUNT" -gt 0 ]
then
  INDEX=0

  while [ "$INDEX" -lt "$ELEMENT_COUNT" ]
  do
    DBEXCLUDE_TABLES="${DBEXCLUDE_TABLES}|${DBEXCLUDE[$INDEX]}"
    let "INDEX = $INDEX + 1"
  done

  DBEXCLUDE_TABLES="(${DBEXCLUDE_TABLES:1})"
fi

# Define the structure only optional table prefixes
DBPREFIX_TABLES=""
ELEMENT_COUNT=${#DBPREFIX[@]}
if [ "$ELEMENT_COUNT" -gt 0 ]
then
  INDEX=0

  while [ "$INDEX" -lt "$ELEMENT_COUNT" ]
  do
    DBPREFIX_TABLES="${DBPREFIX_TABLES}|${DBPREFIX[$INDEX]}"
    let "INDEX = $INDEX + 1"
  done

  DBPREFIX_TABLES="(${DBPREFIX_TABLES:1})?"
fi

# Define the structure only regex
STRUCTURE_ONLY="/^${DBPREFIX_TABLES}${DBEXCLUDE_TABLES}$/"

# Get the tables from the database
TABLES=`mysql ${DBUSER} ${DBPASS} --batch --skip-column-names -e 'show tables;' ${DB}`

if [[ $? > 0 ]]
then
  echo "Exiting for some kind of error... $?"
  exit 1
fi


# Status message
echo "  Starting dump of ${DB}"


# Loop over the tables
for T in $TABLES; do
  # Test if the table matches the 'structure only' regex
  RESULT=`echo "$T" | gawk "$STRUCTURE_ONLY"`

  # if a match...
  if [ $RESULT ]
  then
    echo "    STRUCTURE : ${T}"
    NODATA="--no-data"
  else
    echo "    FULL      : ${T}"
    NODATA=""
  fi

  # Dump the table onto the end of the DBFILE with the data or no data option
  mysqldump ${DBUSER} ${DBPASS} --opt --skip-comments ${NODATA} ${DB} ${T} >> $DBFILE
done


# Finish Message
echo "  Done"
exit 0

Essentially this is the same script as in my previous post, however I've added functionality to provide a custom username, password, database, file, exclude (structure only) and optional-table-prefix...

Comments & suggestions welcome :)

Oh - one final thing… You can find the file for download in my Drupal Sandbox…

http://cvs.drupal.org/viewvc.py/drupal/contributions/sandbox/nicholasThompson/drupaldump/