Backup Workflow and Scripting

November 10, 2014

Categorized: Kate's Updates

Please-please-please don’t refer to anything said in here as a guide or true, unless it comes accompanying a supporting link (and even there, yeah, do your research). I’m learning this stuff and it definitely should not be taken as a how-to, tutorial, etc. If you have input and ways for me to improve what I’ve done or other suggestions, I appreciate it. Thanks!


Objective

What I wanted to was create a bash backup script going through cron jobs. Such a simple sentence, yes? It took me some fighting. It feels longer than it was, really. I don’t get a lot of solid troubleshooting time at work. That hurts, and makes everything a zillion times harder. But! I got it done, both for work and for my personal server.

First Script

I tried this script first. I am not sure why it didn’t work, but as someone pointed out on Unix & Linux, the $HOME is not necessary. Instead, the initial file paths can be called absolutely.

Maybe the script was written that way to be more flexible in terms of use across different sorts of servers, but in my case, removing $HOME and replacing the initial variables with various paths for the two directories didn’t fix it. I’m pretty sure the change I made on the second script with tar options would’ve worked for this one, though.

Second Script

This is the one I tried next. It worked! But I had to alter it on two different servers to get it going. And — in the end, I ended up significantly altering it anyway. I didn’t see the point of annual back-ups, and the monthly back-up of SQL seemed superfluous.

Issues & Changes

JustHost

The script was creating the folders and files, and I could enter and manipulate them — but they were empty. I changed cp -rf to cp -rfa. The -a option is the same as -dpR (preserve links, append source path to directory, copy directories recursively). I have no idea why this worked, but it did, so there’s that.

I also changed the tar options: tar -zcvf became tar -czvf. This question helped (and made me feel less terrible with the wonderful comic).

GoDaddy

When the script ran, it was creating folders like it was supposed to — but it wasn’t moving them anything into where it was supposed to go. Over FTPS, I also could not enter the folders it created. I later learned from GoDaddy support these folders and files were actually being created with illegal character names… dangit. But — I did get it to write directly to the directory where I wanted backups to live by pulling the tmp directory creation and copy/pasting out.

I also changed tar -zcvf to tar czvf.

Both

Structural

I ended up splitting the scripts up: I created one for files, one for the databases. The database script is set to run on a daily cron, whereas the files are weekly. I might decrease that to once every two weeks or once a month on some of my sites that don’t change often. For others, though, the files change and so I gotta make more frequent back-ups than that.

On JustHost, I’m using a single back-up directory, so I set up different backup folders for each of my sites, each with a script for themselves. I used a master script in the upper directory to call the rest of these scripts — again, one for files, one for databases — so I could set the master scripts to run at different times.

Additions

I added a statement to the database backups script, deleting any backups older than seven days. I added a statement to the files backup to delete after sixty days. No good to let everything get full of gunk and old backups, right?

No SSH

In this situation in particular, troubleshooting was… not fun. The first server I was working on was a GoDaddy managed dedicated server. There’s no SSH access on managed dedicated servers, so I was not able to run the script directly through the terminal. I left it to run every minute on a cron job while developing.

It was much easier once I gave up on the dedicated server and went for SSH on my personal server. It helped that I wasn’t being kicked out of “working mode” by down-minutes between saving the file and waiting for it to run. More than anything, clearly — it helped to see errors!

Server Backups to Local Backup

Backups on the server itself isn’t where it stops, oh no. If the server is wiped, there go the back-ups.

So I did this article’s tutorial. It was relatively easy — I had some issue getting the script to connect at first, but this was resolved by pulling my saved FTP connection from the subfolder and into the root WinSCP saved logins folder. Voila, pulling automatically from the live website to my local hard drive once a week on Windows Task Scheduler.

Local Backup to Network Drive

This part was really fast. I created a Windows batch file, using xcopy with a couple flags to take the files from my local hard drive to the shared network drive. I set that to run weekly, the day after the weekly server to local backups run, from the Task Scheduler as well.

Voila. Three backups: live server, local hard drive, shared network drive. Sucks if we get a server failure and a facility fire in the same day, but one can only do so much for free.

Final Structure & Code

This is what I got up and running on my personal server. Again, I pulled this stuff out of this script. I’m not sure of the etiquette of this on GitHub, as it’s pretty different/separated, so I’m crediting here and I’ve left credit in the two files where significant portions are taken from that script.

Structure

Everything lives in the home directory, (I think that’s usually the / or starting directory when you log in via FTP or SSH). This is safe because the stuff up here isn’t accessible over the Internet. If your backups live in the same folder as your website, that’s a security problem, so it’s important this stuff stays up there. Conversely, if someone can access these files, chances are pretty good they can do a lot more damage than just access the back-ups.

Files

On my personal server, one of these went into a folder for each individual website.

#!/bin/sh
# modified https://github.com/dlabey/Simple-Linux-Bash-Rotating-Backup-Script
# files back-up only
# Local Source
SOURCE=/home/user/public_html/site/

# Local Destination
DESTINATION=/home/user/backup/site/

# Date Variables
DAY_OF_WEEK_RAW=$(date '+%w')
DAY_OF_WEEK=$((DAY_OF_WEEK_RAW + 1))

# Make Weekly Folder
mkdir ${DESTINATION}/files/
echo 'Made weekly folder...'

# Make The Weekly Backup
# tar the files
tar -czvf ${DESTINATION}/files/${DAY_OF_WEEK}_files.tar.gz $SOURCE
echo 'Made weekly backup...'

# find and delete files older than 60 days
find ${DESTINATION}/files/ -type f -mtime +60 -exec rm {} \;

Database

On my personal server, one of these went into a folder for each individual website.

#!/bin/sh
# modified https://github.com/dlabey/Simple-Linux-Bash-Rotating-Backup-Script
# database back-up only
# Local Destination
DESTINATION=/home/user/backup/site/

# Database Backup User
DATABASE='database_name'
DATABASE_USER='database_user'
DATABASE_PASSWORD='database_password'
DATABASE_HOST='localhost'

# Date Variables
DAY_OF_WEEK_RAW=$(date '+%w')
DAY_OF_WEEK=$((DAY_OF_WEEK_RAW + 1))

# Make Weekly Folder
mkdir ${DESTINATION}/database/
echo 'Made weekly folder...'

# Make The DAILY Backup
mysqldump -h $DATABASE_HOST -u $DATABASE_USER -p$DATABASE_PASSWORD $DATABASE > $(dirname $0)/${DAY_OF_WEEK}.sql
tar -zcvf ${DESTINATION}/database/${DAY_OF_WEEK}_database.tar.gz $(dirname $0)/${DAY_OF_WEEK}.sql
rm -rf $(dirname $0)/${DAY_OF_WEEK}.sql
echo 'Made weekly backup...'

# find and delete files older than 7 days
find ${DESTINATION}/database/ -type f -mtime +7 -exec rm {} \;

Master

This goes in the backups/ folder. There’s one for files, and a second master script for databases. The separate scripts are again so that the cron can call them at different times.

#!/bin/bash
website/files.sh start
website/files.sh start
website/files.sh start