Skip to main content

Worklet: macOS Deferred Reboot


Forum|alt.badge.img

The purpose of this worklet is to detect if a macOS device is pending a reboot and will notify the user to reboot. If the user does not reboot within your given timeframe, the script will force a reboot.


If the macOS device is at the login window (no user logged in), the device will reboot immediately with no notification.


Example Notification:

Screen Shot 2020-04-29 at 6.30.52 AM


The Reboot Now button does just that, it reboots immediately

The Later button will close the notification and redisplay again based on what you have set (below)


You can set the following options in the Remediation script below:

title - The Title of the notification

message - The message content (use %TIME% in your message to display the time left in minutes

forceRebootIn - The amount of minutes until the macOS device is force rebooted

notifyInterval - Show the above notification every X minutes until a reboot occurs

notifyTimeout - How long the above notification shows on the screen before closing and assuming a deferral

iconFile - Upload a .icns file to the worklet and specify it’s name here


I’ve attached the Automox icns file you see in typical Automox notifications if you want to keep the branding of patching notifications consistent, but feel free to make your own icns file. I found this thread to be a good resource:



Evaluation:


#!/bin/bash



# if either of these paths exist, a macOS Update or a macOS Security Update will install on reboot

if [[ -d "/Volumes/macOS Base System" || -d "/Volumes/OS X Base System" ]]; then

	return 1

fi


Remediation:


#!/bin/bash



# SET YOUR OPTIONS HERE

title="Security Updates"

message="Security updates will install on next reboot.  Your computer will automatically reboot in %TIME% minutes"

forceRebootIn=90 # number of minutes until a reboot is forced

notifyInterval=15 # send notification ever X minutes

notifyTimeout=30 # number of seconds to show notification (required to force Reboot)

iconFile="automox.icns" #optional: this name must match the .icns file attached to your worklet





#CONSTANTS

iconFilePath="$(pwd | sed -E 's/^\///g;s/\//:/g'):${iconFile}"

console_user=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name 😕 && ! /loginwindow/ { print $3 }')

console_user_gui=$(dscl . read /Users/$console_user UniqueID | awk '{print $2}')





function notificationResponse() {

local osaResult



osaResult=$(launchctl asuser "${console_user_gui}" osascript << EOT

display dialog "${message//%TIME%/${time}}" with title "${title}" buttons {"Reboot Now", "Later"} default button {"Later"} giving up after ${notifyTimeout} ${addIcon}

EOT

)

	awk -F "[:|,]" '{print $2}' <<< "${osaResult}"

}



function rebootNow() {

	local notify=$1



	if [[ -z "${console_user}" ]]; then

		# echo "reboot NOW"; exit 0

		launchctl reboot system

	elif [[ ${notify} -eq 1 ]]; then

		launchctl asuser "${console_user_gui}" osascript -e \

		"display dialog \"Your system will reboot now\" with title \"${title}\" buttons {\"Ok\"} giving up after ${notifyTimeout} ${addIcon}"

		# echo "reboot NOW"; exit 0

		launchctl reboot system

	else

		# echo "reboot NOW"; exit 0

		launchctl reboot system

	fi

}



function notifyUser() {

	time=${forceRebootIn}



	while [[ ${time} -gt 0 ]]; do

		# send notification

		if [[ "$(notificationResponse)" == "Reboot Now" ]]; then

			rebootNow 0

		else

			time=$(( time - notifyInterval ))

			echo "reboot deferred"

			sleep $(( notifyInterval * 60 ))

		fi

	done



}



# Check for pending reboot

if [[ -d "/Volumes/macOS Base System" || -d "/Volumes/OS X Base System" ]]; then

	

	# Set icon file if set

	if [[ -n "${iconFile}" ]]; then

		addIcon="with icon alias \"${iconFilePath}\""

	fi





	if [[ -z "${console_user}" ]]; then

		echo "No console user detected, rebooting now"

		rebootNow 0

	else

		notifyUser

		rebootNow 1

	fi

fi



4 replies

  • 0 replies
  • July 21, 2020

I see it says that you attached the icns file but I don’t see it.


The frowny smile in line 27 should be colon slash:

console_user=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ { print $3 }')


sparrowhawk
Forum|alt.badge.img
  • Novice
  • 31 replies
  • September 15, 2023

Is this actually working for everyone?

 


sparrowhawk
Forum|alt.badge.img
  • Novice
  • 31 replies
  • September 15, 2023

The script seems to be triggered and returns a value of 1, but my users are saying they aren’t seeing any notifications. Should the policy be set to force a restart or not?


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings