There are many hints that involve the use of the defaults command to change system settings. When trying to keep my Macs in sync (as well as setting up new ones), I have difficulty remembering which changes I've made. So after some work I was able to build a script that nicely tracks the changes I make to the system.
My requirements were to log any writes or deletes, showing both the old value and the new value to a log file in ~/Library/Logs/ where it is accessible to Console. (I use logger too but those messages get lost in the noise and are aged off). I wanted to leave any other defaults command (read, find, etc.) alone.
My first try was to write a function in my .bash_profile, which is loaded at every login and overrode the executable. That seemed fine until I realized that when using sudo defaults, it wasn't working. This is because sudo simply executes a command as different user without logging in and getting the benefit of profiles. It changes certain environment variables and drops all functions and aliases. So the most important changes of all were missed.
My solution was to create a script and place it in the path prior to /usr/bin/defaults. Thus when sudo calls the command without profiles, it runs the script instead of the binary (you could also do this with a link if the path is a problem).
I export a variable with the path to log file and define a log function that includes the date/time in my .bashrc so it's available to every bash shell invoked (login or not) under my username. You can easily just put these lines in the script itself, but it turns out to be convenient to be able to log anything at the terminal with the function, so I define it in ~/.bashrc:
export lf=${HOME}/Library/Logs/com.yyyy.log
function log() { echo "$(date "+%Y-%m-%d %H:%M:%S") bash $@" >> ${lf}; }
#!/bin/bash
# Defaults - a script to record important changes to the system
source ${HOME}/.bashrc
if [[ ! ${1} ]]; then
echo "This is the script version of defaults. Run /usr/bin/defaults to see help"
exit 1
fi
if [[ (${1} == write) || (${1} == delete) ]]; then
op=${1}; dom=${2}; key=${3}; shift; shift; shift; args="${@}"
[[ (${op} == write) && ("${args}" == "") ]] && args='""'
log "${USER} executed defaults ${op} ${dom} ${key} ${args}"
logger "${USER} executed defaults ${op} ${dom} ${key} ${args}"
log "existing value: \"$(/usr/bin/defaults read ${dom} ${key})\""
logger "existing value: \"$(/usr/bin/defaults read ${dom} ${key})\""
/usr/bin/defaults ${op} ${dom} ${key} ${args}
log "new value: \"$(/usr/bin/defaults read ${dom} ${key})\""
logger "new value: \"$(/usr/bin/defaults read ${dom} ${key})\""
else
/usr/bin/defaults $@
fi
Mac OS X Hints
http://hints.macworld.com/article.php?story=20110629184729634