Skip to content

Instantly share code, notes, and snippets.

@acidprime
Created January 9, 2012 01:23
Show Gist options
  • Save acidprime/1580427 to your computer and use it in GitHub Desktop.
Save acidprime/1580427 to your computer and use it in GitHub Desktop.
Ugly 10.6 Auto Server Setup Generator
#!/bin/bash
# Required commands
declare -x awk="/usr/bin/awk"
declare -x dscl="/usr/bin/dscl"
declare -x defaults="/usr/bin/defaults"
declare -x dscacheutil="/usr/bin/dscacheutil"
declare -x du="/usr/bin/du"
declare -x id="/usr/bin/id"
declare -x ntpdate="ntpdate"
declare -x scutil="/usr/sbin/scutil"
declare -x perl="/usr/bin/perl"
declare -x basename="/usr/bin/basename"
declare -x date="/bin/date"
declare -x defaults="/usr/bin/defaults"
declare -x dscl="/usr/bin/dscl"
declare -x find="/usr/bin/find"
declare -x groups="/usr/bin/groups"
declare -x ls="/bin/ls"
declare -x mv="/bin/mv"
declare -x rm="/bin/rm "
declare -x rmdir="/bin/rmdir"
declare -x sudo="/usr/bin/sudo"
# -- Runtime varibles
declare -x REQCMDS="$awk $dscl $deaults $ntpdate $perl $scutil"
declare -x SCRIPT="${0##*/}" ; SCRIPTNAME="${SCRIPT%%\.*}"
declare -x SCRIPTPATH="$0" RUNDIRECTORY="${0%/*}"
declare -x SYSTEMVERSION="/System/Library/CoreServices/SystemVersion.plist"
declare -x OSVER="$("$defaults" read "${SYSTEMVERSION%.plist}" ProductVersion )"
#declare -x CONFIGFILE="${RUNDIRECTORY:?}/${SCRIPTNAME}.conf"
declare -x BUILDVERSION="2009051"
#[ "$EUID" != 0 ] && printf "%s\n" "This script requires root access ($EUID)!" && exit 1
# -- Start the script log
# Set to "VERBOSE" for more logging prior to using -v
declare -x LOGLEVEL="NORMAL" SCRIPTLOG="/Library/Logs/${SCRIPT%%\.*}.log"
declare -i CURRENT_LOG_SIZE="$("$du" -hm "${SCRIPTLOG:?}" |
"$awk" '/^[0-9]/{print $1;exit}')"
if [ ${CURRENT_LOG_SIZE:=0} -gt 50 ] ; then
"$rm" "$SCRIPTLOG"
statusMessage "LOGSIZE:$CURRENT_LOG_SIZE, too large removing"
fi
exec 2>>"${SCRIPTLOG:?}" # Redirect standard error to log file
# Strip any extention from scriptname and log stderr to script log
if [ -n ${SCRIPTLOG:?"The script log has not been specified"} ] ; then
printf "%s\n" \
"STARTED:$SCRIPTNAME:EUID:$EUID:$("$date" +%H:%M:%S): Mac OS X $OSVER:BUILD:$BUILDVERSION" >>"${SCRIPTLOG:?}"
printf "%s\n" "Log file is: ${SCRIPTLOG:?}"
fi
statusMessage() { # Status message function with type and now color!
# Requires SCRIPTLOG STATUS_TYPE=1 STATUS_MESSAGE=2
declare date="${date:="/bin/date"}"
declare DATE="$("$date" -u "+%Y-%m-%d")"
declare STATUS_TYPE="$1" STATUS_MESSAGE="$2"
if [ "$ENABLECOLOR" = "YES" ] ; then
# Background Color
declare REDBG="41" WHITEBG="47" BLACKBG="40"
declare YELLOWBG="43" BLUEBG="44" GREENBG="42"
# Foreground Color
declare BLACKFG="30" WHITEFG="37" YELLOWFG="33"
declare BLUEFG="36" REDFG="31"
declare BOLD="1" NOTBOLD="0"
declare format='\033[%s;%s;%sm%s\033[0m\n'
# "Bold" "Background" "Forground" "Status message"
printf '\033[0m' # Clean up any previous color in the prompt
else
declare format='%s\n'
fi
# Function only seems to work on intel and higher.
showUIDialog(){
statusMessage header "FUNCTION: # $FUNCNAME" ; unset EXITVALUE TRY
"$killall" -HUP "System Events" 2>/dev/null
declare -x UIMESSAGE="$1"
"$osascript" <<EOF
try
with timeout of 0.1 seconds
tell application "System Events"
set UIMESSAGE to (system attribute "UIMESSAGE") as string
activate
display dialog UIMESSAGE with icon 2 giving up after "3600" buttons "Dismiss" default button "Dismiss"
end tell
end timeout
end try
EOF
return 0
} # END showUIDialog()
case "${STATUS_TYPE:?"Error status message with null type"}" in
progress) \
[ -n "$LOGLEVEL" ] &&
printf $format $NOTBOLD $WHITEBG $BLACKFG "PROGRESS:$STATUS_MESSAGE" ;
printf "%s\n" "$DATE:PROGRESS: $STATUS_MESSAGE" >> "${SCRIPTLOG:?}" ;;
# Used for general progress messages, always viewable
notice) \
printf "%s\n" "$DATE:NOTICE:$STATUS_MESSAGE" >> "${SCRIPTLOG:?}" ;
[ -n "$LOGLEVEL" ] &&
printf $format $NOTBOLD $YELLOWBG $BLACKFG "NOTICE :$STATUS_MESSAGE" ;;
# Notifications of non-fatal errors , always viewable
error) \
printf "%s\n\a" "$DATE:ERROR:$STATUS_MESSAGE" >> "${SCRIPTLOG:?}" ;
[ -n "$LOGLEVEL" ] &&
printf $format $NOTBOLD $REDBG $YELLOWFG "ERROR :$STATUS_MESSAGE" ;;
# Errors , always viewable
verbose) \
printf "%s\n" "$DATE:VERBOSE: $STATUS_MESSAGE" >> "${SCRIPTLOG:?}" ;
[ "$LOGLEVEL" = "VERBOSE" ] &&
printf $format $NOTBOLD $WHITEBG $BLACKFG "VERBOSE :$STATUS_MESSAGE" ;;
# All verbose output
header) \
[ "$LOGLEVEL" = "VERBOSE" ] &&
printf $format $NOTBOLD $BLUEBG $BLUEFG "VERBOSE :$STATUS_MESSAGE" ;
printf "%s\n" "$DATE:PROGRESS: $STATUS_MESSAGE" >> "${SCRIPTLOG:?}" ;;
# Function and section headers for the script
passed) \
[ "$LOGLEVEL" = "VERBOSE" ] &&
printf $format $NOTBOLD $GREENBG $BLACKFG "SANITY :$STATUS_MESSAGE" ;
printf "%s\n" "$DATE:SANITY: $STATUS_MESSAGE" >> "${SCRIPTLOG:?}" ;;
# Sanity checks and "good" information
graphical) \
[ "$GUI" = "ENABLED" ] &&
showUIDialog "$STATUS_MESSAGE" ;;
esac
return 0
} # END statusMessage()
die() { # die Function
statusMessage header "FUNCTION: # $FUNCNAME" ; unset EXITVALUE
declare LASTDIETYPE="$1" LAST_MESSAGE="$2" LASTEXIT="$3"
declare LASTDIETYPE="${LASTDIETYPE:="UNTYPED"}"
if [ ${LASTEXIT:="192"} -gt 0 ] ; then
statusMessage error "$LASTDIETYPE :$LAST_MESSAGE:EXIT:$LASTEXIT"
# Print specific error message in red
else
statusMessage verbose "$LASTDIETYPE :$LAST_MESSAGE:EXIT:$LASTEXIT"
# Print specific error message in white
fi
statusMessage verbose "COMPLETED:$SCRIPT IN $SECONDS SECONDS"
"$killall" "System Events"
exit "${LASTEXIT}" # Exit with last status or 192 if none.
return 1 # Should never get here
} # END die()
cleanUp() { # -- Clean up of our inportant sessions variables and functions.
statusMessage header "FUNCTION: # $FUNCNAME" ; unset EXITVALUE
statusMessage verbose "TIME: $SCRIPT ran in $SECONDS seconds"
unset -f ${!check*}
[ "${ENABLECOLOR:-"ENABLECOLOR"}" = "YES" ] && printf '\033[0m' # Clear Color
if [ "$PPID" == 1 ] ; then # LaunchD is always PID 1 in 10.4+
: # Future LaunchD code
fi
exec 2>&- # Reset the error redirects
return 0
} # END cleanUp()
# Check script options
statusMessage header "GETOPTS: Processing script $# options:$@"
# ABOVE: Check to see if we are running as a postflight script,the installer creates $SCRIPT_NAME
[ $# = 0 ] && statusMessage verbose "No options given"
# If we are not running postflight and no parameters given, print usage to stderr and exit status 1
while getopts vcd:f:t: SWITCH ; do
case $SWITCH in
v ) export LOGLEVEL="VERBOSE" ;;
d ) export SAVE_DIRECTORY="$OPTARG" ;;
c ) export ENABLECOLOR="YES" ;;
f ) export CSV_FILE="$OPTARG" ;;
t ) export TEMPLATE="$OPTARG" ;;
esac
done # END getopts
checkCommands() { # CHECK_CMDS Required Commands installed check using the REQCMDS varible.
declare -i FUNCSECONDS="$SECONDS" # Capture start time
statusMessage header "FUNCTION: # ${FUNCNAME}" ; unset EXITVALUE
declare REQCMDS="$1"
for RQCMD in ${REQCMDS:?} ; do
if [ -x "$RQCMD" ] ; then
statusMessage passed "PASSED: $RQCMD is executable"
else
# Export the command Name to the die status message can refernce it"
export RQCMD ; return 1
fi
done
return 0
declare -i FUNCTIME=$(( ${SECONDS:?} - ${FUNCSECONDS:?} ))
[ "${FUNCTIME:?}" != 0 ] &&
statusMessage verbose "TIME:$FUNCNAME:Took $FUNCTIME seconds to EXIT:$EXITVALUE"
} # END checkCommands()
checkSystemVersion() {
# CHECK_OS Read the /Sys*/Lib*/CoreSer*/S*Version.plist value for OS version
statusMessage header "FUNCTION: # ${FUNCNAME}" ; unset EXITVALUE
declare OSVER="$1"
case "${OSVER:?}" in
10.0* | 10.1* | 10.2* | 10.3* | 10.4*) \
die ERROR "$FUNCNAME: Unsupported OS version: $OSVER." 192 ;;
10.5*) \
statusMessage passed "CHECK_OS: OS check: $OSVER successful!";
return 0;;
10.6*) \
statusMessage passed "CHECK_OS: OS check: $OSVER successful!";
return 0;;
*) \
die ERROR "CHECK_OS:$LINENO Unsupported OS:$OSVER unknown error" 192 ;;
esac
return 1
} # END checkSystemVersion()
checkLineEndings(){
declare -i FUNCSECONDS="$SECONDS" # Capture start time
declare FILE_TO_CHECK="$1"
statusMessage header "FUNCTION: # ${FUNCNAME}" ; unset EXITVALUE
if [ -f "$FILE_TO_CHECK" ] ; then
if ! $perl -ne "exit 1 if m/\r\n/;" "$FILE_TO_CHECK" ; then
statusMessage notice \
"Incorrect line endings detected (probobly due to Mircosoft edit)"
statusMessage notice \
"Backup: $CSV_FILE.bak"
$cp -f "$FILE_TO_CHECK" "$FILE_TO_CHECK".bak
statusMessage verbose 'Resetting line endings \r/\n/ to \n'
$perl -i -pe 's/\r/\n/g' "$FILE_TO_CHECK"
elif ! $perl -ne "exit 1 if m/\r/;" "$FILE_TO_CHECK" ; then
statusMessage notice \
"Incorrect line endings detected (DOS?) fixing backup: $FILE_TO_CHECK.bak"
$cp -f "$FILE_TO_CHECK" "$FILE_TO_CHECK".bak
statusMessage verbose 'Resetting line endings \r/\n/'
$perl -i -pe 's/\r/\n/g' "$FILE_TO_CHECK"
fi
else
statusMessage error "File: $FILE_TO_CHECK does not exist"
die ERROR "Invalid file specified: $FILE_TO_CHECK"
fi
statusMessage verbose "TIME:$FUNCNAME:Took $FUNCTIME seconds to EXIT:$EXITVALUE"
}
checkSystemVersion "${OSVER}"
statusMessage verbose "Using file: $CSV_FILE"
checkLineEndings "$CSV_FILE"
OLDIFS="$IFS"
IFS=$'\n'
for LINE in `cat "$CSV_FILE"` ; do
let LINE_NUM++
if [ $LINE_NUM -eq 1 ] ; then
statusMessage progress "Skipping first line:$(echo "$LINE" | $awk '{print substr($0)}')"
continue
fi
export HW_SERIALNUMBER="$(printf "%s" "$LINE" |
$awk -F',' '{print $2}')"
export HW_MAC="$(printf "%s" "$LINE" |
$awk -F',' '{print $4}' | awk 'BEGIN{FS=""}{print $1$2":"$3$4":"$5$6":"$7$8":"$9$10":"$11$12}')"
export BONJOUR_NAME="$(printf "%s" "$LINE" |
$awk -F',' '{print $6}' |
$awk -F'.' '{print $1}')"
export COMPUTER_NAME="$(printf "%s" "$LINE" |
$awk -F',' '{print $6}' |
$awk -F'.' '{print $1}')"
export MY_HOST_NAME="$(printf "%s" "$LINE" |
$awk -F',' '{print $6}')"
export REGISTERED_TO="$(printf "%s" "$LINE" |
$awk -F',' '{print $21}')"
export SW_SERIAL="$(printf "%s" "$LINE" |
$awk -F',' '{print $5}')"
export IP_ADDRESS="$(printf "%s" "$LINE" |
$awk -F',' '{print $7}')"
export ROUTER="$(printf "%s" "$LINE" |
$awk -F',' '{print $9}')"
if [ ${MY_HOST_NAME:-null} = "null" ] ; then
continue
fi
statusMessage header "Processing: $MY_HOST_NAME"
if [ -f "$TEMPLATE" ] ; then
# HW_SERIALNUMBER
if [ "${#HW_SERIALNUMBER}" -gt 0 ] ; then
cat "$TEMPLATE" |
awk '{gsub(/__HW_SERIALNUMBER__/,ENVIRON["HW_SERIALNUMBER"],$0);print}' >"$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist"
else
statusMessage error "HW_SERIALNUMBER is null for $MY_HOST_NAME"
exit 1
fi
mv "$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist" "$SAVE_DIRECTORY/$MY_HOST_NAME.plist"
# HW_MAC
if [ "${#HW_MAC}" -gt 0 ] ; then
cat "$SAVE_DIRECTORY/$MY_HOST_NAME.plist" |
awk '{gsub(/__HW_MAC__/,ENVIRON["HW_MAC"],$0);print}' >"$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist"
else
statusMessage error "HW_MAC is null for $MY_HOST_NAME"
exit 1
fi
mv "$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist" "$SAVE_DIRECTORY/$MY_HOST_NAME.plist"
# BONJOUR_NAME
if [ "${#BONJOUR_NAME}" -gt 0 ] ; then
cat "$SAVE_DIRECTORY/$MY_HOST_NAME.plist" |
awk '{gsub(/__BONJOUR_NAME__/,ENVIRON["BONJOUR_NAME"],$0);print}' >"$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist"
else
statusMessage error "BONJOUR_NAME is null for $MY_HOST_NAME"
exit 1
fi
mv "$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist" "$SAVE_DIRECTORY/$MY_HOST_NAME.plist"
# COMPUTER_NAME
if [ "${#COMPUTER_NAME}" -gt 0 ] ; then
cat "$SAVE_DIRECTORY/$MY_HOST_NAME.plist" |
awk '{gsub(/__COMPUTER_NAME__/,ENVIRON["COMPUTER_NAME"],$0);print}' >"$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist"
else
statusMessage error "COMPUTER_NAME is null for $MY_HOST_NAME"
exit 1
fi
mv "$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist" "$SAVE_DIRECTORY/$MY_HOST_NAME.plist"
# MY_HOST_NAME
if [ "${#MY_HOST_NAME}" -gt 0 ] ; then
cat "$SAVE_DIRECTORY/$MY_HOST_NAME.plist" |
awk '{gsub(/__MY_HOST_NAME__/,ENVIRON["MY_HOST_NAME"],$0);print}' >"$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist"
else
statusMessage error "MY_HOST_NAME is null for $MY_HOST_NAME"
exit 1
fi
mv "$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist" "$SAVE_DIRECTORY/$MY_HOST_NAME.plist"
# REGISTERED_TO
if [ "${#REGISTERED_TO}" -gt 0 ] ; then
cat "$SAVE_DIRECTORY/$MY_HOST_NAME.plist" |
awk '{gsub(/__REGISTERED_TO__/,ENVIRON["REGISTERED_TO"],$0);print}' >"$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist"
else
statusMessage error "REGISTERED_TO is null for $MY_HOST_NAME"
exit 1
fi
mv "$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist" "$SAVE_DIRECTORY/$MY_HOST_NAME.plist"
# SW_SERIAL
if [ "${#SW_SERIAL}" -gt 0 ] ; then
cat "$SAVE_DIRECTORY/$MY_HOST_NAME.plist" |
awk '{gsub(/__SW_SERIAL__/,ENVIRON["SW_SERIAL"],$0);print}' >"$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist"
else
statusMessage error "SW_SERIAL is null for $MY_HOST_NAME"
exit 1
fi
mv "$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist" "$SAVE_DIRECTORY/$MY_HOST_NAME.plist"
# IP_ADDRESS
if [ "${#IP_ADDRESS}" -gt 0 ] ; then
cat "$SAVE_DIRECTORY/$MY_HOST_NAME.plist" |
awk '{gsub(/__IP_ADDRESS__/,ENVIRON["IP_ADDRESS"],$0);print}' >"$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist"
else
statusMessage error "IP_ADDRESS is null for $MY_HOST_NAME"
exit 1
fi
mv "$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist" "$SAVE_DIRECTORY/$MY_HOST_NAME.plist"
# ROUTER
if [ "${#ROUTER}" -gt 0 ] ; then
cat "$SAVE_DIRECTORY/$MY_HOST_NAME.plist" |
awk '{gsub(/__ROUTER__/,ENVIRON["ROUTER"],$0);print}' >"$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist"
else
statusMessage error "ROUTER is null for $MY_HOST_NAME"
exit 1
fi
mv "$SAVE_DIRECTORY/$MY_HOST_NAME-edit.plist" "$SAVE_DIRECTORY/$MY_HOST_NAME.plist"
else
statusMessage error "Template file not found:$TEMPLATE"
fi
if plutil "$SAVE_DIRECTORY/$MY_HOST_NAME.plist" ; then
statusMessage passed "Plist Passed Consistancy Check"
else
statusMessage error "Plist FAILED consistancy check"
fi
done
OLDIFS="$IFS"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment