Scheduling rebooting of machines

tegus232
Contributor

I have seen bunch of scripts online but if someone has a working script which can deploy will be very helpful.

I am looking a script which checks the last reboot of the machines. Then it would check if the reboot occurred less than 7 days or not. If the user hasn't rebooted for more than 7 days, the script will restart their machines. They will receive a popup that their laptop will be restarting and also allows them to extend the time by few hours before the laptop restarts.

28 REPLIES 28

xavier_burns
New Contributor

I am very interested in this as well - lack of reboots has been problematic in our enterprise.

shaquir
Contributor III

Hi @tegus232 ,
I'd start with the following Extension Attribute to check the last day the machine was rebooted. Make sure to set the Data Type to Date Format.

#!/bin/bash
#https://www.jamf.com/jamf-nation/discussions/10009/uptime-or-last-shutdown-restart#responseChild55774
echo "<result>$(date -jf "%s" "$(sysctl kern.boottime | awk -F'[= |,]' '{print $6}')" +"%Y-%m-%d %T")</result>"

Then I'd create a Smart Group to check for machines that have not rebooted in over 7 days

54d1f7d893d841b5bb7ab64549a26097

I'd then set a policy to run a script like below to the user's machine.

Jamf Helper Reboot Script with Deferral

(You could probably bypass the EA creation and store the script natively on user's machines. You could call it via a Launch Agent, but I personally prefer Jamf handling the script deployment)

I have not tested this workflow.

jschank
Contributor

How did you get Criteria "Uptime"

sdagley
Esteemed Contributor II

@jschank The first part of @shaquir's post is an Extension Attribute (EA) to collect the info from a Mac during inventory, and he named the EA Uptime. When you're creating a Smart Group, click the Show Advanced Criteria button when adding Criteria, and you will then see all of the EAs being collected by your JSS.

atomczynski
Valued Contributor

Here is what I have...
The Mac Admin community has been helpful and I got this working.

With this, the user has the option to select time of restart, or cancel.

#!/bin/bash

###################
### Adam T.
### April 16, 2020
### This is a JamfHelper Script which will be used to notify user if they have not restarted the computer in 7 days
### This script will give the user options how to proceed (now, 1 min, 5 min, 30 min 1 hr, 2 hrs as an example)
### This is needed as staff members tend not to restart their computers often
### This script is called from another script that checks uptime
##################
### Using Jamf Helper is cool
#################



#Message type variables below

#Utility window gives a white background
window="utility"
title="Replace this text to enter the title of the notification"
heading="Please restart your computer (modify as needed)"
description="Your computer has not been restarted in at least seven days. A more frequent restart is recommended.

Doing so optimizes the performance of your computer as well as allows us to deploy security updates or new applications to you automatically.

Please restart now."

icon="/System/Library/CoreServices/Software Update.app/Contents/Resources/SoftwareUpdate.icns"




selection=$("/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper" -windowType "$window" -title "$title" -heading "$heading" -description "$description" -icon "$icon" -button2 "Restart"  -showDelayOptions "0, 60, 300, 3600, 7200" -button1 "Cancel" -cancelButton 1)

buttonClicked="${selection:$i-1}"
timeChosen="${selection%?}"

## Convert seconds to minutes for restart command
timeMinutes=$((timeChosen/60))

## Echoes for troubleshooting purposes
echo "Button clicked was: $buttonClicked"
echo "Time chosen was: $timeChosen"
echo "Time in minutes: $timeMinutes"

if [[ "$buttonClicked" == "2" ]] && [[ ! -z "$timeChosen" ]]; then
    echo "Restart button was clicked. Initiating restart in $timeMinutes minutes"
    shutdown -r +${timeMinutes}
elif [[ "$buttonClicked" == "2" ]] && [[ -z "$timeChosen" ]]; then
    echo "Restart button was clicked. Initiating immediate restart"
    shutdown -r now
elif [ "$buttonClicked" == "1" ]; then
    echo "Cancel button clicked. Exiting..."
    exit 0
fi


exit

Hey @atomczynski I do not see the logic where the script checks for the 7 days

sdagley
Esteemed Contributor II

@Anton The script doesn't check for uptime, that's done via an Extension Attribute to report Uptime and a Smart Group to determine if the value of Uptime is more than 7 days which is used to scope a Policy which runs the script above.

ejadadic
New Contributor III

Is there a way to run a launch daemon every 8 hours?

sdagley
Esteemed Contributor II

@ejadadic Use a <key>StartInterval</key> with <integer>28800</integer> as the value in your LaunchDaemon .plist.

And here's a handy web site for creating schedules for a LaunchDaemon: https://zerolaunched.herokuapp.com 

ejadadic
New Contributor III

Thank you for that information, can I simply input that in the script itself or compose the script and launchagent into a package?

sdagley
Esteemed Contributor II

@ejadadic The StartInterval goes into your LaunchDaemon .plist. It doesn't matter if you have a wrapper script that writes out the LaunchDaemon and the script it's going to call, or if you have a .pkg install the LaunchDaemon and script.

ejadadic
New Contributor III

Thank you for that information 

I've been getting some issues on devices trying to restart

Shutdown at Thu Apr 14 00:09:23 2022.
shutdown: can't detach from console

Hi 

Q about the script that is working perfectly,
In the defer options - can I change the Start now option to Reboot now?

 

sdagley
Esteemed Contributor II

@atomczynski Be aware that by using shutdown -r now the Policy running this script will never get logged since it'll kill the jamf agent before it can log completion with your JSS.

beeboo
Contributor
shutdown -r +1 &

i use that at the end of my OS upgrade script
seems to give it enough time to let JSS know of the results (note, not doing a recon or anything)
that way a user doesnt get prompted multiple times to run the policy before a recon kicks in and theres no point running a recon before the upgrade as i need the new upgrade info post reboot.

KMak84
Contributor

This is great.
The only issue I am experiencing is, the delay option does not seem to work, my checkin is every minutes, if I select anything greater than 15 min in the script it will re run the script on checkin
Any suggestions to get around this

beeboo
Contributor

every how many minutes?
Ours is set to 30 min and its fine, but it also depends on what you want to do.

Occasionally we see this when it comes to large downloads like OS or when a user has a slow internet connection, but my understanding is that when a script is running it wont prompt you again, UNLESS its waiting for your confirmation (we have cases when we auto kick off policy in X minutes and a user might get 2 prompts).

But i could be wrong about the policy part, though logically it should make sense.

techmchs
New Contributor III

Question.. do you need to set an inventory update to occur at reboot to keep this from looping? the script will only recognize the new timestamp after an inventory update.

techmchs
New Contributor III

nvm, I just added an inventory update at reboot.. thought I had that checked before..alas..

mline
New Contributor

Did you create a seperate policy for this to force a group with X amount of days to update inventory at login?

david_maestre
New Contributor III

I recently put this one together but I feel like it's not working exactly how I want. It detects the first portion of over 10 days but not the 14. I think it's canceling itself out. Feel free to share some input to make this better. 

 

Maybe I should put the higher integer first? 

 

#!/bin/sh

########################################
#
# A+E Reboot 2.0 script by David Maestre
#
# Detects machine uptime and uses logic to engage secondary policy.
# 1. Reboot prompt to remind user to restart machine soon.
# 2. Force reboot machine prompt when they surpass 14 days uptime.
# 3. Machine compliant, policy zeros out and exits. User never disturbed.
#
#######################################

# Check if the last reboot was more than 10 days ago
last_reboot=$(sysctl -n kern.boottime | awk -F'[ ,]' '{print $5}')
current_time=$(date +%s)
elapsed_time=$(uptime | awk {'print $3'} | sed 's/,/ /g' | sed 's/d/ d/g')
int1="10"
int2="14"

# Check to see if reboot is required

if [ $elapsed_time -gt $int1 ]; then

	echo "over 10 days - reboot policy engaged"
	/usr/local/bin/jamf policy -event restart-reboot-prompt

elif [ $elapsed_time -gt $int2 ]; then

	echo "over 14 days - forcing restart"
	/usr/local/bin/jamf policy -event force-reboot-prompt
	
else
echo "Machine is Reboot Compliant"
exit 0
fi

 

 

Yup, that did the trick I believe. I flipped the IF statements to have the higher integer first. Now it's working as it should. 

Feel free to use/test in your environment.

egusman
New Contributor II

Tried every script possible but none seem to work. 

@egusman I used @atomczynski's script above. We haven't implemented a 7-day reboot policy yet but wanted to make sure I had something ready. When I tested it, everything worked fine. After my device was online for over 7 days it fell into a smart group which I have my policy scoped to. 
I was able to delay it if I wanted to or reboot it. I did change the delay options times in the script. 

#!/bin/bash

###################
### Adam T.
### April 16, 2020
### This is a JamfHelper Script which will be used to notify user if they have not restarted the computer in 7 days
### This script will give the user options how to proceed (now, 1 min, 5 min, 30 min 1 hr, 2 hrs as an example)
### This is needed as staff members tend not to restart their computers often
### This script is called from another script that checks uptime
##################
### Using Jamf Helper is cool
#################



#Message type variables below

#Utility window gives a white background
window="utility"
title="Reboot Needed"
heading="IMPORTANT: A system reboot is required.  Please close all applications and restart your computer."
description="Your computer has not been restarted in at least seven days. A more frequent restart is recommended.
Doing so optimizes the performance of your computer as well as allows us to deploy security updates or new applications to you automatically. 

To prevent receiving this message in the future, please reboot your computer at least once per week.
NOTE: Use the dropdown below to select a time of when you want to reboot then click Restart. Your device will reboot automatically based on the time you selected."

icon="/System/Library/CoreServices/Finder.app/Contents/Resources/Finder.icns"




selection=$("/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper" -windowType "$window" -title "$title" -heading "$heading" -description "$description" -icon "$icon" -button1 "Restart"  -showDelayOptions "0, 60, 3600, 7200, 14400, 28800")
## The Original line below
#selection=$("/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper" -windowType "$window" -title "$title" -heading "$heading" -description "$description" -icon "$icon" -button2 "Restart"  -showDelayOptions "0, 60, 3600, 7200, 14400, 28800" -button1 "Cancel" -cancelButton 1)

buttonClicked="${selection:$i-1}"
timeChosen="${selection%?}"

## Convert seconds to minutes for restart command
timeMinutes=$((timeChosen/60))

## Echoes for troubleshooting purposes
echo "Button clicked was: $buttonClicked"
echo "Time chosen was: $timeChosen"
echo "Time in minutes: $timeMinutes"

#Changed Line 49 and 52 from 2 to 1
if [[ "$buttonClicked" == "1" ]] && [[ ! -z "$timeChosen" ]]; then
    echo "Restart button was clicked. Initiating restart in $timeMinutes minutes"
    shutdown -r +${timeMinutes}
elif [[ "$buttonClicked" == "1" ]] && [[ -z "$timeChosen" ]]; then
    echo "Restart button was clicked. Initiating immediate restart"
    shutdown -r now
#elif [ "$buttonClicked" == "1" ]; then
    #echo "Cancel button clicked. Exiting..."
    exit 0
fi


exit

 

egusman
New Contributor II

Works perfectly well! Thanks a lot.

JL85
New Contributor III

JL85_0-1721191834555.png

I test with your script with self-service , after reboot , the status of this policy is pending not completed.

Can i know what is wrong with me?

 

bcbackes
Contributor III

Do you have the policy "Execution Frequency" set to "Ongoing". If so, that's probably why. If you have it available in Self Service for testing purposes only you can change the "Execution Frequency" to "Once per computer".

JL85
New Contributor III

The policy only for per computer once time. But i will let user  restart without immediately. 

Another thing, because i would like everything is automation executed task.

A matching Machine >  Smart Group (7days without Reboot) > Policy execute Reboot > Do Recon > Remove Smart Group. 

In the policy i put the inventory but look like machine can not have the correct uptime because user select option delay 10' minutes reboot. 

JL85_0-1721357785421.png

 sudo jamf policy

 

Checking for policies triggered by "recurring check-in" for user "test"...

Executing Policy _04.Schedule 7 days Reboot

Running script Schedule 7-days Reboot...

Script exit code: 0

Script result: Button clicked was: 1

Time chosen was: 300

Time in minutes: 5

Restart button was clicked. Initiating restart in 5 minutes

shutdown: [pid 2283]

Shutdown at Fri Jul 19 09:53:19 2024.

 

                                                                               

*** System shutdown message from test@VNHOCLT0186.local ***                  

 

System going down in 5 minutes                                                 

 

                                                                               

Checking for patches...

No patch policies were found.

Running Recon...

Retrieving inventory preferences from https://trustiq.jamfcloud.com/...

Finding extension attributes...

Locating hard drive information...

Locating accounts...

Locating applications...

Locating package receipts...

Locating software updates...

Locating printers...

Gathering application usage information from the JamfDaemon...

Searching path:

Searching path: /Library/Internet Plug-Ins

Searching path: /System/Applications

Searching path: /Applications

Locating hardware information (macOS 14.5.0)...

Submitting data to https://trustiq.jamfcloud.com/...

<computer_id>8</computer_id>

Submitting log to https://xxx.jamfcloud.com/