Posted on 01-15-2020 02:16 AM
Hi guys
I'm trying to get our Macs a bit more up to date and uniform, since they've gone virtually unmanaged for quite a while.
I made a policy to install software updates from Apple's software update server. The restart option is selected to restart if a package or update requires it, and the user gets a restart message with the specified delay before the restart.
Is it possible to give the user the option to delay this restart? For example giving them a message with the choice between 'restart now' and 'restart later' (with a later time specified).
I know I can allow users to defer the policy, but is this possible for the restart as well?
Thanks!
Solved! Go to Solution.
Posted on 01-16-2020 09:55 AM
I think it might be better to check if updates require a restart before installing them. If the updates require a restart and there is a user logged in, you could prompt the user to make a choice:
This would also allow you to install updates that do not require a restart without bothering the user. It may require some tweaking depending on exactly what/when/how you want things to happen in your environment. You could install updates, then present the user with a jamfHelper with a timer. You could follow-up on systems after a certain point with a version of this script that does not give them an option to cancel/decline but instead just waits for them to acknowledge that a restart will occur once they click OK. Lots of possibilities.
#!/bin/bash
#---VARIABLES---------------------------------------------------------------------------
JAMFHELPER="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
ICON="/System/Library/CoreServices/Software Update.app/Contents/Resources/SoftwareUpdate.icns"
#---FUNCTIONS---------------------------------------------------------------------------
#---------------------------------------------------------------
# getConsoleUsername
# Returns the current console user. An empty return means no one
# is logged in.
#---------------------------------------------------------------
getConsoleUsername()
{
/usr/bin/python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser
user = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]
user = [user,""][user in [u"loginwindow", None, u""]]
print(user)'
}
#---------------------------------------------------------------
# promptRestartMessage
# Prompts user to acknowledge that a restart is required to
# finish installing software updates
#---------------------------------------------------------------
promptRestartMessage()
{
local _window_type _title _heading _description _button1 _default_button
_window_type="utility"
_title="Apple Software Updates"
_heading="Restart Required"
_description="Your computer needs to install Apple software updates that require a restart to complete. Please save all work and click Restart."
_button1="Restart"
_button2="Cancel"
_default_button="1"
_cancel_button="2"
echo "Prompting user to restart"
"$JAMFHELPER"
-windowType "$_window_type"
-title "$_title"
-icon "$ICON"
-heading "$_heading"
-description "$_description"
-button1 "$_button1"
-button2 "$_button2"
-defaultButton "$_default_button"
-cancelButton "$_cancel_button"
}
#---------------------------------------------------------------
# displayRestartReminder
# Displays a persistent dialog as a reminder to the user that
# their system will be restarting to install updates soon
#---------------------------------------------------------------
displayRestartReminder()
{
local _window_type _window_position _title _description
_window_type="hud"
_window_position="ur"
_title="Restart Pending"
_description="Apple software updates are being installed and your system will restart soon."
echo "Displaying restart reminder"
"$JAMFHELPER"
-windowType "$_window_type"
-windowPosition "$_window_position"
-lockHUD
-icon "$ICON"
-title "$_title"
-description "$_description" &
}
#---START SCRIPT------------------------------------------------------------------------
echo "Checking if a restart is required"
# Check if any updates require a restart to complete. The '[restart]' string exists on
# lines for updates that require a restart. The redirect 2>&1 is used to ensure all
# output from the softwareupdate command is sent the same way for the if evaluation
# because softwareupdate uses stderr for some reason for non errors (Don't ask me why).
# If no updates require a restart, all updates will install without user approval.
if [[ "$(/usr/sbin/softwareupdate --list 2>&1)" =~ '[restart]' ]]; then
echo "Restart is required"
# Check if a user is logged in to be able to accept or decline the restart.
# If no user is logged in, the updates will install without user approval.
if [ -n "$(getConsoleUsername)" ]; then
echo "A user is logged in"
# Prompt the user to accept the restart or cancel the updates
if promptRestartMessage; then
echo "User accepted restart"
# Display a window reminding the user that a restart will occur soon
displayRestartReminder
# Exit clean if the user chose to not accept the restart
else
echo "User did not accept restart"
exit 0
fi
# Log the fact that no user is logged in
else
echo "No one is logged in"
fi
# Log the fact that no updates require a restart
else
echo "No updates require a restart"
fi
# Install all updates with the --restart flag which will
# restart the system if any updates require a restart
/usr/sbin/softwareupdate --install --all --restart
exit 0
Posted on 01-15-2020 03:41 AM
There is an option to allow the user to defer the policy from running, but I don't think they can defer the reboot once the update is installed.
On an other note, if you have T2 Macs, be careful not to have the Jamf policy send a reboot command. The Mac gets stuck in a loop and won't boot. T2 Macs need to have a shutdown command instead, and they power back on by themselves.
Posted on 01-15-2020 10:51 PM
Good to know! That's mostly the newer Macs, right?
So using the restart option Jamf provides isn't really an option? How bad would it be to have the restart option in the policy set to 'do not reboot', so the user can reboot when possible (but then having to rely on their goodwill). For example after installing a security update, which requires a reboot, but not having the policy reboot.
I've only recently switched to having to manage Mac instead of Windows, so a lot of things I'm still figuring out.
Posted on 01-16-2020 09:55 AM
I think it might be better to check if updates require a restart before installing them. If the updates require a restart and there is a user logged in, you could prompt the user to make a choice:
This would also allow you to install updates that do not require a restart without bothering the user. It may require some tweaking depending on exactly what/when/how you want things to happen in your environment. You could install updates, then present the user with a jamfHelper with a timer. You could follow-up on systems after a certain point with a version of this script that does not give them an option to cancel/decline but instead just waits for them to acknowledge that a restart will occur once they click OK. Lots of possibilities.
#!/bin/bash
#---VARIABLES---------------------------------------------------------------------------
JAMFHELPER="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
ICON="/System/Library/CoreServices/Software Update.app/Contents/Resources/SoftwareUpdate.icns"
#---FUNCTIONS---------------------------------------------------------------------------
#---------------------------------------------------------------
# getConsoleUsername
# Returns the current console user. An empty return means no one
# is logged in.
#---------------------------------------------------------------
getConsoleUsername()
{
/usr/bin/python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser
user = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]
user = [user,""][user in [u"loginwindow", None, u""]]
print(user)'
}
#---------------------------------------------------------------
# promptRestartMessage
# Prompts user to acknowledge that a restart is required to
# finish installing software updates
#---------------------------------------------------------------
promptRestartMessage()
{
local _window_type _title _heading _description _button1 _default_button
_window_type="utility"
_title="Apple Software Updates"
_heading="Restart Required"
_description="Your computer needs to install Apple software updates that require a restart to complete. Please save all work and click Restart."
_button1="Restart"
_button2="Cancel"
_default_button="1"
_cancel_button="2"
echo "Prompting user to restart"
"$JAMFHELPER"
-windowType "$_window_type"
-title "$_title"
-icon "$ICON"
-heading "$_heading"
-description "$_description"
-button1 "$_button1"
-button2 "$_button2"
-defaultButton "$_default_button"
-cancelButton "$_cancel_button"
}
#---------------------------------------------------------------
# displayRestartReminder
# Displays a persistent dialog as a reminder to the user that
# their system will be restarting to install updates soon
#---------------------------------------------------------------
displayRestartReminder()
{
local _window_type _window_position _title _description
_window_type="hud"
_window_position="ur"
_title="Restart Pending"
_description="Apple software updates are being installed and your system will restart soon."
echo "Displaying restart reminder"
"$JAMFHELPER"
-windowType "$_window_type"
-windowPosition "$_window_position"
-lockHUD
-icon "$ICON"
-title "$_title"
-description "$_description" &
}
#---START SCRIPT------------------------------------------------------------------------
echo "Checking if a restart is required"
# Check if any updates require a restart to complete. The '[restart]' string exists on
# lines for updates that require a restart. The redirect 2>&1 is used to ensure all
# output from the softwareupdate command is sent the same way for the if evaluation
# because softwareupdate uses stderr for some reason for non errors (Don't ask me why).
# If no updates require a restart, all updates will install without user approval.
if [[ "$(/usr/sbin/softwareupdate --list 2>&1)" =~ '[restart]' ]]; then
echo "Restart is required"
# Check if a user is logged in to be able to accept or decline the restart.
# If no user is logged in, the updates will install without user approval.
if [ -n "$(getConsoleUsername)" ]; then
echo "A user is logged in"
# Prompt the user to accept the restart or cancel the updates
if promptRestartMessage; then
echo "User accepted restart"
# Display a window reminding the user that a restart will occur soon
displayRestartReminder
# Exit clean if the user chose to not accept the restart
else
echo "User did not accept restart"
exit 0
fi
# Log the fact that no user is logged in
else
echo "No one is logged in"
fi
# Log the fact that no updates require a restart
else
echo "No updates require a restart"
fi
# Install all updates with the --restart flag which will
# restart the system if any updates require a restart
/usr/sbin/softwareupdate --install --all --restart
exit 0
Posted on 01-17-2020 12:10 AM
Oh wow, thanks so much for the script! I'll be testing it out next week, but from what I read, it's exactly what I need!
Posted on 01-20-2020 03:44 AM
@ChrisCox
I've been testing the script, and it seems to work fine, thanks!
Just one more question about it:
If the software update requires rebooting, it gives the user the prompt informing them. After they agree to the reboot, the update starts downloading and installing. For a bigger update, this can take quite some time. Is there any way to download first, and then prompt the user for installation/reboot?
Posted on 01-20-2020 06:29 AM
Yes, you could just add the following line before prompting.
/usr/sbin/softwareupdate --download --all
Posted on 01-20-2020 06:30 AM
Oh wow yes, silly I didn't think of that myself. Thanks for the help!
Posted on 01-30-2020 11:02 AM
I thought I should update this with something I just discovered. In Catalina, updates that require a reboot no longer have the []
surrounding them. In the if regex evaluation, [restart]
should be changed to just restart
to be compatible with Mojave and Catalina.
Posted on 02-10-2020 06:01 AM
Thanks @ChrisCox ! I'd been seeing some issues with this policy in Catalina.
I have changed the if regex evaluation, but the main issue still exists. On the Catalina devices however, the prompt to reboot now/later doesn't appear anymore and the device just starts rebooting. I haven't had time to look into this properly, but I'm hoping to find some time for it this week.
Posted on 08-24-2020 05:04 AM
Exact what I am looking for - but any support for Catalina at the moment ?
Posted on 04-29-2021 11:53 AM
@ChrisCox
I tried it on Big Sur, and it did run but didn't notice any of the prompts. Thoughts?
Thanks for the awesome script though!
Posted on 04-30-2021 06:24 AM
You might want to take a look at: https://github.com/mpanighetti/install-or-defer