Checking for available macOS updates before prompting user to update

stevenjklein
Contributor II

We have a policy that uses the Software Updates payload to force users to install macOS updates.  By default it's set to run once a month, so users get prompted to install updates, but sometimes there aren't any updates to install.  So it pesters users for no reason.

Ideally, I'd prefer that the policy check for available macOS updates, and only prompt the user if updates are available.  Is anyone already doing this? If so, how?

If there isn't an existing solution, I'll try and create my own. I've been thinking about how to best accomplish this.

Perhaps using two policies, like so:

Policy #1 would run daily and check for updates using whatever method works (perhaps this):

softwareupdate -l

If Policy #1 finds an update, it would use a custom trigger to run policy #2, which would force an update using the Software Updates payload.  (I would allow users to defer it for x days, (where x is a number chosen by our security team).

Advice (and constructive criticism) welcome and appreciated.

10 REPLIES 10

mm2270
Legendary Contributor III

If you're going to run a softwareupdate -l command daily on your Macs, then you might as well combine policy 1 and 2 into one policy. Check for updates, if any are found, prompt the user to install them. If none are found, exit silently. There's no real reason to split those up, but you can do it that way as well if you'd like.

Or you can look at one of the tools out there designed for nagging users to install available updates, like Nudge for example.

sdagley
Honored Contributor III

@stevenjklein In theory that's a good approach, but there's a failure mode in sofwtareupdate where it may never return from a request to list updates, and on Apple Silicon machines installing updates requires providing the name and password for an account with volume owner permissions and that can be a problem.

MDM commands to drive macOS updates are currently best described as unreliable, and it remains to be seen if macOS Ventura improves that. Even if that's the case there remains the issue that Jamf doesn't seem to recognize the ability to schedule those MDM commands as if they were a Policy would be a Very Good Thing™, and suggests using the Jamf API to trigger MDM update commands. That unfortunately doesn't help those of us where security policies prevent the use of the Jamf API from individual endpoints.

sdagley
Honored Contributor III

Here's a Q&D script I use to look for the availability of a specific update that tries to work around the case of a "stuck" sofwtareupdate process:

 

 

#!/bin/sh

SoftwareUpdatePList="/Library/Preferences/com.apple.SoftwareUpdate.plist"

UpdateLookingFor="macOS Monterey 12.6"

UpdateIsAvailable=$(/usr/bin/defaults read "$SoftwareUpdatePList" RecommendedUpdates | grep "$UpdateLookingFor")
if [ -n "$UpdateIsAvailable" ]; then
	echo "$UpdateLookingFor is available"
else
	echo "Update was not found - resetting softwareupdate"
	/bin/rm "$SoftwareUpdatePList"
	/bin/launchctl kickstart -k system/com.apple.softwareupdated

	sleep 15
	/usr/sbin/softwareupdate --list &
	sleep 120

	UpdateIsAvailable=$(/usr/bin/defaults read "$SoftwareUpdatePList" RecommendedUpdates | grep "$UpdateLookingFor")
	if [ -n "$UpdateIsAvailable" ]; then
		echo "Reset successful - $UpdateLookingFor now is available"
	else
		echo "Reset unsuccessful - Update still not found"
		exit 1
	fi

fi

exit 0

 

 

@sdagley Your script would require manual updates every time Apple releases an update.

After I posted my question yesterday, I came up with a better method, but I'm still not where I want to be.

We allow users to run the current and previous major releases of macOS.  So I've created a Smart Group called Macs needing macOS updates with these criteria:

 

Operating System Version is Like 12. and Operating System Version is Not 12.6

OR

Operating System Version is Like 11. and Operating System Version is Not 11.7

 

Then I scoped my "force update" policy to that smart group.  Now only Macs needing updates nag users to update.

Of course, like your script, this Smart Group would require frequent manual maintenance.

My real goal is to avoid having to manually do anything: Users who are out of date would get prompted  (read: Forced) to update, but nobody else will.  Given the bugs in sofwtareupdate that you describe, my goal may be unobtainable.

mm2270
Legendary Contributor III

With @sdagley 's script, the 

UpdateLookingFor

variable can be a script parameter instead of hardcoded, which would make it a little easier to manage going forward, but would still require some hand holding as new updates appear. But at least the script itself would not need to be modified.

sdagley
Honored Contributor III

@stevenjklein Every time Apple releases a macOS update it has to be qualified for my environment so the amount of time required to manually modify the script for the new version is insignificant. I think the game Jenga must have been invented by an IT engineer to represent the process of qualifying an OS upgrade with all of the various 3rd party tools Enterprise orgs are likely to require.

donmontalvo
Esteemed Contributor II

FWIW we've been advised by Apple to use the MDM method of enabling users to run Software Updates through the prefs pane. Seems to be more reliable than the old school method of building policies to do it.

--
https://donmontalvo.com

I have been looking for this in my MDM...not JAMF fyi.  what specific payload did Apple say would allow them to install updates as standard users?

rjturner
New Contributor

@stevenjklein I run this script at login to check for updates and if any are found a message is displayed to users, then the software update System Preferences pane is opened. If no updates are found, the script will exit with no user interaction.

This works best for minor updates, in my environment major updates are delayed until full testing is completed.

 

#!/bin/sh

if softwareupdate -l | grep -q "Software Update found the following" ;
then

# Get the logged in username
loggedInUser=$( scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ { print $3 }' )
uid=$(id -u "$loggedInUser")

## Description passed in from parameter set in the policy
Title="$4"
Header="$5"
Desc="$6"

## The new message variable passed to jamfHelper
titleMSG=$( printf "$Title" )
headerMSG=$( printf "$Header" )
descMSG=$( printf "$Desc" )

JAMFHELPER="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"

RESULT=`"$JAMFHELPER" -windowType utility -icon "/Users/$loggedInUser/Library/Application Support/com.jamfsoftware.selfservice.mac/Documents/Images/brandingimage.png" -title "$titleMSG" -heading "$headerMSG" -description "$descMSG" -button1 "Install"`


if [ $RESULT == 0 ]; then
    open /System/Library/PreferencePanes/SoftwareUpdate.prefPane
fi

else exit 0;
fi

 

  

donmontalvo
Esteemed Contributor II

Pretty sure Apple advises to not use this command anymore...

softwareupdate -l

 

--
https://donmontalvo.com