Need to process policy based on uptime


I'm trying to build a SMART GROUP that's based on user's machine uptime that I'm grabbing in an Extension Attribute. But apparently there's no way for me to build Smart Groups using that criteria (i.e., Machines where Extension Attribute Uptime > 5 days). For smart Group Operator values, I have only these options: is, is not, like, not like. I need some greater than, less than values in there - is there a way to do this?


Valued Contributor

You need to build and set your EA to use an integer as its result value.

Legendary Contributor II

Correct, as @iJake stated. Change the Data type for the EA to "integer". Just make sure your EA is actually submitting a proper integer - just pure numbers - and not something with text in it or you'll get odd results with your Smart Group.

Valued Contributor III

Here is one I wrote quite some time ago but it works okay.
It has a minimum value of 1 for anything less than a day.
If you make a smart group around it I advise dropping anything with an inventory older than a certain amount as well, gives a more usable set of computers especially for reporting as most of the machines without a recent inventory are more than likely switched off anyway hence the uptime will be wrong and you don't want them to apply the policy as soon as they rejoin the network and haven't yet updated the EA.

LongResult=`uptime | sed -e 's/,.*//' -e 's/^.*up *//'`
if [[ "$LongResult" =~ "days" ]] ; then
result="`echo $LongResult | cut -d" " -f1`"
echo "<result>$result</result>"


Here is what we finally decided to build. It uses Cocoa Dialog for the presentation of the message since it allows interaction, buttons, etc.

First, a Library/LaunchDaemon/ called:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">
<plist version="1.0">

Then put this in /usr/local/scripts/
file is called:

logfile=/var/log/rebooter # The Log file
bootTime=$(sysctl kern.boottime | awk '{print $5}' | tr -d ",") # When did I boot up? In seconds since Jan 1, 1970 12:00am
currentTime=$(date "+%s") # What time is it? Seconds since the epoch
upTime=$(expr $currentTime - $bootTime) # Uptime = current time minus boot time
oneDay=$(echo 60*60*24 | bc ) # How long is a day ? 60 second * 60 minutes * 24 hours
CD=/Applications/ # Where is CocoaDialog ?

currentHour=$(date "+%H") # What is the current hour?
echo $(date) Uptime: $upTime >> "$logfile" # Make some noise in the log!
if [ $upTime -gt $oneDay ] # Is our uptime at least one day? It is ain't just fall through. Move along, nothing to see here....
    daysUp=$(expr $upTime / $oneDay) # Lets figure out how many days I have been running. Do a integer divide of uptime by one day. Integer Divide leaves no remainder. Does not round, it truncates any fraction of a day.
    echo $(date) Days Up: $daysUp >> "$logfile" # Squawk in the logfile 
    if (( 5 <= $daysUp && $daysUp < 7)) # Up at least 5 days, but less than 7?
        if (( 8 < $currentHour && $currentHour < 18 )) # Is the hour greater than 8 (9 or above) and less then 6pm (5pm or below). Only warn if the user is likely to see it, otherwise, don't make a pile of warnings for the user to have to click through in the morning.
            $CD bubble --timeout 1800 --background-bottom FF0000 --icon computer --title "Computer Uptime" --text "Your computer has been up at least $daysUp days. You must reboot."  # Warn User

    if ((7 <= $daysUp && $daysUp < 8 )) # Is days up equal to 7 or greater, but less that 8? (On the 7th day)
        currentHour=$(date "+%H")

        if (($currentHour >= 19)) # Is the current hour greater that 7pm
            rebootTime=$(date -v +15M "+%H:%M") # After 7pm, get a time in the future by fifteen mintues
            $CD bubble --timeout 900 --background-bottom FF0000 --icon computer --title "Computer Reboot Scheduled" --text "Computer will reboot at $rebootTime. Click this window to reboot now." # Tell the user we are going to reboot them in 15 minutes... This Dialog will timeout in 15 minutes (60 seconds * 15 = 900 seconds). Blocks until time out of until user clicks dialog
            reboot # Do the deed
            $CD bubble --timeout 1800 --background-bottom FF0000 --icon computer --title "Computer Reboot Required" --text "Computer will be force rebooted after 5:00PM today. Please reboot." # Not after 7:00pm, give a warning we will reboot after 5 today... 

    if (( $daysUp >= 8 )) # It is 8 days or more... we no longer care what time of the day it is.
        rebootTime=$(date -v +15M "+%H:%M") # Get the time of 15 minutes in the future
        $CD bubble --timeout 900 --background-bottom FF0000 --icon computer --title "Computer Reboot Scheduled" --text "Computer will reboot at $rebootTime. Click this window to reboot now." # Tell user blah blah blah
        reboot # do the deed

#Keep log under control
tail -n 100 "$logfile" > /private/tmp/temprebooter # take the last 100 lines in the logfile and put it into a temp file
mv /private/tmp/temprebooter "$logfile" # move the tempfile back to logfile, overwritting it. this ensures the log will not grow over 100 lines. Keeps size manageable and still useful.

sleep 10 # We MUST stay running for a bit of time, otherwise LaunchD will think we are broken. Sleep a bit, have a drink, relax. 5 seconds is probably enough, but seconds of sleep don't cost nothing. I am feeling generous.

Thank you to my counterpart Ernie for doing the hard coding.

This has been great as a V1 script.

We're now considering to check whether the machine is on the VPN or Wired/Wireless network and presenting the information relevant to that too, as for us, rebooting on the WIRED network allows for much more two-way interaction than a simple reboot when home. This could allow us to trigger certain installs to cache prior to the next reboot on or off the network, etc.