-
-
Save scriptsandthings/b799595136b3964dc594ad2adec28dc6 to your computer and use it in GitHub Desktop.
Apple Remote Desktop List creator from CSV
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
declare -x uuidgen="/usr/bin/uuidgen" | |
declare -x plistbuddy="/usr/libexec/PlistBuddy" | |
declare -x awk="/usr/bin/awk" | |
declare -x cat="/bin/cat" | |
declare -x cp="/bin/cp" | |
declare -x dscl="/usr/bin/dscl" | |
declare -x defaults="/usr/bin/defaults" | |
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" | |
declare -x serversetup="/System/Library/ServerSetup/serversetup" | |
declare -x plistbuddy="/usr/libexec/PlistBuddy" | |
# -- 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 vCud:f: SWITCH ; do | |
case $SWITCH in | |
v ) export LOGLEVEL="VERBOSE" ;; | |
C ) export ENABLECOLOR="YES" ;; | |
u ) export GUI="ENABLED" ;; | |
d ) export SAVE_DIRECTORY="$OPTARG" ;; | |
f ) export CSV_FILE="$OPTARG" ;; | |
esac | |
done # END getopts | |
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" | |
} | |
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*) \ | |
die ERROR "$FUNCNAME: Unsupported OS version: $OSVER." 192 ;; | |
10.4*) \ | |
statusMessage passed "CHECK_OS: OS check: $OSVER successful!"; | |
return 0;; | |
10.5*) \ | |
statusMessage passed "CHECK_OS: OS check: $OSVER successful!"; | |
return 0;; | |
10.6*) \ | |
die ERROR "$FUNCNAME:$LINENO Unsupported OS:$OSVER is too new." 192 ;; | |
*) \ | |
die ERROR "CHECK_OS:$LINENO Unsupported OS:$OSVER unknown error" 192 ;; | |
esac | |
return 1 | |
checkDNS(){ | |
declare SERVER_HOSTNAME="$1" SERVER_IP="$2" | |
statusMessage header "$SERVER_HOSTNAME ($SERVER_IP)" | |
if host "${SERVER_HOSTNAME:-null}" &>/dev/null ; then | |
statusMessage passed "FORWARD[A]:$SERVER_HOSTNAME ($SERVER_IP)" | |
else | |
statusMessage error "FORWARD[A]:$SERVER_HOSTNAME ($SERVER_IP)" | |
fi | |
if host "${SERVER_IP:-null}" &>/dev/null ; then | |
statusMessage passed "REVERSE[PTR]:$SERVER_HOSTNAME ($SERVER_IP)" | |
else | |
statusMessage error "REVERSE[PTR]:$SERVER_HOSTNAME ($SERVER_IP)" | |
fi | |
printf "\n" | |
} | |
} # END checkSystemVersion() | |
statusMessage verbose "Using file: $CSV_FILE" | |
checkLineEndings "$CSV_FILE" | |
declare -x PLIST="${SAVE_DIRECTORY:="."}/${CSV_FILE%%.csv}.plist" | |
$plistbuddy -c "Add :listName string ${CSV_FILE%%.csv}" "$PLIST" | |
$plistbuddy -c "Add :uuid string $($uuidgen)" "$PLIST" | |
OLDIFS="$IFS" | |
IFS=$'\n' | |
declare -ix N=0 | |
for LINE in `$cat "${CSV_FILE:?"Must specify a file with -f"}"` ; do | |
let LINE_NUM++ | |
if [ $LINE_NUM -eq 1 ] ; then | |
statusMessage progress "Skipping first line:$LINE" | |
continue | |
fi | |
# statusMessage verbose "processing $LINE" | |
declare -x SITE_ID="$(printf "$LINE" | $awk -F',' '{print $1;exit}')" | |
declare -x SERVER_ETHERNET[0]="$(printf "$LINE" | $awk -F',' '{print $12;exit}')" | |
declare -x SERVER_ETHERNET[1]="$(printf "$LINE" | $awk -F',' '{print $13;exit}')" | |
declare -x SERVER_HW_SERIAL="$(printf "$LINE" | $awk -F',' '{print substr($15,1,8);exit}')" | |
# AdminUser | |
declare -x ADMIN_USER_EXISTS="false" | |
declare -x ADMIN_USER_NAME="$(printf "$LINE" | $awk -F',' '{print $16;exit}')" | |
declare -x ADMIN_USER_PASSWORD="$(printf "$LINE" | $awk -F',' '{print $17;exit}')" | |
declare -x ADMIN_USER_REALNAME="$ADMIN_USER_NAME" | |
declare -ix ADMIN_USER_UID="501" | |
# HostName | |
declare -x HOST_NAME="$(printf "$LINE" | $awk -F',' '{print $4;exit}')" | |
statusMessage verbose "HOST_NAME: $HOST_NAME" | |
# Bonjour | |
declare -x BONJOUR_ENABLED="true" | |
declare -x BONJOUR_NAME="$(printf $HOST_NAME | $awk -F'.' '{print $1;exit}')" | |
# ComputerName | |
declare -x COMPUTER_NAME="$(printf $HOST_NAME | $awk -F'.' '{print $1;exit}')" | |
# DS | |
declare -x DS_TYPE="Standalone" | |
# DefaultGroupName | |
declare -x DEFAULT_GROUP_LONGNAME="Work Group" | |
declare -x DEFAULT_GROUP_SHORTNAME="workgroup" | |
# EnableARD | |
declare -x ENABLE_ARD="true" | |
# InstallLanguage | |
declare -x INSTALL_LAUNGUAGE="English" | |
# Keyboard | |
declare -x KEYBOARD_DEFAULT_FORMAT="0" | |
declare -x KEYBOARD_DEFAULT_SCRIPT="0" | |
declare -x KEYBOARD_RESNAME="U.S." | |
declare -ix KEYBOARD_SCRIPTID="0" | |
declare -ix KEYBOARD_KBRESID="0" | |
# NetworkInterfaces | |
declare -ax INTERFACE_ACTIVEAT[0]="false" | |
declare -ax INTERFACE_ACTIVETCPIP[0]="true" | |
declare -ax DNS_DOMAIN[0]="$(printf "$LINE" | $awk -F',' '{print $11;exit}')" | |
declare -ax DNS_SERVER_PRIMARY[0]="$(printf "$LINE" | $awk -F',' '{print $8;exit}')" | |
declare -ax DNS_SERVER_SECONDARY[0]="$(printf "$LINE" | $awk -F',' '{print $9;exit}')" | |
declare -ax DNS_SERVER_TERIARY[0]="$(printf "$LINE" | $awk -F',' '{print $10;exit}')" | |
declare -ax INTERFACE_DEVICENAME[0]="en0" | |
declare -ax ETHERNET_ADDRESS[0]="00:00:00:00:00:00" | |
declare -ax IPV6_TYPE[0]="3" | |
declare -ax PORT_NAME[0]="Ethernet 1" | |
declare -ax IP_ADDRESS[0]="$(printf "$LINE" | $awk -F',' '{print $5;exit}')" | |
declare -ax ROUTER[0]="$(printf "$LINE" | $awk -F',' '{print $7;exit}')" | |
declare -ax SUBNET_MASK[0]="$(printf "$LINE" | $awk -F',' '{print $6;exit}')" | |
declare -ax INTERFACE_TYPE[0]="Manual Configuration" | |
declare -ax INTERFACE_ACTIVEAT[1]="false" | |
declare -ax INTERFACE_ACTIVETCPIP[1]="false" | |
declare -ax INTERFACE_DEVICENAME[1]="en1" | |
declare -ax ETHERNET_ADDRESS[1]="00:00:00:00:00:00" | |
declare -ax IPV6_TYPE[1]="3" | |
declare -ax PORT_NAME[1]="Ethernet 2" | |
declare -ax IP_ADDRESS[1]="192.168.50.90" | |
declare -ax ROUTER[1]="0.0.0.0" | |
declare -ax SUBNET_MASK[1]="255.255.255.0" | |
declare -ax INTERFACE_TYPE[1]="Manual Configuration" | |
# PrimaryLanguage | |
declare -x PRIMARY_LANGUAGE="English" | |
# Serial Number | |
declare -x SERIAL_NUMBER="$(printf "$LINE" | $awk -F',' '{print $14;exit}')" | |
# Service NTP | |
declare -x HOST_NTP="false" | |
declare -x HOST_NTP_SERVER="$(printf "$LINE" | $awk -F',' '{print $21;exit}')" | |
declare -x USE_NTP="true" | |
# TimeZone | |
declare -x TIME_ZONE="$(printf "$LINE" | $awk -F',' '{print $20;exit}')" | |
# Version Number | |
declare -ix VERSION_NUMBER="3" | |
declare SERVER_MAC="$(printf "%s" "${SERVER_ETHERNET[0]}" | $awk 'BEGIN{FS=""}{print $1$2":"$3$4":"$5$6":"$7$8":"$9$10":"$11$12}')" | |
$plistbuddy -c "Add :items array" "$PLIST" | |
$plistbuddy -c "Add :items: dict" "$PLIST" | |
$plistbuddy -c "Add :items:$N::hardwareAddress string $SERVER_MAC" "$PLIST" | |
$plistbuddy -c "Add :items:$N::hostname string $HOST_NAME" "$PLIST" | |
$plistbuddy -c "Add :items:$N::name string $HOST_NAME" "$PLIST" | |
$plistbuddy -c "Add :items:$N::networkAddress string ${IP_ADDRESS[0]}" "$PLIST" | |
$plistbuddy -c "Add :items:$N::preferHostname bool false" "$PLIST" | |
let N++ | |
done | |
OLDIFS="$IFS" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment