Need to process policy based on uptime

chuck3000
Contributor

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?

4 REPLIES 4

iJake
Valued Contributor

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

mm2270
Legendary Contributor III

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.

Look
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.

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

chuck3000
Contributor

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: com.xxx.rebooter.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.xxx.rebooter</string>
    <key>Program</key>
    <string>/usr/local/scripts/reboot.sh</string>
    <key>RunAtLoad</key>
    <true/>
    <key>StartInterval</key>
    <integer>7200</integer>
</dict>
</plist>

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

#!/bin/bash
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/CocoaDialog.app/Contents/MacOS/CocoaDialog # 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....
then
    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?
    then
        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.
        then
            $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
        fi
    fi

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

        if (($currentHour >= 19)) # Is the current hour greater that 7pm
        then
            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
        else
            $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... 
        fi
    fi

    if (( $daysUp >= 8 )) # It is 8 days or more... we no longer care what time of the day it is.
    then
        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
    fi
fi


#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.