Jaime Gago Condensing Information Systems From the Vapor Of Data

29Jan/102

Automating Os X Server Backups Without 3rd Party Software

There are plenty of different options to backup Os X Server, including free tools like the excellent Mike Bombich’s Carbon Copy Cloner and Open Source ones like lbackup or amanda. Michael Dhaliwal has a pretty good paper that he updates and publishes on his company (i.e. district13 computing) website.

For various reasons not worth listing here I decided to come with my own design while relying exclusively on built in tools (e.g. launchd). I thought this might help other OS X Server Admins so here it is.

Disclaimer: If you plan to use this post as a reference, please keep in mind this backup setup is very particular to its environment and probably won’t work as it is in yours.

First of all it is important to mention this server is limited to LAN access during business hours which means it can be down at night.
One of the caveats of Server backup is databases with opened files, because as previously mentioned I can take the server down at night it makes it much more simpler.
Ok enough with the warnings let’s start.

Overview
The following process happens automatically on a scheduled time:
-reboots the server from a second startup disk
-create a compressed image of the main OS disk
-reboots back to the main OS disk

Technologies concerned:
-Launchd
-Property list files
-bless
-hdiutil
-Shell scripting
-AppleScript

Preparation
-A second bootable Os X disk available to the server that is going to be backed up.
For this I use a firewire external drive from OWC (they have nice rack ones) and apple software restore. I decided to clone the main server so I was sure I wouldn’t go into any hardware incompatibilities.

-2 slightly different plists files, I edited with VI and TextWrangler.
-2 Shell Scripts, again VI and TextWrangler

Step 1: Reboot *once* to the second Os X disk

a) Write a script to do this, save it to /PATH/TO/YOUR/FILE while understanding this will be run as root via launchd...

Mine is pretty basic, I test if the server is at the login window and reboot, if not I try to nicely quit every application before restarting. While doing this “nice quit try”,  to make sure the script doesn’t commit suicide I had its name (i.e. blessme) to the whitelist. If you copy this script make sure either to name it blessme or to edit it so it matches the name you’ve chosen.

Here it is

#!/bin/bash
#
#Combination of AppleScript + Shell and Apple Tools
#to restart the computer on external hard drive
#for one next reboot only
#
#Convenience variables
external="name_of_the_second_bootable_disk"
#the diskid can be found using disk utility/info
diskid="diskXsX"
#
#Login Window?
if ! killall -d "Finder" &>/dev/null ;then
diskutil Mount $diskid
bless -mount /Volumes/$external -setboot -nextonly
shutdown -r now
fi
#
#User Logged In try nice quit applications without saving
osascript<<APPLESCRIPT &>/dev/null
tell application "System Events" to set the visible of every process to true
set white_list to {"Finder", "blessme"}
tell application "Finder"
        set process_list to the name of every process whose visible is true
    end tell
    repeat with i from 1 to (number of items in process_list)
        set this_process to item i of the process_list
        if this_process is not in white_list then
            tell application this_process
                quit without saving
            end tell
        end if
    end repeat
APPLESCRIPT
bless -mount /Volumes/$external -setboot -nextonly
osascript -e 'tell application "Finder" to restart'
exit 0

b) Write a plists to start the shell script at decided time (i.e 2 AM, 5th).

This one is pretty straight forward since you have to respect Apple standards for property lists.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<false/>
<key>Label</key>
<string>org.yourorganisation.backupday5</string>
<key>ProgramArguments</key>
<array>
<string>/PATH/TO/YOUR/SCRIPT</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Day</key>
<integer>5</integer>
<key>Hour</key>
<integer>02</integer>
<key>Minute</key>
<integer>00</integer>
</dict>
<key>UserName</key>
<string>root</string>
</dict>
</plist>

c)Place the plist in /Library/LaunchDaemons on the server to backup while making sure the plist has the right POSIX permissions, owner and group (i.e. 644, root, wheel), otherwise it’ll fail.

Step 2 : Backing Up (while booted on the second Os X disk) and reboot

a)Write a script to do this, place it in /PATH/TO/YOUR/SCRIPT2.

If everything goes according to the plan at execution time the system is fresh rebooted and on the login window (unless you have enabled automatic login). I use hdiutil to create a compressed image of the main server.

Here is my script

#!/bin/bash
#Apple imaging on second drive
#designed to work at the loginwindow of a rebooted system
#
#If the destination path is not on the booted partition you need to mount it
#first, unless automatic login is enabled
#diskutil Mount Your_diskID
#
hdiutil create -format UDZO -srcfolder /Volumes/MAIN_SERVER /Volumes/BACKUP_VOLUME/day5.dmg
shutdown -r now

b)Write a plists to start the shell script at decided time. In my setup I gave a generous 10 minutes window to allow the rebooting from the second disk process. Thus It’s the same plist as in the first step except for the minutes parameters and the path to the script executed

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<false/>
<key>Label</key>
<string>org.yourorganisation.hdiutilbackupday5</string>
<key>ProgramArguments</key>
<array>
<string>/PATH/TO/YOUR/SCRIPT2</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Day</key>
<integer>5</integer>
<key>Hour</key>
<integer>02</integer>
<key>Minute</key>
<integer>10</integer>
</dict>
<key>UserName</key>
<string>root</string>
</dict>
</plist>

c)Place the plist in /Library/LaunchDaemons *on the second os disk* (the one we have booted to using the bless command) while making sure the plist has the right POSIX permissions, owner and group (i.e. 644, root, wheel), otherwise it’ll fail.

At this point this will create an image of the main server the 5th of every month starting at 2:10 AM and then reboot to the original disk, to have it work on the 15th and the 25th it needs 4 extra plists and 2 more scripts (to change paths of the the backup images otherwise it will overwrite which is not what I want). But if you have read through all of this you should be able to figure it out, if not just use the comments.

Here are few things to watch out during implementation
-Understand the security component of running scripts as root
-plists placed in /Library/LaunchDaemons must be owned by root, group wheel and with 644 permissions otherwise launchd won't be happy
-Make sure the scripts are executable
-The backups needs to be scanned (using asr) in order to be restored, this is an easy process to automate using the same technics (i.e. launchd, shellscripts, asr)
-ntp
-Check log files...

Filed under: Server Leave a comment
Comments (2) Trackbacks (1)
  1. I haven’t tested my backup with this Backup Bouncer but because it is basically an Apple Image the kind I use to restore a computer every day it should pass 100%.

    http://www.n8gray.org/blog/category/projects/backup-bouncer/

  2. I forgot to reference this excellent article on the topic by Mike Bombich

    http://www.bombich.com/mactips/image.html

    Also something I didn’t mention for those who are not familiar with launchd, you have to “activate” the plists in charge of starting scripts either by rebooting or using launchctl.


Leave a comment