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:
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
i -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 i -z "${console_user}" ]]; then
# echo "reboot NOW"; exit 0
launchctl reboot system
elif li ${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 il ${time} -gt 0 ]]; do
# send notification
if i "$(notificationResponse)" == "Reboot Now" ]]; then
rebootNow 0
else
time=$(( time - notifyInterval ))
echo "reboot deferred"
sleep $(( notifyInterval * 60 ))
fi
done
}
# Check for pending reboot
if
i -d "/Volumes/macOS Base System" || -d "/Volumes/OS X Base System" ]]; then
# Set icon file if set
if i -n "${iconFile}" ]]; then
addIcon="with icon alias \"${iconFilePath}\""
fi
if i -z "${console_user}" ]]; then
echo "No console user detected, rebooting now"
rebootNow 0
else
notifyUser
rebootNow 1
fi
fi