Reset network interfaces via networksetup command

jhalvorson
Valued Contributor

We've had an on going issue with factory fresh Macs that are netbooted, Casper imaged with a thin configuration, and not having a working network connection after the first reboot. All of the apps and settings are installed perfectly. But without the working network connection, many systems being deployed to the end user that are not bound to the domain, which then leads to calls to the Help Desk.

At first, we thought it was because the Mac wasn't obtaining a IP address quick enough post boot. But it appears that it's more likely that with the full screen jamfhelper and/or the temp account that is used to login At Reboot, the Network panel isn't adding the removable network adapter.

I was going to create a first boot script that checked for a working network connection or halted until the tech ensured the thunderbolt or usb ethernet adapter was detected and had a valid IP address. Instead, I came up with the following script that appears to work and covers if the laptop arrives with either type of removable network adapter. I also think it retains the model specific service orders. The script is the first script to run after reboot.

(Casper versions 7.x ~ 9.21, OS X 10.6 ~ 10.9.0)

#!/bin/sh

##########################################################################################
# Create time date stamped log
##########################################################################################
logFile="/private/var/log/OurCompany.log"

log () {
    /bin/echo $1
    /bin/echo $(date "+%Y-%m-%d %H:%M:%S: ") $1 >> $logFile 
}

log "-----"
log "Begin script 100_resetNetworkLocationAndPorts.sh"
log "Adjust Network Locations to correctly add network ports"
sleep 5

##########################################################################################
# Create a temporarily Network location and recreate the Automatic location.
##########################################################################################
networksetup -createlocation TempLoc populate
sleep 5

networksetup -switchtolocation TempLoc
sleep 2

networksetup -deletelocation Automatic
sleep 2

networksetup -createlocation Automatic populate
sleep 5

networksetup -switchtolocation Automatic
sleep 5

networksetup -deletelocation TempLoc

log “Network Location Setup Completed.”

exit 0

Is there a better way to ensure the network interfaces are set properly for each Mac model and variations of network interfaces?

22 REPLIES 22

mm2270
Legendary Contributor III

Is this not resolved by deleting the contents of the /Library/Preferences/SystemConfiguration/ directory? That folder stores network interface information in the plist files. From what I've seen, just deleting that stuff on your base image usually fixes this kind of stuff, because when the Mac first boots up it recreates all that based on the model its booting and the available interfaces.

If you haven't already tried that, you may want to give it a try. It might be all that's needed.

bajones
Contributor II

In my experience, deleting /Library/Preferences/SystemConfiguration/ accomplishes this task just fine but you also lose your computer name in the process. Not a huge deal but it might interfere with your binding process.

jhalvorson
Valued Contributor

I'll give that a try, but these are factory fresh Macs that have never been booted from the internal Hard Drive. We are unboxing, netbooting to a like version of OS, then using Casper Imaging without erasing the hard drive to install packages and a couple of At Reboot scripts. I would assume that the existing /Library/Preferences/SystemConfiguration would have the known built-in interfaces, but not necessarily have both USB and Thunderbolt interfaces added.

What I have observed is that the "populate" argument within the command "networksetup -createlocation Automatic populate" acts exactly as if a admin user click on the agreement to add a new USB Ethernet port in the GUI; it adds it and enables it.

laurendc
New Contributor

@jhalvorson][/url][/url][/url][/url][/url][/url I'm currently working on a similar solution for our builds. Thank you for sharing this. I am going to play with your script to see if it can work for us.

@bajones][/url][/url][/url][/url][/url][/url to follow up with this - we had to address a similar issue since we are currently deleting the contents of /Library/Preferences/SystemConfiguration/ at reboot since killing it on our base isn't an option for us. Just sharing what I did to remove the conflict with our bind process was run the following tasks as a part of our First Run Scripts:

-remove the appropriate plist file located in /Library/Preferences/SystemConfiguration/
-run networksetup -detectnewhardware -run our bind script
-set hostname from dsconfigad contents

Works OK.

Back to the topic: However, currently running networksetup -detectnewhardware only works with interfaces that are currently active while imaging. Not thrilled with it. So if a tech uses Thunderbolt for imaging, the USB interface on our Airs does not appear. So the timing of this post is great.

ifbell
Contributor

Here is part of a script we are using to detect new hardware and populate two different locations. The grep X.X is the first two octets of your network.



#!/bin/bash

IFS="
"

for i in `networksetup -listallnetworkservices | grep Ethernet | grep -v ^*`; do result=networksetup -getinfo "$i" | grep IP address | grep X.X if [ ! -z "$result" ]; then networksetup -createlocation Home populate networksetup -createlocation Work networksetup -switchtolocation Work networksetup -createnetworkservice "$i" "networksetup -listallhardwareports | grep -A1 "$i" | grep Device | awk '{print $2}'"


I hope this will be of help.

franton
Valued Contributor III

I think this has been answered in other posts, namely https://jamfnation.jamfsoftware.com/discussion.html?id=3422

Here's the relevant section of our first run script, which may help:

# Set up the variables we need for future changes

MacModel=$( ioreg -l | awk '/product-name/ { split($0, line, """); printf("%s
", line[4]); }' )
PrefModel=$( defaults read /Library/Preferences/SystemConfiguration/preferences.plist Model )

# Fix the incorrect model name in /Library/Preferences/SystemConfiguration/preferences.plist
# Also make sure the .plist is in the correct format

if [[ "$PrefModel" != "$MacModel" ]];
then
  /bin/echo $AdminPW | sudo -S defaults write /Library/Preferences/SystemConfiguration/preferences.plist Model $MacModel
  /bin/echo $AdminPW | sudo -S plutil -convert xml1 /Library/Preferences/SystemConfiguration/preferences.plist
fi

# Fix the incorrect network service names
# Script lovingly stolen from https://jamfnation.jamfsoftware.com/discussion.html?id=3422

# Detect new network hardware
networksetup -detectnewhardware

# List all network services and read one by one
networksetup -listallnetworkservices | tail -n +2 | while read service
do

# Remove asterisk from string for renaming disabled services
    service=${service#**}

# Use filter to select next line which has the hardware port defined
    filter=false

# Display network services
    networksetup -listnetworkserviceorder | while read serviceorder
    do
        if [[ ${filter} == true ]]
        then
            # Grab hardware port
            hardwareport=`echo ${serviceorder} | sed -e 's/(Hardware Port: //;s/, Device:.*//'`

            # Check if service name if different
            if [[ ${service} != ${hardwareport} ]]
            then
                # Rename the network service
                networksetup -renamenetworkservice "${service}" "${hardwareport}"
                echo -e "Renamed network service "${service}" to "${hardwareport}""
            fi
        fi

        if [[ ${serviceorder} == *${service} ]]
        then        
            # Got the line with the service. Set the filter to true to grab the next line which contains the hardware port
            filter=true
            else
            filter=false
        fi
    done
done

laurendc
New Contributor

@franton nice, thanks for sharing! Just to confirm - the plist files you're working with are the ones that you kept on your base OS, correct?

franton
Valued Contributor III

We use this as part of a script we run over the top of the loginwindow on first boot. The base OS I now generate from the InstallESD via autodmg.

mostlikelee
Contributor

Any suggestions on how to assign network services to interfaces that don't currently exist (ie. usb ethernet)? I'm trying to preconfigure proxy settings for all possible network interfaces (Display Ethernet, USB Ethernet, Thunderbolt Ethernet, etc...) without having them all connecting during imaging time. Right now I'm looking at modifying /Library/Preferences/SystemConfiguration/com.apple.NetworkInterfaces with Plistbuddy. It looks like each model of machines reserve interfaces consistently MacBook Air (en0 = Wifi, en1=USB Ethernet)

bentoms
Release Candidate Programs Tester

@timkalee.. Where are you trying to set these?

We use the following post imaging & it sets all interfaces proxy URL (for our PAC File). http://macmule.com/2011/09/09/how-to-change-the-automatic-proxy-configuration-url-in-system-preferen...

drheiner
New Contributor III

I have a workaround that I posted up a while ago for Casper 8.7x in which Casper was not keeping the computer name, This was due to a number of things however I found the network adapters not being refreshed correctly as one of the main issues. I made a new version to refresh these adapters as I am using a another script to turn on and off the Airport when an ethernet device is found. This works for our environment so no way a 100% answer to the question however this may help.

Please decompile this .pkg first to ensure everything looks fine. This works on the new Macbook Pro's and MacBook Airs. 1. Download this Package: http://home.comcast.net/~nw_systems/Has_OSX_10.9_Workstation_Network-Adapters_Refresh.pkg

  1. Place this in your task sequence right after your base image has been copied over (Before the first reboot)

Test! I found the Thunderbolt Bridge was tripping me up the most

mostlikelee
Contributor

@bentoms @drheiner
Thanks for the links. At image time we're able to at proxy configs to any active interfaces. If/when the user plugs into USB Ethernet or Thunderbolt Display Ethernet, the proxy settings are not there. I was hoping to somehow create those interfaces at image time before the proxy config script runs. I might just need to have a cached script to run at network change.

blackholemac
Valued Contributor III

@franton][/url][/url

I took your script listed above, added a shebang line to it, created a payload free installer package with it as a post install script. Uploaded the package to Casper Admin. Set it the package to "install of boot drive after imaging". Set the package with a priority of 2.

The base image was created using Mac OS X 10.9.2 AutoDMG straight vanilla with no updates or anything applied. Uploaded that to Casper Admin. Created a Configuration that includes the Base OS, two local accounts we create on every machine (I declared those in Casper Admin), the package I created with your script, and a simple script that has the command 'software update -i -a' in it. Every time I image that configuration to a test Mac Pro (2013 model) I have, we end up hanging in jamfhelper. Force quit jamfhelper only to see Bluetooth PAN discovered and my software update -i -a command never seems to run even if I accept the addition of the adapter from the GUI by force quitting jamfhelper!!

I have been trying for days to figure out how to not have 'Bluetooth PAN adapter detected' come up using different base OS creation techniques to no win. Saw your script and that it seemed to work for you and others. For whatever reason it's not working here.

What advice can you give on workflows, scripting syntax, etc to make this work?

I'm with you, I'd rather use a vanilla AutoDMG image with no accounts personally, but can't seem to make a go of it despite my best efforts. There is one way I know I can make a go of this using AutoDMG, but it seems like a painful method. I could just capture the /Library/Preferences/SystemConfiguration/preferences.plist and /Library/Preferences/SystemConfiguration/NetworkInterfaces.plist on each hardware model that we use, but honestly that method makes me want to groan as I would have to maintain separate configurations by hardware model.

@drheiner][/url][/url seemed to have a good idea but when it looked at the postinstall script in his package (as posted below), I noted that my AutoDMG vanilla base image doesn't even have a /Library/Preferences/SystemConfiguration/preferences.plist file at all so I wonder why (or how) to delete keys from a file that isn't there or why I would want to remove the two files at the end (they aren't on the base OS either).

#!/bin/sh
# Has_OSX_10.9_Workstation_Network-Adapters_Refresh
# Daniel Rheiner
# Should have priority 2 after Base Image
# Version 1
# OS X 10.9

pathToScript=$0
pathToPackage=$1
targetLocation=$2
targetVolume=$3

defaults delete "$2/Library/Preferences/SystemConfiguration/preferences" NetworkServices
defaults delete "$2/Library/Preferences/SystemConfiguration/preferences" CurrentSet
defaults delete "$2/Library/Preferences/SystemConfiguration/preferences" Sets
defaults delete "$2/Library/Preferences/SystemConfiguration/preferences" Model
defaults delete "$2/Library/Preferences/SystemConfiguration/preferences" Interface
defaults delete "$2/Library/Preferences/SystemConfiguration/preferences" VirtualNetworkInterfaces
defaults delete "$2/Library/Preferences/SystemConfiguration/preferences" Thunderbolt Bridge
rm "$2/Library/Preferences/SystemConfiguration/com.apple.smb.server.plist"
rm "$2/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist"

exit 0      ## Success
exit 1      ## Failure

In the end very confused and frustrated and seeking help from folks who have already tamed Mavericks imaging well.

franton
Valued Contributor III

My scripting runs over the top of the loginwindow on first boot. Attempting to run it anywhere else is not guaranteed!

blackholemac
Valued Contributor III

This seems like a lame question @franton][/url][/url, but I've got to ask to be specific.

loginwindow at first boot: so to implement that, I would create a launchdaemon (or launch agent whichever you recommend), have it and your script laid down after the OS is being laid down but before it reboots to do post imaging .pkg files (I can see doing that...make a DMG that contains your script called by a launchdaemon plist) and later get rid of said script and launchdaemon (or launch agent) after it has run successfully?

Is that you how implement running it "over the top of the loginwindow on first boot". Not a newbie, but since I'm having troubles, it always helps to be specific I'm guessing. I am going to try that but would appreciate any confirmation of your methodology. I thank you for responding to my earlier post.

franton
Valued Contributor III

@blackholemac Essentially that's it. Our implementation uses a launch agent (as daemons do not run on the loginwindow tag in launchd plists), to run iHook. iHook is called to run our firstrun script including the stuff you see above.

(iHook incidentally is used to provide a user accessible display of what the computer is doing while locking it out for general use until all tasks are done. This includes our initial software and policy installation.)

blackholemac
Valued Contributor III

that is why I was thinking a very simple daemon, it runs at boot, not as a user considering we are messing with system settings. I don't use iHook but am not opposed, it just isn't in our environment yet as I've never needed it. I'll try both as launch agent and launchdaemon to see what works, I have injected some upped logging code in the launchdaemon script to see how far things are getting.

Basically my overall goal is this, lay down the autodmg OS package and anything that doesn't need scripting logic to run. Reboot, install all the packages that do require scripting logic (maybe about 10 or 20 depending on our labs).

At installing all of those pkgs, I want to call an "environment package" I have that adds custom folder/file payloads for users where I want them and sets permissions right. As part of that "environment package", I have a post flight script that sets the behavior of the machine's environment.

Anyway, given that, the whole workflow seems to barf when I get to any package that requires network access (or if I take all the packages out leaving just the "environment package", it seems to barf when I get to the softwareupdate -i -a command)

franton
Valued Contributor III

What you propose could work ... it's not all that different from what we have. I prefer to get the jamf binary to do it's work when the full OS is present however. The disadvantage of my way is that you're operating not as the root user, so you have to do nasty kludge work if you need root level access such as the shutdown command.

blackholemac
Valued Contributor III

Well given what you told me about running it as a LaunchAgent at the loginwindow, I did some reading up (plus I tried doing it my way and spectacularly continued to fail.)

I formulated a launchagent here:

<?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>Label</key>
  <string>refreshnetworkprefs</string>
  <key>LimitLoadToSessionType</key>
  <array>
    <string>LoginWindow</string>
  </array>
  <key>Program</key>
<string>/Library/Scripts/Admin/refreshnetworkprefs.sh</string>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

I formulated a very minorly modified version of your script here..primarily to inject some breadcrumbs to see where I am failing and allow the network interfaces time to get IPs and settle:

#!/bin/sh

# Set up the variables we need for future changes

echo "script kicked off" >> /Library/Scripts/Admin/refreshnetworkprefslog

MacModel=$( ioreg -l | awk '/product-name/ { split($0, line, """); printf("%s
", line[4]); }' )
PrefModel=$( defaults read /Library/Preferences/SystemConfiguration/preferences.plist Model )

# Fix the incorrect model name in /Library/Preferences/SystemConfiguration/preferences.plist
# Also make sure the .plist is in the correct format

if [[ "$PrefModel" != "$MacModel" ]];
then
  /bin/echo $AdminPW | sudo -S defaults write /Library/Preferences/SystemConfiguration/preferences.plist Model $MacModel
  /bin/echo $AdminPW | sudo -S plutil -convert xml1 /Library/Preferences/SystemConfiguration/preferences.plist
fi

# Fix the incorrect network service names
# Script lovingly stolen from https://jamfnation.jamfsoftware.com/discussion.html?id=3422

echo "variables declared" >> /Library/Scripts/Admin/refreshnetworkprefslog

# Detect new network hardware
networksetup -detectnewhardware

# List all network services and read one by one
networksetup -listallnetworkservices | tail -n +2 | while read service
do

# Remove asterisk from string for renaming disabled services
    service=${service#**}

# Use filter to select next line which has the hardware port defined
    filter=false

# Display network services
    networksetup -listnetworkserviceorder | while read serviceorder
    do
        if [[ ${filter} == true ]]
        then
            # Grab hardware port
            hardwareport=`echo ${serviceorder} | sed -e 's/(Hardware Port: //;s/, Device:.*//'`

            # Check if service name if different
            if [[ ${service} != ${hardwareport} ]]
            then
                # Rename the network service
                networksetup -renamenetworkservice "${service}" "${hardwareport}"
                echo -e "Renamed network service "${service}" to "${hardwareport}""
            fi
        fi

        if [[ ${serviceorder} == *${service} ]]
        then        
            # Got the line with the service. Set the filter to true to grab the next line which contains the hardware port
            filter=true
            else
            filter=false
        fi
    done
done

sleep 10

launchctl unload -w /Library/LaunchDaemons/refreshnetworkprefs.plist

echo "script ran" >> /Library/Scripts/Admin/refreshnetworkprefslog
exit 0

I am testing this as I type...I'll keep you posted. Thank you @franton for being a patient man with us.

franton
Valued Contributor III

No worries. I've been through the pain of this firsthand, so glad to help. Anyway while I wait for a large amount of CS6 installs to finish, here's what I have.

LaunchAgent first. This calls a "wrapper" script as I found passing parameters from launchd to be fiddly.

<?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>Label</key>
  <string>com.ual.casperfirstrun</string>
  <key>LimitLoadToSessionType</key>
  <array>
    <string>LoginWindow</string>
  </array>
  <key>Program</key>
<string>/firstrun/firstrun.sh</string>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

Now for the first run script itself. I'm going to redact a few ... interesting sections.

#!/bin/bash

# Firstrun script for a freshly imaged JSS managed OS X client.

# Author      : r.purves@arts.ac.uk

# Version 1.0 : 1-11-2012 - Initial Version
# Version 1.1 : 5-11-2012 - Added MS DNS server settings
# Version 1.2 : 6-11-2012 - Now forcibly resets all network services to default
# Version 1.3 : 8-11-2012 - The above but also:
# 1) Finds the mac model name from the current computer
# 2) Fixes the /Library/Preferences/SystemConfiguration/preferences.plist to use correct model name
# 3) Removed MS DNS server settinsg
# This is because casper imaging 8.62 isn't changing the model key at all in this file causing headaches
# Version 1.4 : 13-11-2012 - Forces a policy flush and an mcx push.
# Version 1.5 : 19-11-2012 - Added assistive device and AD authenticated printing settings.

# Version 2.0 : 22-11-2012 - Added cascading menu system to fix Casper 8.62 building/dept bug
# Version 2.1 : 22-11-2012 - Now with added error trapping! Moved MCX refresh to just before manual software install trigger.
# Version 2.2 : 23-11-2012 - Interrogates JSS for building/dept config and skips menu if it has one.
# Version 2.3 : 23-11-2012 - Moved variables behind iHook invoke code to stop spurious screen on startup.
# Version 2.4 : 26-11-2012 - Tidied up JSS interrogation and added Adobe installer policies.
# Version 2.5 : 28-11-2012 - Implemented change of background for menu at specific points.
# Version 2.6 : 03-12-2012 - Process check function to try and avoid multiple jamf triggers running at once.
# Version 2.7 : 10-12-2012 - Changed timer on check function. Added code to make sure network and local hostnames are correct.
# Version 2.8 : 20-12-2012 - Debugged (again) the JSS check and added a computer/hostname refresh. Should keep DNS up to date.
# Version 2.9 : 18-01-2013 - Removed energy saver as this is now deployed automatically via smart groups
# Version 2.91: 24-01-2013 - Added time zone setting for incorrect clock on first boot.
# Version 2.92: 06-02-2013 - Removed spaces from department names.
# Version 2.93: 22-03-2013 - Added ARD enable for remote imaging purposes.
# Version 2.94: 28-03-2013 - Added the deletion of Adobe SpeedGrade symbolic link to fix inventory issues.
# Version 2.95: 20-05-2013 - Moved uadmin account creation to start of script along with addition to allowed SSH users list.

# Version 3.0 : 12-06-2013 - Initial Deploy version. Removed menu. Hard code building for Self Service deploy later.
# Version 3.01: 12-06-2013 - Added final recon to keep inventory correct
# Version 3.02: 12-08-2013 - Recording current imaging time to file for extension attribute
# Version 3.03: 18-10-2013 - Modification to re-enroll section that checks if the "jamf manage" stuff left by Imaging has finished
# Version 3.04: 29-01-2014 - Modified to set UAL energy saving settings before script finish, and to force curl install to use option "-3"
#                            This option forces the use of SSLv3. It only needs to be present on Casper sshadmin management account.
# Version 3.05: 07-02-2014 - Records last update time after performing the update
# Version 3.1 : 04-03-2014 - Work by j.durler@arts.ac.uk and myself to detect if computer inventory building/dept settings are present.
#                            If they are, auto image with correct software. If not, dump into holding group.

# iHook 1.2 - for status display over login window
# Copyright 2006 - Research Systems Unix Group
# http://rsug.itd.umich.edu/software/ihook

# Set up the variables we need for future changes

RunLoc="/firstrun"
AdminPW="xx"
MacModel=$( ioreg -l | awk '/product-name/ { split($0, line, """); printf("%s
", line[4]); }' )
PrefModel=$( defaults read /Library/Preferences/SystemConfiguration/preferences.plist Model )
errorcode=1
EnrollLD="/Library/LaunchDaemons/com.jamfsoftware.firstrun.enroll.plist"
EnrolWait=$(( 8 * 60 ))
EnrolWaitIncrement=30

# Start iHook progress display and to lock out the user from the mac

/bin/echo %BECOMEKEY
/bin/echo %WINDOWSIZE MAX
/bin/echo %WINDOWLEVEL HIGH
/bin/echo %WINDOWPOSITION CENTER
/bin/echo %BACKGROUND ./UAL.jpg
/bin/echo %BACKGROUNDSCALING PROPORTIONALLY
/bin/echo %BEGINPOLE
/bin/echo %SHOWTIMER
/bin/echo %0 Preparing to start OS X Software Deployment

# Set System Timezone to avoid clock sync issues and record imaging time.

systemsetup -settimezone Europe/London
systemsetup -setusingnetworktime on
systemsetup -setnetworktimeserver timeserver.com
/usr/sbin/ntpd -g -q

/bin/echo %TITLE "UAL Software Deployment - Started at" $( date )

/bin/echo $AdminPW | sudo -S touch /usr/lastimaged
/bin/echo $AdminPW | sudo -S echo "`date`" > /usr/lastimaged

/bin/echo %6 Detecting current building/department groups

# Set up variables for building/department autodetect and processing

ethernet=$(ifconfig en0|grep ether|awk '{ print $2; }')
apiurl=`/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf.plist jss_url`
apiuser="xx"
apipass="xx"
cmd="curl --silent --user ${apiuser}:${apipass} --request GET ${apiurl}JSSResource/computers/macaddress/${ethernet//:/.}"
hostinfo=$( ${cmd} )
building=$( echo $hostinfo | xpath '//computer/location/building' )
department=$( echo $hostinfo | xpath '//computer/location/department' )

# Hide users under UID 500 and create uadmin account here if it doesn't already exist

/bin/echo %12 Creating admin account

defaults write /Library/Preferences/com.apple.loginwindow.plist Hide500Users -bool YES

if id -u uadmin >/dev/null 2>&1; then
    echo "admin already exists. Skipping account creation."
else
    jamf createaccount -username uadmin -realname admin -password "$AdminPW" -home /Users/admin -shell /bin/bash -admin
fi

# Disable iCloud popup.

/bin/echo %18 Disabling iCloud pop up on first login
mv -f -v /System/Library/CoreServices/Setup Assistant.app/Contents/SharedSupport/MiniLauncher /System/Library/CoreServices/Setup Assistant.app/Contents/SharedSupport/MiniLauncher.backup

# Enable ARD for remote access for all users.

/bin/echo %24 Enabling Apple Remote Desktop access

/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -activate -configure -access -on -restart -agent -privs -all 

# Make sure the computer has enrolled

/bin/echo %30 Enrolling computer in JSS

echo "Checking to see if JAMF enroll.sh is still running"

while [ -e "$EnrollLD" ]; do
    if [ $EnrolWait -le 0 ]; then
        echo "Reached wait timeout of ${EnrolWait} seconds!"
        break
    fi

    echo "Still not complete. Waiting another ${EnrolWaitIncrement} seconds..."
    sleep $EnrolWaitIncrement 
    (( EnrolWait -= $EnrolWaitIncrement ))
done    

# Set up error trapping function for multiple jamf binary processes

function multiplejamf {
    # Check to see if jamf binary is running, and wait for it to finish.
    # Trying to avoid multiple triggers running at once at the expense of time taken.
    # There are two existing jamf processes running at all times. More than that is bad for us!

    TEST=$( pgrep jamf | wc -l )

    while [ $TEST -gt 2 ]
    do
        /bin/echo Waiting for existing jamf processes to finish ...
        sleep 3
        TEST=$( pgrep jamf | wc -l )
    done
}

# Set energy saving settings to never sleep

/bin/echo %36 Setting Energy Saving Settings for Deployment

/usr/bin/pmset -a displaysleep 0
/usr/bin/pmset -a disksleep 0
/usr/bin/pmset -a sleep 0

# Fix the incorrect model name in /Library/Preferences/SystemConfiguration/preferences.plist
# Also make sure the .plist is in the correct format

/bin/echo %42 Setting correct network details

if [[ "$PrefModel" != "$MacModel" ]];
then
  /bin/echo $AdminPW | sudo -S defaults write /Library/Preferences/SystemConfiguration/preferences.plist Model $MacModel
  /bin/echo $AdminPW | sudo -S plutil -convert xml1 /Library/Preferences/SystemConfiguration/preferences.plist
fi

# Fix the incorrect network service names
# Script lovingly stolen from https://jamfnation.jamfsoftware.com/discussion.html?id=3422

# Detect new network hardware
networksetup -detectnewhardware

# List all network services and read one by one
networksetup -listallnetworkservices | tail -n +2 | while read service
do

# Remove asterisk from string for renaming disabled services
    service=${service#**}

# Use filter to select next line which has the hardware port defined
    filter=false

# Display network services
    networksetup -listnetworkserviceorder | while read serviceorder
    do
        if [[ ${filter} == true ]]
        then
            # Grab hardware port
            hardwareport=`echo ${serviceorder} | sed -e 's/(Hardware Port: //;s/, Device:.*//'`

            # Check if service name if different
            if [[ ${service} != ${hardwareport} ]]
            then
                # Rename the network service
                networksetup -renamenetworkservice "${service}" "${hardwareport}"
                echo -e "Renamed network service "${service}" to "${hardwareport}""
            fi
        fi

        if [[ ${serviceorder} == *${service} ]]
        then        
            # Got the line with the service. Set the filter to true to grab the next line which contains the hardware port
            filter=true
            else
            filter=false
        fi
    done
done

# JAMF imaging should have set the machine name correctly. Let's make sure hostname is also set properly

setName=`networksetup -getcomputername`
scutil --set ComputerName ${setName}
scutil --set LocalHostName ${setName}
scutil --set HostName ${setName}

# Enable Assistive Device Access

/bin/echo %48 Enable Assistive Device Access

/usr/bin/touch /private/var/db/.AccessibilityAPIEnabled

# Enable AD authenticated printing

/bin/echo %54 Enable AD authenticated printing

/usr/sbin/cupsctl DefaultAuthType=Negotiate
pause 5

/bin/echo %60 Installing Department Specific Software

# Based on info obtained from JSS at start of script, detect if the building or department is set.
# If not set or incorrect, give it the holding group. Reset the building variable to stop it installing EVERYTHING!

if [ "$department" = "<department />" ] || [ "$building" = "<building />" ]
then
    multiplejamf    
    jamf recon -building InitialDeployment
    multiplejamf
    jamf recon -department InitialDeployment    
    building="InitialDeployment"
fi

# Process building/department variables to remove XML tags. Sorry for the terse bash but it worked. Eventually.

building=${building##*<building>}
building=${building%%</building>*}

department=${department##*<department>}
department=${department%%</department>*}

# If the building is correct (and it should be), install the proper departments policy load out.

case $building in
    building1|building2|building3|Unmanaged)
        multiplejamf
        jamf policy -trigger $department -verbose
        multiplejamf
        jamf recon
    ;;
esac

/bin/echo %66 Installing Initial Software

# This will install University wide software and policies (and CS6)

multiplejamf    
    jamf policy -trigger SoftwareInstall -verbose
multiplejamf
    jamf recon
multiplejamf
    jamf policy -trigger AdobeCSInstall1 -verbose
    rm /Applications/Adobe SpeedGrade CS6/Adobe SpeedGrade CS6.app/Contents/MacOS/Adobe SpeedGrade CS6.app
    jamf recon
multiplejamf
    jamf policy -trigger AdobeCSInstall2 -verbose

/bin/echo %72 Installing Updates

multiplejamf
    jamf policy -trigger UALUpdatePolicy -verbose
multiplejamf
    jamf recon

/bin/echo $AdminPW | sudo -S touch /usr/lastupdated
/bin/echo $AdminPW | sudo -S echo "`date`" > /usr/lastupdated

/bin/echo %78 Installing MCX Settings

multiplejamf
jamf mcx

# Final recon to make sure Inventory is up to date.

/bin/echo %84 Updating computer inventory record
multiplejamf
    jamf recon

# Cleanup on aisle three!

/bin/echo %90 Setting UAL Energy Saving settings

/usr/bin/pmset -a displaysleep 30
/usr/bin/pmset -a disksleep 0
/usr/bin/pmset -a sleep 0
/usr/bin/pmset -a womp 1
/usr/bin/pmset -a ring 0
/usr/bin/pmset -a autorestart 1
/usr/bin/pmset -a powerbutton 0

/bin/echo %96 Final cleanup of files

rm -f /Library/LaunchAgents/com.ual.casperfirstrun.plist
rm -rf /firstrun

# Shutdown iHook and the computer

/bin/echo %100 Complete! Mac will now restart in 10 seconds
/bin/sleep 10
/bin/echo echo %ENDPOLE

/bin/echo $AdminPW | sudo -S /sbin/shutdown -r now

exit 0

So what all this gets you is a first run script where unless your computer has an existing correct inventory record, it'll install base configuration and place it in a holding group. Self Service policies finish the configuration. If the computer has already been set up, the reimaging process becomes completely automatic.

Obviously this requires a lot of policy configuration to work as well.

blackholemac
Valued Contributor III

Looks very good...I'm gonna try to keep from having to reconfigure everything, but using the part I had before, the script called properly, but hung about midway at the second echo line I added to your script. I added about 3 or 4 more echo lines to see how far I get this time. I am going to study your script and learn man.

One of the reasons, I don't do things more the style you are doing them is that we operate in a modular imaging model (not thin, because i have to regularly refresh labs and what not). I could do thin imaging the first time but I don't want to have to send a tech later to boot all the Macs to Recovery partition and reinstall the OS and kick off a QuickAdd.

I am going to study and learn for sure. In the meantime, I added more echo lines to the script you had provided before and see where I get.

I found myself wondering while reading your script what the $AdminPW variables were being used for as I didn't see them declared. (Of course that is not something you would declare on a public forum, but is it something I have to declare in the script somewhere?).

franton
Valued Contributor III

No worries ;) The change log shows how long i've been working on it.

Rather than clog up this thread anymore, my email address is in the script. Shoot me an email and i'll discuss.