Ubuntu WordPress Bash backup scripts

Since my recent scare losing a table in MySQL while trying various back-up plug-ins in WordPress I decided to just make my own back-up script in Ubuntu. Eventually I’ll back-up to a local folder, and then rsync from there to some kind of rsync server – maybe I could use a Raspberry Pi 0 in that capacity? (Eventually of course I’ll be looking to use Docker for various images including different WordPress installation but at the moment WordPress is just running on a LAMP/Ubuntu VM hosted by Windows with a handy shared-folder).

Although I’ve used various flavours of Linux on and off for decades, I’ve always been Windows focused and never really spent long enough in terminals in Linux to feel comfortable. This is my first real attempt at putting together some Bash scripts myself (obviously with the continual help of Google lol).

nb: I use WordPress on Windows with IIS and as I have Acronis set-up on there I never worry about back-ups – but am heading towards Docker (mostly linux based) where ever it makes sense in terms of maximising use of hardware, low-energy, and for long-term maintenance and management. (I do admittedly still see “containers” as pets but am forcing myself to see them as “cattle” … it’s painful but necessary).

First of all I looked at copying my simlinks into the cron.daily, cron.weekly and cron.monthly directories or virtual directories or whatever they are but that didn’t get me anywhere – and then I figured the crontab -e route was the way to go (using sudo so that the symlink/regular virtual file would run with the root owner).

Oops – got dom – day of month, and mon – month mixed-up on first attempt.


# delete old WordPress back-ups, but only if there are existing back-ups
# only daily and weekly (not touching monthly)
# 2017, Feb: dave@xarta.co.uk  (first "proper" BASH script - woohooo!)

# nb: might change back-ups in the future to use local folder, and then rsync over ssh


# doing this "assignment" way to avoid empty string from wc -l (instead of "0").
count_bkup_d_before=$(find $bkup_daily -type f | wc -l)
count_bkup_w_before=$(find $bkup_weekly -type f | wc -l)

if [ $count_bkup_d_before -gt "28" ]; then
    find $bkup_daily -mtime +27 -type f -delete

if [ $count_bkup_w_before -gt "5" ]; then
    find $bkup_weekly -mtime +34 -type f -delete

count_bkup_d_after=$(find $bkup_daily -type f | wc -l)
count_bkup_w_after=$(find $bkup_weekly -type f | wc -l)

# Making separate log in shared folder, so Acronis on host of shared-folder backs-up online, too
# (logger -s "blah" 2>>$something etc. will make a user thingy entry in syslog AND $something)
logger -s "Deleting old WP backup files" 2>> $wp_backup_log

logger -s "WP daily bkup files: before $count_bkup_d_before, after $count_bkup_d_after" 2>> \

logger -s "WP weekly bkup files: before $count_bkup_w_before, after $count_bkup_w_after" 2>> \




# 2017, Feb: dave@xarta.co.uk

# daily, weekly, monthly use simlink name "0" e.g. bkup_daily.sh
# e.g. avoid duplicate code - just one back-up script (+ delete-files script)
# bkup_daily
# bkup_monthly
# bkup_weekly

#TODO look at including DB_BKUP_FOLDER etc in the basename
filename=$(basename "$0")


# TODO look at using a config file for paths
# TODO look at reading-in password from elsewhere - some kind of vault or something
read -d $'\x04' DB_PASS < /home/davros/WPbackups/MySQLpassword

today=`date '+%Y_%m_%d__%H_%M_%S'`;

# (mySql root and root-password)
/usr/bin/mysqldump -u root -p$DB_PASS  $DB_NAME | gzip > $targetoutputsql


if [ -f $targetoutputsql ]; then
    if [ $type == "bkup_weekly" ] || [ $type == "bkup_monthly" ]; then
	    # back-up WP files too (organically bolted-on)
	    find $SITE_PATH -mindepth 2 -type f -print0 | tar \
		 --exclude="updraft" --exclude="wp-admin" --exclude="wp-includes" \
		 -czvf $targetoutputfiles1 --null -T -

	    find $SITE_PATH  -maxdepth 1 \( -name "wp-config.php" -o -name ".htaccess" \) \
		 -type f -print0 | tar \
		 -czvf $targetoutputfiles2 --null -T -

	    # delete old backups, if any
    # TODO error-handling
    logger -s "ERROR: $targetoutputsql" 2>> $wp_backup_log
    echo "ERROR: $targetoutputsql"

# notes on sudo crontab -e
# if owner of this file MySQLdump.sh is root, even if simlink bkup_daily is me,
# ... then use "sudo" for crontab -e so runs as root (for mysqldump command)
# ... I'm just giving MySQLdump.sh and symlinks rwx at least for owner, for now

# Example of job definition (copied off internet somewhere):
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed

# 01 22 *  *  * /home/davros/WPbackups/bkup_daily.sh     ... symlink to MySQLdump.sh
# 05 22 *  *  0 /home/davros/WPbackups/bkup_weekly.sh    ... symlink to MySQLdump.sh
# 10 22 1  *  0 /home/davros/WPbackups/bkup_monthly.sh   ... symlink to MySQLdump.sh


I believe it should be possible to run c# “script” instead of bash to achieve the same goals. I’ve seen it done using a bash shim that uses mono to compile the code transparently and deal with command line arguments and console output etc. I’ll have to look into doing something similar for .NET Core. It seemed wise to become at least basically familiar with bash so I can better understand others’ solutions to Linux problems (and as I’m beginning to use Linux more and more for low-cost / low-energy distributed-style options). Oh – and of course – Bash now runs on windows! (Still prefer PowerShell so far).