Script for warning users of impeding reboot multiple times.

aalberty
New Contributor III

Goal: A policy to force minor OS updates, then run a script alerting the end user twice that a reboot is required. The second alert is locked on screen. If the user does not interact with the script, the machine will reboot in 4 hours and successfully complete the policy. If the user force quits the second warning (cmd + q), the machine immediately reboots and successfully completes the policy. If the user manually reboots their machine, the policy is successfully completed.

Script:

#!/bin/sh  
jamf displayMessage -message "Minor OS updates have been installed and your machine will reboot in 4 hours. It is recommended that you save your work and reboot immediately to prevent loss of work."
sleep 12600
/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -title "Reboot" -description "Your machine will reboot at $(date -v +30M). Please ensure all work is saved and restart within the next 30 minutes. Attempting to force quit (CMD + Q) will result in your machine restarting IMMEDIATELY."  -lockHUD -timeout 1800
jamf reboot -immediately

As you can see, the user has 4 hours to reboot. The first message displays and immediately starts a 3h30 sleep (key point is that it doesn't wait for them to click OK to start the "timer"). Then a jamfHelper displays for 30 minutes warning users that they are about to reboot. With this code, if the user clicks OK to the initial warning and then has no further interaction with the script (i.e. let the second warning sit on screen for 30 minutes), then the script completes, and the policy is marked in JSS as completed.

The issue: If the user manually reboots at any point while the script is running, the script does NOT complete, which means (since no exit code 0) the policy remains as pending in the JSS. This gets the user stuck in a loop of the policy happening over and over again. If the user force quits (cmd + q) the 30 minute warning, it appropriately reboots the machine, however without exit code 0, and therefore the policy remains at pending in the JSS and the policy loop happens.

I've tried just using jamf reboot -minutes 30 -message "blah blah blah" -background, but I don't like this for two reasons; firstly, it reboots 30 minutes from acknowledging the message, and secondly, you can force quit the message. Granted, the message will continue popping up if you force quit it, but there is potential to just leave the message alone indefinitely and not reboot at all. Due to this, I would like to keep the jamf reboot -immediately portion.

If someone could help point me toward a method of getting the script to return an exit code 0 when the second warning is force quit, or the user manually reboots the machine at any point while the script is running, I believe this would resolve my issues. Any help is deeply appreciated!

1 ACCEPTED SOLUTION

aalberty
New Contributor III

@mm2270 Thanks for that link! That looks like a really useful tool. I've been tinkering this morning, and think I've got a solution.

  1. A policy to force minor updates and runs CALL REBOOT script shown below.

  2. A policy with a custom trigger called "Reboot" that runs REBOOT script shown below.

CALL REBOOT:

#!/bin/sh
jamf policy -event "Reboot" &
exit 0

Notice the & at the end of line 2 - this makes it so that CALL REBOOT does not wait for REBOOT to finish before exiting.

REBOOT:

#!/bin/sh
jamf displayMessage -message "Minor OS updates have been installed and your machine will reboot in 4 hours. It is recommended that you save your work and reboot immediately to prevent loss of work."
sleep 12600
/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -title "Reboot" -description "Your machine will reboot at $(date -v +30M). Please ensure all work is saved and restart within the next 30 minutes. Attempting to force quit (CMD + Q) will result in your machine restarting IMMEDIATELY."  -lockHUD -timeout 1800
jamf reboot -immediately

I've tested all three cases - letting the scripts execute naturally without intervention, force quitting (cmd + q), and manually rebooting, and all three cause both policies to show "Completed", therefore not causing the end user to get caught in a policy loop. I got the idea for the two policy approach from BK's comment on this post.

View solution in original post

5 REPLIES 5

marklamont
Contributor III

why don't you split it up?
have an EA written by script 1 that scopes script 2 using a smart group then trigger it as an when you need.
have a launchD real a local attribute that both scripts set to different values to call appropriate polices or delete local attributes as required.

basically just don't rely on just jamf to sort this, use a bit of both ends in co-operation

aalberty
New Contributor III

@marklamont First off, thanks so much for the reply!

So, if I'm understanding your response, you're recommending something along the lines of:
1. Put an attribute on all end user machines that has two states; "needs reboot" and "done rebooting" for instance.
2. Have a policy in Jamf to force minor OS updates, and run a script that switches the attribute to "needs reboot".
3. Have a smart group in Jamf containing all machines with the attribute set to "needs reboot".
4. Have a second policy in Jamf scoped to the smart group from (3) that runs my reboot script from above, with the addendum of switching the attribute to "done rebooting".

Follow up question for you then - I'm not familiar with how to make attributes like this, and looking through the advanced criteria for smart groups in Jamf, I'm not seeing anything that suggests to me it can look at the state of an attribute on a machine. Would it be along the lines of a daemon that appears as a Local User Account and gets killed when the reboot script runs?

mm2270
Legendary Contributor III

@aalberty While it may be a little overkill for your purposes, you can take a look at an old script I put together which may help you get where you're looking to go with this, called "reboot_scheduler". You can find the script here: reboot_scheduler.sh
The script itself has a lot of comments and information in it on how to use it, but if you decide to try it and have any questions, be sure to post back and mention me so I can jump back in to help.

aalberty
New Contributor III

@mm2270 Thanks for that link! That looks like a really useful tool. I've been tinkering this morning, and think I've got a solution.

  1. A policy to force minor updates and runs CALL REBOOT script shown below.

  2. A policy with a custom trigger called "Reboot" that runs REBOOT script shown below.

CALL REBOOT:

#!/bin/sh
jamf policy -event "Reboot" &
exit 0

Notice the & at the end of line 2 - this makes it so that CALL REBOOT does not wait for REBOOT to finish before exiting.

REBOOT:

#!/bin/sh
jamf displayMessage -message "Minor OS updates have been installed and your machine will reboot in 4 hours. It is recommended that you save your work and reboot immediately to prevent loss of work."
sleep 12600
/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -title "Reboot" -description "Your machine will reboot at $(date -v +30M). Please ensure all work is saved and restart within the next 30 minutes. Attempting to force quit (CMD + Q) will result in your machine restarting IMMEDIATELY."  -lockHUD -timeout 1800
jamf reboot -immediately

I've tested all three cases - letting the scripts execute naturally without intervention, force quitting (cmd + q), and manually rebooting, and all three cause both policies to show "Completed", therefore not causing the end user to get caught in a policy loop. I got the idea for the two policy approach from BK's comment on this post.

joe_adu
New Contributor

@aalberty this looks pretty neat and is something I'm looking to do in my environment. Can you walk me through how you have these two scripts integrated with OS update policies? Do you still have a restart payload configured within the OS update policy. I'd like to implement this with my pre-existing MacOS update policy.
Thanks,
Joe