Deploying an OS X Upgrade: Recon at Reboot script

dan-snelson
Valued Contributor II

Overview

The script below will create a LaunchDaemon and Bash script to run Recon at the next reboot.

We've found this helpful with OS upgrade policies which tend to ignore (or fail) when "Maintenance > Update Inventory" is included.


Background

We use Deploying OS X v10.7 or Later with the Casper Suite as a guide for our users to upgrade their operating system via Self Service.

After the installer is cached, in a separate policy, we prompt users to visit Self Service and actually run the OS upgrade. The policy then updates inventory.

Including "Maintenance > Update Inventory" in the OS installation policy proved problematic and after a sucessful OS upgrade via Self Service, the JSS would have stale inventory data and end-users would be again prompted to install the OS upgrade they ran the day before.


Script

Note: Search for /path/to/client-side/ and replace with the appropriate path.

#!/bin/bash
####################################################################################################
#
# ABOUT
#
#   Creates a Launch Daemon to run a Recon at next Reboot
#
####################################################################################################
#
# HISTORY
#
#   Version 1.0, 10-Nov-2016, Dan K. Snelson
#
####################################################################################################
# Import client-side functions
source /path/to/client-side/functions.sh
####################################################################################################

# Variables
plistDomain="com.company"                     # Hard-coded domain name (i.e., "com.company")
plistLabel="reconAtReboot"                        # Unique label for this plist (i.e., "reconAtReboot")
plistLabel="$plistDomain.$plistLabel"             # Prepend domain to label

ScriptLog "##############################"
ScriptLog "### Recon at Reboot Create ###"
ScriptLog "##############################"


# Create launchd plist to call a shell script
ScriptLog "* Create the LaunchDaemon ..."

/bin/echo "<?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>${plistLabel}</string>
        <key>ProgramArguments</key>
        <array>
            <string>sh</string>
            <string>/path/to/client-side/scripts/reconAtReboot.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
</plist>" > /Library/LaunchDaemons/$plistLabel.plist



# Set the permission on the file
ScriptLog "* Set LaunchDaemon file permissions ..."

/usr/sbin/chown root:wheel /Library/LaunchDaemons/$plistLabel.plist
/bin/chmod 644 /Library/LaunchDaemons/$plistLabel.plist
/bin/chmod +x /Library/LaunchDaemons/$plistLabel.plist



# Create reboot script
ScriptLog "* Create the script ..."
/bin/echo "#!/bin/sh
####################################################################################################
#
# ABOUT
#
#   Recon at Reboot
#
####################################################################################################
#
# HISTORY
#
#   Version 1.0, 10-Nov-2016, Dan K. Snelson
#
####################################################################################################
# Import logging functions
source /path/to/client-side/functions.sh
####################################################################################################

ScriptLog "### Recon at Reboot ###"

ScriptLog " " # Blank line for readability

# Sleeping for 300 seconds to give Wi-Fi time to come online.
ScriptLog "* Pausing Recon at Reboot for five minutes to allow Wi-Fi and DNS to come online ..."
/bin/sleep 300
ScriptLog "* Resuming Recon at Reboot ..."

ScriptLog "* Updating inventory ..."
/usr/local/bin/jamf recon

# Delete launchd plist
ScriptLog "* Delete $plistLabel.plist ..."
/bin/rm -fv /Library/LaunchDaemons/$plistLabel.plist

# Delete script
ScriptLog "* Delete script ..."
/bin/rm -fv /path/to/client-side/scripts/reconAtReboot.sh

exit 0" > /path/to/client-side/scripts/reconAtReboot.sh

# Set the permission on the file
ScriptLog "* Set script file permissions ..."
/usr/sbin/chown root:wheel /path/to/client-side/scripts/reconAtReboot.sh
/bin/chmod 644 /path/to/client-side/scripts/reconAtReboot.sh
/bin/chmod +x /path/to/client-side/scripts/reconAtReboot.sh

ScriptLog "* LaunchDaemon and Script created."

exit 0
7 REPLIES 7

jwojda
Valued Contributor II

I get a bunch of errors with this... when I run it with my 10.13 upgrade (10.12.x when it's installed, 10.13 after the upgrade)

: /Library/Application Support/JAMF/tmp/ReconAtReboot: line 16: /Library/Scripts/functions.sh: No such file or directory
/Library/Application Support/JAMF/tmp/ReconAtReboot: line 24: ScriptLog: command not found
/Library/Application Support/JAMF/tmp/ReconAtReboot: line 25: ScriptLog: command not found
/Library/Application Support/JAMF/tmp/ReconAtReboot: line 26: ScriptLog: command not found
/Library/Application Support/JAMF/tmp/ReconAtReboot: line 30: ScriptLog: command not found
/Library/Application Support/JAMF/tmp/ReconAtReboot: line 51: ScriptLog: command not found
/Library/Application Support/JAMF/tmp/ReconAtReboot: line 60: ScriptLog: command not found
/Library/Application Support/JAMF/tmp/ReconAtReboot: line 99: /Library/Scripts/scripts/reconAtReboot.sh: No such file or directory
/Library/Application Support/JAMF/tmp/ReconAtReboot: line 102: ScriptLog: command not found
chown: /Library/Scripts/scripts/reconAtReboot.sh: No such file or directory
chmod: /Library/Scripts/scripts/reconAtReboot.sh: No such file or directory
chmod: /Library/Scripts/scripts/reconAtReboot.sh: No such file or directory
/Library/Application Support/JAMF/tmp/ReconAtReboot: line 107: ScriptLog: command not found

bpavlov
Honored Contributor

Looks whoever posted the script left out the function.

Look
Valued Contributor III

Can't you just create a once only on restart policy scoped to the new version people are moving to? i.e. 10.13 in this case.
Actually you could just have one for each major version and one of them would run whenever anyone moved from one version to another.

EDIT: Scrub that, won't work because of course the JSS doesn't know there is a new version!

jwojda
Valued Contributor II

@dan.snelson can you check the functions that are required to run this?

dan-snelson
Valued Contributor II

@jwojda Sorry for the delay; here's part of the client-side functions we install on Macs during enrollment. (You should be able to just use echo or logger instead.)

Client-side Functions

You'll need to install the following functions client-side (i.e., when enrollment in complete)

#!/bin/sh
####################################################################################################
#
# ABOUT
#
#   Standard functions which are imported into other scripts
#
####################################################################################################



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
#
# LOGGING
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 


## Variables
logFile="/var/log/com.company.log"
alias now="/bin/date '+%Y-%m-%d %H:%M:%S'"


## Check for / create logFile
if [ ! -f "${logFile}" ]; then
    # logFile not found; Create logFile ...
    /usr/bin/touch "${logFile}"
    /bin/echo "`/bin/date +%Y-%m-%d %H:%M:%S`  *** Created log file via function ***" >>"${logFile}"
fi

## I/O Redirection to client-side log file
exec 3>&1 4>&2            # Save standard output (stdout) and standard error (stderr) to new file descriptors
exec 1>>"${logFile}"        # Redirect standard output, stdout, to logFile
exec 2>>"${logFile}"        # Redirect standard error, stderr, to logFile


function ScriptLog() { # Write to client-side log file ...

    /bin/echo "`/bin/date +%Y-%m-%d %H:%M:%S`  ${1}"

}



function jssLog() { # Write to JSS ...

    ScriptLog "${1}"              # Write to the client-side log ...

    ## I/O Redirection to JSS
    exec 1>&3 3>&- 2>&4 4>&-        # Restore standard output (stdout) and standard error (stderr)
    /bin/echo "${1}"              # Record output in the JSS

}

jwojda
Valued Contributor II

when you say install, what does that mean?
dump the script in a folder?

dan-snelson
Valued Contributor II

@jwojda Correct; we built a package which installs the client-side functions that is installed on each client when enrollment is complete.

(You could combine both scripts into one or use logger to write to system.log.)