Policy run after Inventory Update

pairjal
New Contributor II

Hi,

i set update inventory every day for each device and i have set extension attribute (device uptime) that also will be collect during update inventory.

I have set policy that will trigger a notification if the device uptime is more than 5days. the problem is, and maybe only my concern and think too much; :) ; how can i make the policy run AFTER update inventory every day?

i tried to figure out in smart group: Last inventory update, not sure how to set that.

Anyone please?

2 ACCEPTED SOLUTIONS

mm2270
Legendary Contributor III

@pairjal

I think maybe you are over thinking this a little :)

Instead of using an EA to populate a Smart Groups that in turn triggers a policy, why not just combine all this into one policy that would do this-

Run a script that is a combination of your EA and your messaging script. High level, have the script do-
• Check UPTIME on the Mac
• If UPTIME is equal to or greater than x number of days (5?) then display message about being up too long to the user (with something like jamfHelper, cocoaDialog, etc)
• if UPTIME is less than x number of days, exit silently

Have the above run once per day on the every 15 trigger. This way you can be 100% certain that no-one would ever see a message about their Mac being up too long unless it really was. Having the script run on the Mac will gather accurate information and then take an action.

Does this make sense? I think you should forget about unnecessarily complicating this, personally.

If you wanted to make your script somewhat flexible, you could set up a parameter, $4, to pass a value to check for down to the script. In other words, if you decided later you wanted to check for 6 days or greater, just change the value for uptime days being passed to the script. No need to rewrite it and re-upload the script.

Lastly, to answer your question about recon for an extension attribute only, no, there is no way to do this. There are at least 2 Feature Requests asking for this though, and they're popular requests, but as of right now it doesn't look like it will make its way into the product. So you're not alone in wanting to do that.

View solution in original post

mm2270
Legendary Contributor III

@pairjal,

I think to make this work, you'll need to adjust your uptime script. Though its cool that it provides a human readable format for the computer uptime, it might be a little tricky to use it in a script that checks for a greater than / less than value and then takes action. What I think would work better is to just get the days value as an integer, or you could go with hours as well. Whichever makes the most sense.

Here's a modified version of an uptime script I'm using as an EA. I changed this up a little because in my version I calculate a number with some decimal points using bc (bash calculator) In your case it can simply get a single numeric value for days up, so something like "4" or "10" or whatever. Later in the script we can do a simple test to see if the returned number is equal to or greater than a defined threshold.

#!/bin/sh

daysVal="86400"
hrsVal="3600"

## Get uptime in seconds from sysctl
secUp=$( sysctl kern.boottime | awk '{print $5}' | sed 's/,//' )

## Get epoch time in seconds
epochTime=$( date +%s )

## Calculate adjusted uptime for computer
adjTime=$(( $epochTime - $secUp ))

## Calculate uptime in hours and days
DaysUp=$(( $adjTime / $daysVal ))
HrsUp=$(( $adjTime / $hrsVal ))

echo "Days Up: $DaysUp
Hours Up: $HrsUp"

So using something like this, how about a script like so-

#!/bin/bash

daysVal="86400"

## Get uptime in seconds from sysctl
secUp=$( sysctl kern.boottime | awk '{print $5}' | sed 's/,//' )

## Get epoch time in seconds
epochTime=$( date +%s )

## Calculate adjusted uptime for computer
adjTime=$(( $epochTime - $secUp ))

## Calculate uptime in hours and days
DaysUp=$(( $adjTime / $daysVal ))

if [[ "$DaysUp" -ge 5 ]]; then
/usr/bin/osascript <<-EOF
with timeout of 200 seconds
tell application "Finder"
    activate
    set question to display dialog "This computer has not been shut down or restarted for more than a week. Please shut down or restart the computer by clicking on Shut Down or Restart." with title "System Event by Andres Cheah, MCM" buttons {"Shut Down", "Restart", "Cancel"} with icon stop
    set answer to button returned of question
    if answer is equal to "Shut Down" then
            set question to display dialog "This computer will shut down in 3 minutes. Please save anything you are working on." with title "System Event by Andres Cheah, MCM" buttons {"OK"} with icon stop
            delay 120
            shut down
    end if
    if answer is equal to "Restart" then
            set question to display dialog "This computer will restart in 3 minutes. Please save anything you are working on." with title "System Event by Andres Cheah, MCM" buttons {"OK"} with icon stop
            delay 120
            restart
    end if
    if answer is equal to "Cancel" then
            return
    end if
end tell

end timeout

EOF
else
    exit 0
fi

This is just slapped together more or less, so I haven't really tested this. You'll need to do that, especially when called from a policy.

Edit: to give credit where credit is due, I learned the sysctl kern.boottime trick to get the Mac's boot time from a post by Zachary Smith @acidprime here: https://jamfnation.jamfsoftware.com/discussion.html?id=4058. Just wanted to mention that.

View solution in original post

9 REPLIES 9

mscottblake
Valued Contributor

If all you are doing is triggering a notification, my suggestion is to create a Smart Group with your criteria, and set it to Send Email Notification on Change.

When the Update Inventory policy runs, the machines matching the Smart Group criteria will be automatically added which will cause an email notification to be sent.

pairjal
New Contributor II

Hi Blake

no, what i mean, in the policy (uptime), i have make a script that will trigger display dialog to the user.

so, i just wanted to know, is there a way to make sure that the policy run AFTER update inventory run first?
because i wanted the inventory update first, then extension attribute i set is up-to-date and smart group has accurate information and can run the policy (uptime)..

mscottblake
Valued Contributor

Okay, then I think your best bet is to first trigger an inventory update from your script with```
sudo jamf recon

Then use the JSS API to get the updated information with```
curl -s -u API_USER:API_PASS https://your.jss.com:8443/JSSResource/computers/name/COMPUTER_NAME/subset/groups_accounts&extension_attributes

If the machine was removed from the smart group during this recon, exit the script. If not, you now have accurate information you can display to your users.

mm2270
Legendary Contributor III

Wait, why not just rely on the regular check in cycle to do this for you? If you already have a Smart Group that the Macs fall into or out of based on the value returned in your EA, once they submit their daily inventory, if they fall into the group, just setup your messaging policy with the every 15 trigger and once per day execution, and scoped to that Smart Group. Assuming you use Every 15 minutes as the check in, the next cycle, which would be between 15 - 20 minutes later at most, will run the policy and make the message come up.
Its not immediately after inventory submission, but its fairly close. What's 15 minutes between friends/policies? :)

The only possible issue with this approach, and perhaps the gist of what your concern is, is that its possible users would see the message about long uptime even after they restarted their Mac recently, if the Mac hasn't submitted new inventory. One way you might get around that would be a policy that simply recons a Mac with the Startup trigger. So if they reboot, it should recon, drop into/out of the group and thus wouldn't run the other message policy if it didn't need to.

pairjal
New Contributor II

Hi msblake,

thanks, but it too complicated for me :))

Hi mm2270,

Yeah, that what i'm concern about. It is good idea to do another recon on startup trigger, i never do that, is it will slow down startup process? Or, can i do recon for specific extension attribute? It would be great if can do that.

thanks.

mm2270
Legendary Contributor III

@pairjal

I think maybe you are over thinking this a little :)

Instead of using an EA to populate a Smart Groups that in turn triggers a policy, why not just combine all this into one policy that would do this-

Run a script that is a combination of your EA and your messaging script. High level, have the script do-
• Check UPTIME on the Mac
• If UPTIME is equal to or greater than x number of days (5?) then display message about being up too long to the user (with something like jamfHelper, cocoaDialog, etc)
• if UPTIME is less than x number of days, exit silently

Have the above run once per day on the every 15 trigger. This way you can be 100% certain that no-one would ever see a message about their Mac being up too long unless it really was. Having the script run on the Mac will gather accurate information and then take an action.

Does this make sense? I think you should forget about unnecessarily complicating this, personally.

If you wanted to make your script somewhat flexible, you could set up a parameter, $4, to pass a value to check for down to the script. In other words, if you decided later you wanted to check for 6 days or greater, just change the value for uptime days being passed to the script. No need to rewrite it and re-upload the script.

Lastly, to answer your question about recon for an extension attribute only, no, there is no way to do this. There are at least 2 Feature Requests asking for this though, and they're popular requests, but as of right now it doesn't look like it will make its way into the product. So you're not alone in wanting to do that.

pairjal
New Contributor II

Hi @mm2270

brilliant! anyone know how to script combination between check uptime and notifcation?
uptime script:

#! /bin/sh

# if $4 from `uptime` is "mins," then the system has been up for less than an hour. 
# We set $timeup to the output of $3, appending only "m".
timechk=`uptime | awk '{ print $4 }'`

if [ $timechk = "mins," ]; then
        timeup=`uptime | awk '{ print $3 "m" }'`

# if $4 is "days," then we generate a readable string from $3, $4, and $5;
elif [ $timechk = "days," ]; then

                timeup=`uptime | awk '{ print $3 $4 " " $5 }' | sed 's/days,/d/g' | sed 's/:/h /g' | sed 's/,/m/g'`

# otherwise, generate a readable string from $3.
else

                timeup=`uptime | awk '{ print $3 }' | sed 's/:/h /g' | sed 's/,/m/g'`

fi

echo "<result>$timeup</result>"

and this notification script:

#!/bin/bash
VARIABLE=$(/usr/bin/osascript <<-EOF
with timeout of 200 seconds
tell application "Finder"
    activate
    set question to display dialog "This computer has not been shut down or restarted for more than a week. Please shut down or restart the computer by clicking on Shut Down or Restart." with title "System Event by Andres Cheah, MCM" buttons {"Shut Down", "Restart", "Cancel"} with icon stop
    set answer to button returned of question
    if answer is equal to "Shut Down" then
            set question to display dialog "This computer will shut down in 3 minutes. Please save anything you are working on." with title "System Event by Andres Cheah, MCM" buttons {"OK"} with icon stop
            delay 120
            shut down
    end if
    if answer is equal to "Restart" then
            set question to display dialog "This computer will restart in 3 minutes. Please save anything you are working on." with title "System Event by Andres Cheah, MCM" buttons {"OK"} with icon stop
            delay 120
            restart
    end if
    if answer is equal to "Cancel" then
            return
    end if
end tell

end timeout

EOF)

exit 0

If anyone help will be appreciate. thanks

mm2270
Legendary Contributor III

@pairjal,

I think to make this work, you'll need to adjust your uptime script. Though its cool that it provides a human readable format for the computer uptime, it might be a little tricky to use it in a script that checks for a greater than / less than value and then takes action. What I think would work better is to just get the days value as an integer, or you could go with hours as well. Whichever makes the most sense.

Here's a modified version of an uptime script I'm using as an EA. I changed this up a little because in my version I calculate a number with some decimal points using bc (bash calculator) In your case it can simply get a single numeric value for days up, so something like "4" or "10" or whatever. Later in the script we can do a simple test to see if the returned number is equal to or greater than a defined threshold.

#!/bin/sh

daysVal="86400"
hrsVal="3600"

## Get uptime in seconds from sysctl
secUp=$( sysctl kern.boottime | awk '{print $5}' | sed 's/,//' )

## Get epoch time in seconds
epochTime=$( date +%s )

## Calculate adjusted uptime for computer
adjTime=$(( $epochTime - $secUp ))

## Calculate uptime in hours and days
DaysUp=$(( $adjTime / $daysVal ))
HrsUp=$(( $adjTime / $hrsVal ))

echo "Days Up: $DaysUp
Hours Up: $HrsUp"

So using something like this, how about a script like so-

#!/bin/bash

daysVal="86400"

## Get uptime in seconds from sysctl
secUp=$( sysctl kern.boottime | awk '{print $5}' | sed 's/,//' )

## Get epoch time in seconds
epochTime=$( date +%s )

## Calculate adjusted uptime for computer
adjTime=$(( $epochTime - $secUp ))

## Calculate uptime in hours and days
DaysUp=$(( $adjTime / $daysVal ))

if [[ "$DaysUp" -ge 5 ]]; then
/usr/bin/osascript <<-EOF
with timeout of 200 seconds
tell application "Finder"
    activate
    set question to display dialog "This computer has not been shut down or restarted for more than a week. Please shut down or restart the computer by clicking on Shut Down or Restart." with title "System Event by Andres Cheah, MCM" buttons {"Shut Down", "Restart", "Cancel"} with icon stop
    set answer to button returned of question
    if answer is equal to "Shut Down" then
            set question to display dialog "This computer will shut down in 3 minutes. Please save anything you are working on." with title "System Event by Andres Cheah, MCM" buttons {"OK"} with icon stop
            delay 120
            shut down
    end if
    if answer is equal to "Restart" then
            set question to display dialog "This computer will restart in 3 minutes. Please save anything you are working on." with title "System Event by Andres Cheah, MCM" buttons {"OK"} with icon stop
            delay 120
            restart
    end if
    if answer is equal to "Cancel" then
            return
    end if
end tell

end timeout

EOF
else
    exit 0
fi

This is just slapped together more or less, so I haven't really tested this. You'll need to do that, especially when called from a policy.

Edit: to give credit where credit is due, I learned the sysctl kern.boottime trick to get the Mac's boot time from a post by Zachary Smith @acidprime here: https://jamfnation.jamfsoftware.com/discussion.html?id=4058. Just wanted to mention that.

pairjal
New Contributor II

hi @mm2270

thanks for your brilliant idea and script. i will test it in our environment.