Script testing

kadams
Contributor

Hello everyone, I have this script im testing that @mm2270 posted. The script checks for apple updates and if the machine requires a reboot. I would like to know if there is a way to get a reboot script to only execute after the first script has said it requires a reboot? My personal machine is up to date at the moment. When I run the script, it says that no reboot is requires at this time. I have another script that prompts the user to reboot the machine and has a deferral option. I would like the second script to only run when the first script has said the computer needs a reboot.

4 REPLIES 4

dzogrim
New Contributor III

Maybe @mm2270 can answer your question, but how to help and know which script you're talking about since he posted a lot πŸ™‚

mm2270
Legendary Contributor II

Yes, please post a link to the script you're referring to. Unfortunately, some of the older scripts I've posted may not be working anymore and I don't always have time to go back to look over them for a refresh. But if you post the script or preferably a link to it, I'll be able to tell you if it can be modified to do what you're asking.

kadams
Contributor

Here is the script that I have taken from your post @mm2270

!/bin/bash

Get available Software Updates and determine which need reboots when installed

############### Script behavior options (Choose one or both options) ###############

Set the below variable to Yes to make the script operate as an Extension Attribute

EAScript="Yes"

Set the below variable to Yes to have the script export the results out to a local log file

LogScript="Yes"

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

Local file where reboot required update names get stored (if option above is enabled)

Reboot_Needed_Log="/Library/Application Support/Reboot_Updates_Needed"

Gets the names of downloaded updates that require a reboot by scanning for the reboot flag in the dist file

function get_Reboot_Updates ()
{

i=0
while read folder; do if [[ -e "/Library/Updates/${folder}" ]]; then while read distFile; do if [[ $(grep -i restart "$distFile") ]]; then RestartPkgs+=("${updateIdentifiers[$i]}-${updateVersions[$i]}") fi done < <(find "/Library/Updates/${folder}" -name *.dist) let i=$((i+1)) else echo "Could not find path /Library/Updates/${folder}" fi
done < <(printf '%s ' "${productKeys[@]}")

if [[ "${RestartPkgs[@]}" != "" ]]; then echo "Some updates require a reboot"

if [ "$EAScript" ]; then ## prints the reboots needed results in Casper Suite Extension Attribute format echo "<result>$(printf '%s ' "${RestartPkgs[@]}")</result>" fi

if [ "$LogScript" ]; then echo "Adding details to local file..." ## Sends the reboots needed result into local log file printf '%s ' "${RestartPkgs[@]}" > "$Reboot_Needed_Log" exit 0 fi
else echo "No reboot updates are available at this time..." if [ "$EAScript" ]; then echo "<result>None</result>" fi

if [ "$LogScript" ]; then echo "Nothing to write to log file" exit 0 fi
fi

}

Creates several arrays with values extracted from the SoftwareUpdate plist (to be used later)

function get_Update_Stats ()
{

echo "Getting update stats..."

RecommendedUpdatesData=$(/usr/bin/defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist RecommendedUpdates)

while read identifier; do updateIdentifiers+=("$identifier")
done < <(awk -F'= ' '/Identifier/{print $NF}' <<< "$RecommendedUpdatesData" | sed 's/"//g;s/;//g')

while read version; do updateVersions+=("$version")
done < <(awk -F'= ' '/Display Version/{print $NF}' <<< "$RecommendedUpdatesData" | sed 's/"//g;s/;//g')

while read Key; do productKeys+=("$Key")
done < <(awk -F'= ' '/Product Key/{print $NF}' <<< "$RecommendedUpdatesData" | sed 's/"//g;s/;//g')

while read Name; do displayNames+=("$Name")
done < <(awk -F'= ' '/Display Name/{print $NF}' <<< "$RecommendedUpdatesData" | sed 's/"//g;s/;//g')

echo "Looking for reboot required updates..."
get_Reboot_Updates

}

Checks the current downloaded updates versus what Software Update's last check saw as being available

check_Downloads_Vs_AvailUpdates ()
{

While reading over the recommended update IDs, check to see if a matching directory exists in /Library/Updates/

If any are not found, set a flag to get new downloads

while read item; do if [[ $(echo "$downloadedUpdates" | grep "$item") == "" ]]; then getDownloads="Yes" fi
done < <(printf '%s ' "$RecommendedUpdateKeys")

If the get downloads flag was set, first download available updates before continuing

if [ "$getDownloads" ]; then echo "Some available updates are not already downloaded. Downloading all available updates..." softwareupdate -d -a get_Update_Stats
else ## Or, if all downloads are accounted for, move to grabbing the values from the plist echo "All available updates have been downloaded. Skipping to checking the update stats..." get_Update_Stats
fi

}

Remove any previous reboot needed log file

if [ -e "/Library/Application Support/Reboot_Updates_Needed" ]; then rm "/Library/Application Support/Reboot_Updates_Needed"
fi

Get the last recommended update IDs from the SoftwareUpdate plist

RecommendedUpdateKeys=$(/usr/bin/defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist RecommendedUpdates | awk -F'= ' '/Product Key/{print $NF}' | sed 's/"//g;s/;//g')

Get a list of directories in /Library/Updates/ to scan through

downloadedUpdates=$(find "/Library/Updates" -maxdepth 1 -type d | sed '1d')

echo "Running check for available updates..."
check_Downloads_Vs_AvailUpdates

mm2270
Legendary Contributor II

Just for the purposes of making sure the script is clear on this thread, I'm reposting the full script below. When posting a script here, highlight it and click the script tag in the small toolbar above the post field. It looks something like >_ so it's readable as a script.

So, this script I wrote doesn't install anything at all. I'm guessing you know that, but I wanted to be sure. It simply checks the available updates and determines if any of them would require a reboot and then prints back an answer on what it found. I'm not sure if your plan was to then install all available updates after running this or not, and then invoking your reboot deferral script if needed, but if so, there is likely an easier way to do this.
Still, if that is your plan, you'll want to add a line or section in the get_Reboot_Updates function area. Directly underneath these lines

if [[ "${RestartPkgs[@]}" != "" ]]; then
    echo "Some updates require a reboot"

you can add a jamf policy call that will run your other script, which you can attach to a policy. That section is for when it found updates, so that's the most logical place to put something that would run another script call.

Another thing you could consider is to merge the scripts together. Take the main program of your reboot deferral script and place it into it's own function within my script. Then in the get_Reboot_Updates section I call out above, add a line that calls that function. Let's say you name the function show_reboot_deferral, you would add that to the section, like so

if [[ "${RestartPkgs[@]}" != "" ]]; then
    echo "Some updates require a reboot"
    ## Call the reboot deferral function
    show_reboot_deferral

But you of course need to make sure there is a full function within the script that is referenced by that, or it won't work.

Good luck.

Full script below

#!/bin/bash

## Get available Software Updates and determine which need reboots when installed

##################### Script behavior options (Choose one or both options) #####################

## Set the below variable to Yes to make the script operate as an Extension Attribute
EAScript="Yes"

## Set the below variable to Yes to have the script export the results out to a local log file
LogScript="Yes"

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

## Local file where reboot required update names get stored (if option above is enabled)
Reboot_Needed_Log="/Library/Application Support/Reboot_Updates_Needed"


## Gets the names of downloaded updates that require a reboot by scanning for the reboot flag in the dist file
function get_Reboot_Updates ()
{

i=0
while read folder; do
    if [[ -e "/Library/Updates/${folder}" ]]; then
        while read distFile; do
            if [[ $(grep -i restart "$distFile") ]]; then
                RestartPkgs+=("${updateIdentifiers[$i]}-${updateVersions[$i]}")
            fi
        done < <(find "/Library/Updates/${folder}" -name *.dist)
        let i=$((i+1))
    else
        echo "Could not find path /Library/Updates/${folder}"
    fi
done < <(printf '%s
' "${productKeys[@]}")

if [[ "${RestartPkgs[@]}" != "" ]]; then
    echo "Some updates require a reboot"

    if [ "$EAScript" ]; then
        ## prints the reboots needed results in Casper Suite Extension Attribute format
        echo "<result>$(printf '%s
' "${RestartPkgs[@]}")</result>"
    fi

    if [ "$LogScript" ]; then
        echo "Adding details to local file..."
        ## Sends the reboots needed result into local log file
        printf '%s
' "${RestartPkgs[@]}" > "$Reboot_Needed_Log"
        exit 0
    fi
else
    echo "No reboot updates are available at this time..."
    if [ "$EAScript" ]; then
        echo "<result>None</result>"
    fi

    if [ "$LogScript" ]; then
        echo "Nothing to write to log file"
        exit 0
    fi
fi

}

## Creates several arrays with values extracted from the SoftwareUpdate plist (to be used later)
function get_Update_Stats ()
{

echo "Getting update stats..."

RecommendedUpdatesData=$(/usr/bin/defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist RecommendedUpdates)

while read identifier; do
    updateIdentifiers+=("$identifier")
done < <(awk -F'= ' '/Identifier/{print $NF}' <<< "$RecommendedUpdatesData" | sed 's/"//g;s/;//g')

while read version; do
    updateVersions+=("$version")
done < <(awk -F'= ' '/Display Version/{print $NF}' <<< "$RecommendedUpdatesData" | sed 's/"//g;s/;//g')

while read Key; do
    productKeys+=("$Key")
done < <(awk -F'= ' '/Product Key/{print $NF}' <<< "$RecommendedUpdatesData" | sed 's/"//g;s/;//g')

while read Name; do
    displayNames+=("$Name")
done < <(awk -F'= ' '/Display Name/{print $NF}' <<< "$RecommendedUpdatesData" | sed 's/"//g;s/;//g')

echo "Looking for reboot required updates..."
get_Reboot_Updates

}


## Checks the current downloaded updates versus what Software Update's last check saw as being available
check_Downloads_Vs_AvailUpdates ()
{

## While reading over the recommended update IDs, check to see if a matching directory exists in /Library/Updates/
## If any are not found, set a flag to get new downloads
while read item; do
    if [[ $(echo "$downloadedUpdates" | grep "$item") == "" ]]; then
        getDownloads="Yes"
    fi
done < <(printf '%s
' "$RecommendedUpdateKeys")

## If the get downloads flag was set, first download available updates before continuing
if [ "$getDownloads" ]; then
    echo "Some available updates are not already downloaded. Downloading all available updates..."
    softwareupdate -d -a
    get_Update_Stats
else
    ## Or, if all downloads are accounted for, move to grabbing the values from the plist
    echo "All available updates have been downloaded. Skipping to checking the update stats..."
    get_Update_Stats
fi

}

## Remove any previous reboot needed log file
if [ -e "/Library/Application Support/Reboot_Updates_Needed" ]; then
    rm "/Library/Application Support/Reboot_Updates_Needed"
fi


## Get the last recommended update IDs from the SoftwareUpdate plist
RecommendedUpdateKeys=$(/usr/bin/defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist RecommendedUpdates | awk -F'= ' '/Product Key/{print $NF}' | sed 's/"//g;s/;//g')

## Get a list of directories in /Library/Updates/ to scan through
downloadedUpdates=$(find "/Library/Updates" -maxdepth 1 -type d | sed '1d')

echo "Running check for available updates..."
check_Downloads_Vs_AvailUpdates