Install Apps After Mountain Lion Upgrade?

musat
Contributor II

Hello,

We are looking at the process for upgrading our Lion MacBook Airs to Mountain Lion and have run into a situation where an application needs to get installed right after the Mountain Lion upgrade for logins to work properly. Is there a way to queue a package install for "first boot" like you can for imaging?

Tim

7 REPLIES 7

andrew_stenehje
Contributor

We just had all of our teachers update their laptops to 10.8.3 through Self Service and we used a LaunchDaemon to trigger a "Cleanup" policy that ran at first boot after the update ran.

We used the post imaging style window to cover the login window while this was running, and the policy did things like:

  • Re Bind the machine to AD/OD and rename
  • Cleanup items like the iCloud pop up
  • Update applications, preferences, run Software Updates, etc

When it was done it ran Recon and rebooted. It worked great for us. The entire process generally took about an hour from start to finish. I'd be happy to send more information if it would be helpful.

mm2270
Legendary Contributor III

Is the product able to be installed without someone logged into the Mac? I'm assuming yes or you would have a bit of a chicken and egg problem on your hands. :)
If so, you could scope a policy with a trigger of "startup" to Macs in the process of being upgraded. You'd need a reliable way to identify any Macs that have begun the upgrade process, but aren't actually upgraded yet. Perhaps a dummy receipt or something to that affect dropped on the Macs when they initiate the upgrade process and a recon to pull them into a Smart Group.

There may be more efficient ways to do it, but hopefully that gives you an idea or two. A custom one time LaunchDaemon might also work, but it might be overkill for this situation.

andrew_stenehje
Contributor

I tested doing it in the way that mm2270 described but ran into quite a few cases where it didn't work properly, which is why I switched to using a LaunchDaemon. This jives with what I heard from a few others as well; Smart Groups and startup policies weren't as reliable as we'd all hoped. We just moved 2,000 laptops with our process using the LaunchDaemon and our failure rate was super small.

TimT
Contributor

I have been testing with a 10.8 upgrade using Greg Neagle's brilliant Son of InstallLion package and was trying to use manual triggers in the self service policy to recreate <500 accounts, User Template plists which get hosed in the upgrade via scripts but its not working for me. I have read launchd is the way to go but I'm a novice when it comes to creation and implementation within the 10.8 upgrade package in the policy.
Any advice would be appreciated. Cheers
Tim

rtrouton
Valued Contributor III

I've developed a installer package-based solution for this issue, where you can install packages at first boot following a createOSXinstallPkg-driven upgrade. I've posted about it here:

http://derflounder.wordpress.com/2013/05/13/first-boot-package-install-pkg/

The installer package is available here on my GitHub repo:

https://github.com/rtrouton/rtrouton_scripts/tree/master/rtrouton_scripts/first_boot_package_install...

musat
Contributor II

I am going to take a look at that createOSXinstall.pkg option, but, Andrew, I would be interested in reading more about your LaunchDaemon solution as well. It might fit in quicker to our current install than starting completely over with the createOSXinstall.pkg.

Tim

andrew_stenehje
Contributor

This might seem like overkill, but with 2,000 people running it, I wanted it to be pretty fool proof. Less than 10% of the machines that ran it had problems, and the problems were due to things like network issues or staff people not plugging into power, etc; not problems with the process itself. It allowed users to just plugin, start the install from Self Service and come back about an hour later to an updated and patched machine that still had all of their data/apps. We were very happy with how it went.

Here's what we did...

##############################################################

Created a Smart Group of computers that were eligible for the 10.8 update. Criteria for this group was "like 10.7" or "is 10.6.8", and "not like 10.8", and then all of the hardware specific requirements for 10.8 (proc, memory, excluded models, etc).

Created a policy scoped to this group, called "Install Mountain Lion", in Self Service. This policy installs these items:

  • A package called "Mountain Lion Cleanup Trigger"
  • A package called "Mountain Lion Didn't Install Cleanup"
  • A package called "Cleanup Window", which is just a Launch Agent that calls JAMFHelper to cover up the login window while the cleanup stuff is running
  • The 10.8.3 installer, created using Greg Neagle's awesome tool

##############################################################

The "Mountain Lion Cleanup Trigger" package includes a LaunchDaemon (set to Run at Load) and the script it runs. The script looks like this:

#!/bin/sh

# Triggers policy that runs post Mountain Lion installation items
# AS (1-22-13)

echo "Pausing 30 seconds..."
/bin/sleep 30


# variables
OSVERSION=`/usr/bin/sw_vers | /usr/bin/grep ProductVersion |  /usr/bin/awk '{print $2}' | sed -Ee 's/^[0-9]+.([0-9]+).[0-9]+$/1/'`


if [ "$OSVERSION" = 8 ]; then


    # Create file that Extenstion Attribute is based off of
    /usr/bin/touch /Library/Management/.mountainlion

    # Remove items to catch failures
    if [ -f /Library/LaunchAgents/us.or.k12.beaverton.ml_error_cleanup.plist ]; then 

        /bin/rm -f /Library/LaunchAgents/us.or.k12.beaverton.ml_error_cleanup.plist

        else

        /bin/rm -f /Library/Management/us.or.k12.beaverton.ml_error_cleanup.plist

    fi

        /bin/rm -f /Library/Management/ml_error_cleanup.sh
        /bin/rm -f /Library/Management/OS-X-Mountain-Lion.png

    echo "Running Mountain Lion Cleanup Policy"
    /usr/sbin/jamf policy -action MountainLionCleanup



else

        /bin/echo "Not Running 10.8.  Will abort Post Mountain Lion Cleanup."

        # Move Failure Launch Agent into place so user gets popup
        /bin/mv /Library/Management/us.or.k12.beaverton.ml_error_cleanup.plist /Library/LaunchAgents/
        /usr/sbin/chown root:admin /Library/LaunchAgents/us.or.k12.beaverton.ml_error_cleanup.plist
        /bin/chmod 644 /Library/LaunchAgents/us.or.k12.beaverton.ml_error_cleanup.plist

        # Create file that Extenstion Attribute is based off of
        /usr/bin/touch /Library/Management/.mountainlion_fail

        # Stop the loginwindow image from showing
        /usr/bin/killall -m jamfHelper

        # Remove Launch items meant for post install cleanup
        /bin/mv /Library/LaunchDaemons/com.bsd.MountainLionCleanup.plist /Library/Management/
        /usr/sbin/chown root:wheel /Library/Management/com.bsd.MountainLionCleanup.plist
        /bin/rm /Library/LaunchAgents/com.bsd.postimage.2012.plist


        # Refresh the login window for good measure
        /usr/bin/killall loginwindow 

        # Run Recon so machine gets into group of failed 10.8 machines via extension attribute
        /usr/sbin/jamf recon

fi

As you can see, the script checks the OS and if it's 10.8 (which means the installer ran successfully), it creates a file for an extension attribute so we know it ran the update successfully, and then triggers a policy that runs all of the cleanup items. If the OS is not 10.8, we know the update failed, so it kills and removes the JAMFHelper login window pop up and moves the Launch D item so that it doesn't run at reboot every time. It also moves the "failure" Launch Agent into place so that users are notified at login that the install failed. I put this in place because there were some machines that the 10.8 update wouldn't run successfully on, and this would give the user a way of knowing that it hadn't actually worked. Might not be necessary if you're only doing a few machines, but for 2,000 I wanted to have our bases covered.

##############################################################

The "Mountain Lion Didn't Install Cleanup" package includes a Launch Agent that calls this script:

#!/bin/bash


####################################################################################################
# Meant to run if 10.8 Self Service Install fails
# Prompts User to Update to 10.8
# AS
####################################################################################################
####################################################################################################

if [ -d /Library/Application Support/JAMF/bin/jamfHelper.app ]; then 
    userDecision=`/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -title "Company Name Here" -heading "10.8 Update Failed!" -alignHeading center -description 'This computer appears to have failed the 10.8 Mountain Lion Update.  Please click on "Install Now" to open Self Service so that you can start the update again.' -button2 "Install Now" -defaultButton 2 -icon "/Library/Management/OS-X-Mountain-Lion.png" -iconSize 125 &`

    else 
            echo "Could not find jamfHelper.app"
        exit 0
fi 


if [ "$userDecision" = 2 ]; then

        echo "Opening Self Service"

        # Open Self Service
        open /Applications/Self Service.app


else
        echo User cancelled

fi

##############################################################

The "Mountain Lion Cleanup" policy that gets triggered after the update successfully ran, runs the following items:

  1. Bind script that unbinds, renames and rebinds machine to AD/OD
  2. Scripts that do things like disable gatekeeper, modify kerb settings if needed, update iLife if needed, update Promethean software if needed, runs Apple Software Updates, modifies the /etc/authorization file to open up some prefs for staff, looks at name of machine and adds additional admin group for the machine if it belongs to a certain site.
  3. Uninstalls our previous User Templates package and installs newest version
  4. Uninstalls other packages for software that isn't 10.8 compatible and installs newer version if it exists
  5. Installs latest HP printer drivers
  6. Installs latest Java web app
  7. Installs latest Java for OSX
  8. Installs package that disables X Protect
  9. Installs package that enables Java for Safari 6.0.3+
  10. Installs latest Office update
  11. Flush user caches
  12. Runs unix command "sudo /bin/rm /Users//Library/Preferences/ByHost/com.apple.loginwindow." so that Self Service (and other apps) don't open when the user logs in after the update
  13. Runs a script called "mountain_lion_cleanup_after.sh" (see contents below)

##############################################################

"mountain_lion_cleanup_after" script contents:

#!/bin/bash


##################################################################################################################################
# Runs cleanup items at end of Mountain Lion Install Cleanup policy
# This is a combination of other scripts
# AS
##################################################################################################################################
##################################################################################################################################



###################################################################################################################################
# Turn off Java Updates and remove Launch Agent pop up
##################################################################################################################################

        ####################################################################################################
        ####################################################################################################



        /bin/echo "Beginning running disable_java_updates script"


        ####################################################################################################
        # Get number variable needed to set suppression of update reminder
        ####################################################################################################

        NUMBER=`/bin/cat /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Enabled.plist |grep ';deploy=' |cut -d"=" -f2 |cut -d"<" -f1`

            echo The number for suppression of this version of Java is "$NUMBER"


            # Verify that it received a numeric value

                case "$NUMBER" in 
                [0-9]*) 
                        echo "Entry is a numeric value.  Continuing..."
                        ;;
                * ) 
                        echo "Error: This entry is not a number.  Will fail to properly suppress update pop up."
                        ;;
                esac



        ####################################################################################################
        # Remove Updater Launch Agent Sym Link that gets created during updates
        ####################################################################################################

            /bin/echo "Checking to see if Launch Agent sym link exists..."

                if [ -f /Library/LaunchAgents/com.oracle.java.Java-Updater.plist ]; then

                    /bin/echo "Launch Agent exists.  Unloading and removing."

                    /bin/rm /Library/LaunchAgents/com.oracle.java.Java-Updater.plist

                    /bin/echo "Removed Update Launch Agent Sym Link"

                else
                            /bin/echo "Launch Agent does not exist."

                fi


        ####################################################################################################
        # Remove Updater Launch Daemon Sym Link that gets created during updates
        ####################################################################################################

            /bin/echo "Checking to see if Launch Daemon sym link exists..."

                if [ -f /Library/LaunchDaemons/com.oracle.java.Helper-Tool.plist ]; then

                    /bin/echo "Launch Daemon exists.  Unloading and removing."

                    /bin/rm /Library/LaunchDaemons/com.oracle.java.Helper-Tool.plist

                    /bin/echo "Removed Update Launch Daemon Sym Link"

                else
                            /bin/echo "Launch Daemon does not exist."

                fi


        ####################################################################################################
        ####################################################################################################


                # Check to see if Java Plugin exists
                if [ -d /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home ]; then


                        echo "Java Plugin is installed, continuing..."


                                if [ ! -f /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties ]; then

                                        /bin/echo "The deployment.properties file does not yet exist.  Will create..."


                                            # Create deployment.properties file
                                                /usr/bin/touch /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties

                                                    /bin/echo "Created deployment.properties file"


                                            # Change ownership on this new file
                                                /usr/sbin/chown root:wheel /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties

                                                    /bin/echo "Changed ownership on deployment.properties file"


                                            # Change permissions on this file
                                                /bin/chmod 755 /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties

                                                    /bin/echo "Changed permissions on deployment.properties file"


                                            # Write contents of this file
                                                /bin/echo '#deployment.properties' > /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.macosx.check.update.locked >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.macosx.check.update=false >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.expiration.decision.suppression."$NUMBER".locked >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.expiration.decision.suppression."$NUMBER"=true >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.expiration.decision."$NUMBER".locked >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.expiration.decision."$NUMBER"=later >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties

                                                    /bin/echo "Wrote content to deployment.properties file.  Have a wonderful day."

                                        else


                                                    /bin/echo "deployment.properties file already exists.  Removing and building new version..."


                                            # Delete existing version of the file
                                                    /bin/rm -f /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties

                                                    /bin/echo "Deleted previous deployment.properties file"


                                            # Create deployment.properties file
                                                /usr/bin/touch /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties

                                                    /bin/echo "Created deployment.properties file"


                                            # Change ownership on this new file
                                                /usr/sbin/chown root:wheel /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties

                                                    /bin/echo "Changed ownership on deployment.properties file"


                                            # Change permissions on this file
                                                /bin/chmod 755 /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties

                                                    /bin/echo "Changed permissions on deployment.properties file"


                                            # Write contents of this file
                                                /bin/echo '#deployment.properties' > /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.macosx.check.update.locked >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.macosx.check.update=false >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.expiration.decision.suppression."$NUMBER".locked >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.expiration.decision.suppression."$NUMBER"=true >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.expiration.decision."$NUMBER".locked >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties
                                                /bin/echo deployment.expiration.decision."$NUMBER"=later >> /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/deployment.properties

                                                    /bin/echo "Wrote content to deployment.properties file.  Have a wonderful day."


                                fi

                else
                        echo "Error: Failure to find Java Plugin path.  Either Java is not installed, or the path within the plugin has changed. Exiting"

                fi



        /bin/echo "Finished running disable_java_updates script"



##################################################################################################################################



########################################
# Disables iCloud/Apple ID Login Pop up
########################################


        # Remove existing Setup Assistant file from all existing user directories   
            /bin/rm -rf /Users/*/Library/Preferences/com.apple.SetupAssistant.plist
            /bin/rm -rf /Users/*/Library/Preferences/com.apple.loginwindow.plist
            /bin/rm -rf /Users/*/Library/Preferences/loginwindow.plist


                # Remove our local admin Setup and Login Window files
                    /bin/rm -rf /private/var/ouradmin/Library/Preferences/com.apple.SetupAssistant.plist
                    /bin/rm -rf /private/var/ouradmin/Library/Preferences/com.apple.loginwindow.plist
                    /bin/rm -rf /private/var/ouradmin/Library/Preferences/loginwindow.plist

                echo "Removed Setup Assistant file and Login Window files for all users"



        # Copy items to any existing user folders except Shared
            find /Users -maxdepth 1 -type d ! -name Shared -mindepth 1 -exec /bin/cp -r /System/Library/User Template/English.lproj/Library/Preferences/com.apple.SetupAssistant.plist {}/Library/Preferences/com.apple.SetupAssistant.plist ;

            find /Users -maxdepth 1 -type d ! -name Shared -mindepth 1 -exec /bin/cp -r /System/Library/User Template/English.lproj/Library/Preferences/loginwindow.plist {}/Library/Preferences/loginwindow.plist ;

            find /Users -maxdepth 1 -type d ! -name Shared -mindepth 1 -exec /bin/cp -r /System/Library/User Template/English.lproj/Library/Preferences/com.apple.loginwindow.plist {}/Library/Preferences/com.apple.loginwindow.plist ;


                # Copy items to our local admin folder
                    /bin/cp -r /System/Library/User Template/English.lproj/Library/Preferences/com.apple.SetupAssistant.plist private/var/ouradmin/Library/Preferences/com.apple.SetupAssistant.plist
                    /bin/cp -r /System/Library/User Template/English.lproj/Library/Preferences/com.apple.loginwindow.plist private/var/ouradmin/Library/Preferences/com.apple.loginwindow.plist
                    /bin/cp -r /System/Library/User Template/English.lproj/Library/Preferences/loginwindow.plist private/var/ouradmin/Library/Preferences/loginwindow.plist


                echo "Copied Setup Assistant file and Login Window files for all users"



        # Change ownership on this folder to the user
            for user in `find /Users -maxdepth 1 -type d ! -name Shared -mindepth 1 |cut -d/ -f3`
                do
                    /usr/sbin/chown -R $user /Users/$user/Library/Preferences/
                done


                    # Change our local admin file ownership
                        /usr/sbin/chown -R ouradmin /private/var/ouradmin/Library/Preferences/com.apple.SetupAssistant.plist
                        /usr/sbin/chown -R ouradmin /private/var/ouradmin/Library/Preferences/com.apple.loginwindow.plist
                        /usr/sbin/chown -R ouradmin /private/var/ouradmin/Library/Preferences/loginwindow.plist

                echo "Changed owernship on Setup Assistant file for all users"



##################################################################################################################################



####################################################################################
# Finishes cleanup, removes Launch Items, updates Login window, runs Recon, Reboots
####################################################################################

        # Create File that Extension attribute is built off of
            /usr/bin/touch /Library/Management/.mountainlion

                echo "Created Mountain Lion file for Extension Attribute"

        # If Failure file exists, remove
            if [ -f /Library/Management/.mountainlion_fail ]; then

                /bin/rm -f /Library/Management/.mountainlion_fail


                echo "Removed failed Mountain Lion file that existed.  Machine must have previously failed install.  This will now show up as a failed machine in policy log."
            fi


        # Trigger Policy that will change Apple logo at Login Window to our Logo
            /usr/sbin/jamf policy -action InstallBSDLogoLion

                echo "Ran Logo policy"


        # Remove Launch Item that triggered this policy
            /bin/rm /Library/LaunchDaemons/com.bsd.MountainLionCleanup.plist

                echo "Removed Mountain Lion Cleanup startup item"


        # Run Recon
                echo "Running Recon..."

            /usr/sbin/jamf recon


        #Remove the plist file so that it doesn't pop up again
            /bin/rm /Library/LaunchAgents/com.bsd.postimage.2012.plist   

                echo "Removed Launch Item that triggered Login Window Message"


        # Stop the loginwindow image from showing
            /usr/bin/killall -m jamfHelper

                echo "Killed jamfHelper Login Window item"


        # Refresh the login window for good measure
            /usr/bin/killall loginwindow 

                echo "Refreshed the Login Window"


        # Reboot in one minute
                echo "This is the last cleanup line.  Will reboot in one minute..."

            /sbin/shutdown -r +1 



##################################################################################################################################
##################################################################################################################################
##################################################################################################################################

##############################################################

Hope this helps...