I put together this script for my own use, and thought others here might find it useful:
Of course you'll need to change the SRC_USER and DEST_DMG variables to hold values that make sense for your system. A little creative editing can very easily change this script to backup any directory to a compressed disk image.
I made it owned by "root.system" (chown root.system FILENAME) and set its permissions to "-rwxr-x---" (chmod u+rwx FILENAME; chmod go-rwx FILENAME; chmod g+rx FILENAME). I also added it to my system crontab (Cronnix makes this simple) so that it runs automatically every Saturday morning at 4:00AM ("0 4 * * 6 root FILENAME").
Be careful to limit ownership and write access if you have it run from the system crontab, as it will run with root (!) permissions (necessary in my case since some of my application's preferences cannot be read with a regular user account, for security reasons). If you don't have these issues, you can run it from your regular user crontab and skip the chown (and possibly chmod) steps. My backup disk image fits on a DVD (barely...) so I back it up to DVD every Saturday as well.
Let me know if my comments are unclear (or if I made any typos).
Code:
#!/bin/tcsh -f
#
# ABOVE: The "!/bin/tcsh -f" line tells the shell to run this with
# the tcsh shell interpreter, and the "-f" parameter tells tcsh to
# ignore the user's "~/.tcshrc" file (so as to start faster). This MUST be
# the first line in the shell script file!
#
#
# Backup_Daryl_To_Storage_DMG (tcsh script)
# version 1.0.1 (2004-10-15)
#
#
# Embedded copy of /Users/daryl/Scripts/setdatetime.
#
#
# These two lines use the "mktemp" command to create two temporary
# files (usually in /tmp) named "setdatetime-date.XXXXXXXXXX" and
# "setdatetime-time.XXXXXXXXXX" ("mktemp" replaces the "X" characters
# with a unique set of semi-random characters). The back-quote characters
# "`" tell the shell to execute the enclosed commands; the "|| exit 1"
# clauses at the end tell the shell to exit with error code 1 if either
# "mktemp" fails; the assignment statements at the beginning puts the
# return value of the "mktemp" commands (which is the pathname of the
# created temp file) into the specified local variables.
#
set TEMP_DATE = `mktemp -t setdatetime-date.XXXXXXXXXX` || exit 1
set TEMP_TIME = `mktemp -t setdatetime-time.XXXXXXXXXX` || exit 1
#
# These two lines call the "date" command with the single-quoted format
# strings (the characters following the '%' characters tell the "date"
# command to insert date/time information here. Everything within the
# single-quote characters following the "date" command comprises the
# format string; the '+' character tells the "date" command that the
# following characters comprise a user-defined format string. Type
# "man date" from a Terminal window for more information...
# The section at the end of each line after the '>' character tells the
# shell to send the output of the preceeding command into the following
# file, here represented by the local variables (the '$' character tells
# the shell to insert the variable's value here).
# The purpose is to essentially create two files containing shell scripts
# which will create (global) shell environment variables holding the
# current date and time. For example, if run now these temp files might
# contain the following text: "setenv DATE 2004-10-19" and "10:16:59".
#
date '+setenv DATE %Y-%m-%d' > $TEMP_DATE
date '+setenv TIME %H:%M:%S' > $TEMP_TIME
#
# These two sets of commands execute the scripts in the temp files
# (the source command tells the shell to execute the script in THIS
# shells environment, so any variable assignments are seen by THIS
# shell too) and then remote (delete) the temp files.
#
source $TEMP_DATE ; rm $TEMP_DATE
source $TEMP_TIME ; rm $TEMP_TIME
#
# Script code to create the DMG file from user home directory.
#
#
# These four lines create another four local variables with the specified
# values. Again the '$' characters tell the shell that it should substitute
# the value of the following variable. The '{' and '}' are usually optional;
# they can be used to bracket a variable name make it easier for the
# shell to tell it from adjacent text (basically it makes it 100% clear
# to the shell where the variable name begins and ends).
#
# Replace "daryl" in $SRC_USER with your user name; this is used in
# $SRC_DIR and is used as the disk image volume name.
#
# You can change $SRC_DIR to whatever directory/folder you wish to have
# backed up.
#
# You can change DEST_DMG to whatever DMG file you want to have created.
# Mine is on my "Storage" volume, in its "-Backup" directory, named (for
# example, if run today) "2004-10-19 daryl.dmg".
#
# $DEST_OUT is the file to hold the status output from the hdiutil program.
# This is generally CRC values, elapsed time, output file size, compression
# ratio, etc.). It is named the same as $DEST_DMG but with ".out" appended
# to it ("2004-10-19 daryl.dmg.out" using my example name above).
#
set SRC_USER = "daryl"
set SRC_DIR = "/Users/${SRC_USER}"
set DEST_DMG = "/Volumes/Storage/-Backup/${DATE} ${SRC_USER}.dmg"
set DEST_OUT = "${DEST_DMG}.out"
#
# The first "if-then" line tells the shell to only execute the following
# lines (every line until "else") ONLY if the statement between "if" and
# "then" is true. This particular statement would read, in English, as
# "if (the file whose name is in the DEST_DMG variable does NOT exist) then".
# The "-e" is a test for file existence, and the "== 0" works like a "NOT"
# modifier, because we don't want the following command to overwrite an
# existing file with the same name.
#
# The second "sudo hdiutil..." line is a command to execute the hdiutil
# program (with super-user permissions) using the parameters that follow
# it on the line (type "man hdiutil" for more details). Basically, in
# English, this line would read something like "with super-user permissions,
# use the "hdiutil" application to create a disk image from the source
# folder in $SRC_DIR with an HFS+ filesystem using the UDZO format (UDIF
# zlib-compressed image) with maximum compression (the "-imagekey
# zlib-level=9" part) with a disk image volume name of $SRC_USER into the
# output file named $DEST_DMG with all of the command's output status
# messages redirected to the file $DEST_OUT (where the shell replaces all
# variables preceeded by a '$' with their respective values, of course).
# The sudo command is not needed if this script is run as root (i.e. in
# the system crontab file as I mention below), but may be needed if you run
# it manually from your regular user account, since some files in your
# user Library directory may not be normally readable (this is true of some
# disk utilities, for instance).
#
# The third "else" line marks the end of the "if" command lines and the
# start of the "else" command lines, which are executed only if the
# $DEST_DMG file DOES exist.
#
# The fourth "echo..." line outputs its status message indicating that
# the $DEST_DMG file already exists and so this script is aborting without
# creating a new disk image.
#
# The fifth (and final) "endif" line marks the end of the "else" command
# lines and the end of the entire if-then-else block.
#
#
if ((-e "${DEST_DMG}") == 0) then
sudo hdiutil create -srcfolder $SRC_DIR -fs HFS+ -format UDZO -imagekey zlib-level=9 -volname $SRC_USER "$DEST_DMG" >&! "$DEST_OUT"
else
echo "Output file '${DEST_DMG}' already exists; aborting."
endif
Of course you'll need to change the SRC_USER and DEST_DMG variables to hold values that make sense for your system. A little creative editing can very easily change this script to backup any directory to a compressed disk image.
I made it owned by "root.system" (chown root.system FILENAME) and set its permissions to "-rwxr-x---" (chmod u+rwx FILENAME; chmod go-rwx FILENAME; chmod g+rx FILENAME). I also added it to my system crontab (Cronnix makes this simple) so that it runs automatically every Saturday morning at 4:00AM ("0 4 * * 6 root FILENAME").
Be careful to limit ownership and write access if you have it run from the system crontab, as it will run with root (!) permissions (necessary in my case since some of my application's preferences cannot be read with a regular user account, for security reasons). If you don't have these issues, you can run it from your regular user crontab and skip the chown (and possibly chmod) steps. My backup disk image fits on a DVD (barely...) so I back it up to DVD every Saturday as well.
Let me know if my comments are unclear (or if I made any typos).