Run a policy (Inventory Update) every 4 hours

bgreeno
New Contributor III

Sorry if I'm missing something easy here. I currently have check-ins set for every 15 minutes. I would like to set inventory to update regularly, but not as often as 15 minutes. The next available option is to set execution frequency at once per day, but it cannot be set more often than that without adjusting the check-in time. How can I trigger the policy to run at different intervals i.e. every 4 hours.

Thanks!

2 ACCEPTED SOLUTIONS

mm2270
Legendary Contributor II

You're not really missing anything easy here.
You can change your default check in time to something else using a special URL in your JSS to give you some more granular options, but I don't think every 4 hours is an option and I'm also not sure its even available anymore under version 9. You can also make a second check in "task", again using that special URL, and assign that to the inventory collection policy, but its not sanctioned by JAMF to do this. (creating the additional task, which may be why its not available any more)

Other than that, an option would be to deploy a LaunchDaemon that simply runs /usr/sbin/jamf recon as its Program Arguments and with a StartInterval of 4 hours in seconds.
The problem with that second approach is then its on you to make sure that gets deployed and remains working, since its an adjunct to the built in check in policy already delayed by the Casper Suite tools. You'd also have to decide if you want to keep the existing once a day inventory collection, which may run soon after one of the ones initiated by the LaunchDaemon. Probably not a huge deal, but I'm not sure if there would be a way to make sure they don't occasionally trip over each other.
A slightly better approach might be to have the ProgramArguments call a policy with a manual trigger, like
/usr/sbin/jamf policy -trigger manualRecon or something that would call an additional policy set up to only run on that trigger from the JSS to do the inventory collection.
Finally, if using version 9.x you could use something like the Network State Change trigger to do an inventory collection, so every time a Mac reports a change in its network state it will push updated inventory to the JSS. That might end up giving you more recons in a day than you actually want though.

And those are only 3 out of probably many ways to approach this.

View solution in original post

mm2270
Legendary Contributor II

@bgreeno][/url, I was knocking this discussion around in my head last night a bit and I think I figured out a relatively simple way for you to get what you're looking for with minimal effort.
The process I came up with only involves one policy, one script and a small change to your normal inventory collection policy.

The policy would be set up to be scoped to all Macs, or perhaps a subset if you wanted, with a frequency set to Ongoing and the trigger set to the normal every X minutes check-in or "Recurring Check-in" as I think its called now.
The policy would not have the "Collect Inventory" box checked.

This is the script that would be run in the policy-

#!/bin/sh

## Script name: recon_every_x_hours.sh

## Variable to store # of hours before a new inventory collection is needed
Hours="4"

## Path to local last recon time stamp file
lastReconFile="/Library/Application Support/JAMF/.last_recon_time"

function checkDifference ()
{
## Convert hours into seconds
Secs=$((60*60*Hours))

## Get current time in Unix seconds
timeNow=$( date +%s )

## Grab the last recon time stamp from file and store into variable
lastReconTime=$( cat "$lastReconFile" )

## Determine difference in seconds between the last time stamp and current time
timeDiff=$(( timeNow-lastReconTime ))

if [[ "$timeDiff" -ge "$Secs" ]]; then
    echo "Has been at least 4 hours since last recon. Starting inventory collection..."
    jamf recon
    echo "Updating the time stamp file with new current time information…"
    echo "$( date +%s )" > "$lastReconFile"
else
    echo "Has not been at least 4 hours since last recon. Exiting..."
    exit 0
fi
}

## Check to see if the last recon timestamp file is there
if [[ -e "$lastReconFile" ]]; then
    ## Run the function to check the time difference
    checkDifference
else
    echo "last recon timestamp file was not found. Starting inventory collection..."
    jamf recon
    echo "Creating last recon timestamp file with current time information..."
    echo "$( date +%s )" > "$lastReconFile"
fi

Quick explanation on what its doing.
1 - A variable up top defines how many hours you would like to have between inventory submissions.
2 - The script first checks to see if a local timestamp file exists on the Mac that should be in /Library/Application Support/JAMF/
3 - If its there it grabs a value from it which should be the last time in Unix seconds that the policy ran and performed a full recon on that Mac.
4 - If the timestamp file is not there it runs an immediate inventory collection, then creates the timestamp file by echoing the current time in Unix seconds into the file
5 - If the file is there and there's a value in it when the script runs, it does some math to compare the current time and the time recorded in the timestamp file. If the difference between them is equal to or greater than the number of hours specified in the script in seconds, it runs a recon. It then updates the timestamp file with a new value of Unix time in seconds after its done recon-ing.
6 - If the time difference is less than the X number of hours in seconds, it notes that and exits silently.

What will happen is, every time a Mac checks in it will run this script, determine whether its been 4 hours or whatever value you specify and then take action, or not, depending on when it last needed to submit inventory.

While this means the policy will run each time a check in happens, its a very quick process to determine if a new inventory collection is needed or not. This process keeps everything in the JSS in the normal policy/script functions rather than deploying something like a LaunchDaemon and needing to keep on top of that to make sure its working.

In addition to the above, to prevent the normal daily inventory collection and this process from happening one after the other, you can add the following line to the Run Command field in your built in inventory collection policy-

echo "$( date +%s )" > /Library/Application Support/JAMF/.last_recon_time

This updates the timestamp file with the current time in seconds after the regular daily collection happens, That way if the custom Recurring Check In policy runs in the next 15 minutes it will see that a recent inventory collection happened not long ago and simply exit until the next run.

Hopefully the above makes some sense and will be helpful. While this won't capture inventory exactly every X hours, it will be pretty close. There is always the random delay that happens when check in occurs that will shift the time a little bit when it runs.

As an added bonus, we could flip that "Hours" variable at the top of the script over to a script parameter that gets passed down to it from the JSS. That way a single script could be used with different sites and policies to have different timeframes for each one. Like at one site collect inventory every 6 hours, another site collect it every 4 hours. Another one every 12, for example.

Let me know what you think or if you have any questions.

Edit: Fixed a un-commented line in script

View solution in original post

16 REPLIES 16

acdesigntech
Contributor II

So the check-in interval is how often the clients will check the JSS to see if they have anything to do, not how often they will do whatever that might be. The execution frequency is where you determine how often they run a particular job.

In the example above your clients will query the JSS every 15 minutes to see if there are any outstanding jobs to run. If you have an inventory collection policy triggered by the every15 check-in interval that runs once a day, that means that once a day the clients will submit inventory, triggered by the every15 check in trigger. However it will only run once a day, not every 15 minutes. You'd have to set the execution frequency to "Ongoing" to get them to run every 15 minutes.

The most you can set the check-in interval to on v8.x is every 1 hour with a 2-hour randomization, so every 1 to 3 hours for check in. But it's random so that's not a huge help.

Note that inventory collection is cumulative, so on Day 1 the client will submit report A, on day 2 it will submit Report B on top of Report A, on day 3 it will submit report Report C on top of reports A and B, etc. So you might not want it as frequent as every day - inventory collection makes the MySQL database grow rather quickly. I keep my scheduled inventory report submission as once every week. You can always submit an inventory report on demand, which many of the policies I create that install something, remove something, etc do as the last step before exiting, to keep the JSS database current.

bgreeno
New Contributor III

@acdesigntech Sorry if I didn't communicate clearly.

So the check-in interval is how often the clients will check the JSS to see if they have anything to do, not how often they will do whatever that might be. The execution frequency is where you determine how often they run a particular job.
I understand this. The issue is a want the execution frequency to be less than one day, but greater than 1 hour. Ideally, every 4 or 8 hours would be preferred. I flush the inventory report logs once a week so I'm not too concerned with acquiring too much data for the database. Hopefully this makes more sense.

acdesigntech
Contributor II

Ahh, ok that makes more sense. I don't know of a way to make the execution frequency more often than once a day. Other than ongoing, of course.

Are you using v8.x or 9.x of casper?

scottb
Honored Contributor

It used to be in (8.x) under jss.company.com:8443/tasks.html

But apparently JAMF was not fond of using it. I made some before I read that and deleted them after.

WARNING: Additional scheduled tasks are only necessary in special circumstances and are not recommended for typical use. Scheduling clients to check in too frequently can cause unneeded overhead on the clients and the JSS. Please contact JAMF Software Support prior to creating an additional task to discuss the risks.

mm2270
Legendary Contributor II

You're not really missing anything easy here.
You can change your default check in time to something else using a special URL in your JSS to give you some more granular options, but I don't think every 4 hours is an option and I'm also not sure its even available anymore under version 9. You can also make a second check in "task", again using that special URL, and assign that to the inventory collection policy, but its not sanctioned by JAMF to do this. (creating the additional task, which may be why its not available any more)

Other than that, an option would be to deploy a LaunchDaemon that simply runs /usr/sbin/jamf recon as its Program Arguments and with a StartInterval of 4 hours in seconds.
The problem with that second approach is then its on you to make sure that gets deployed and remains working, since its an adjunct to the built in check in policy already delayed by the Casper Suite tools. You'd also have to decide if you want to keep the existing once a day inventory collection, which may run soon after one of the ones initiated by the LaunchDaemon. Probably not a huge deal, but I'm not sure if there would be a way to make sure they don't occasionally trip over each other.
A slightly better approach might be to have the ProgramArguments call a policy with a manual trigger, like
/usr/sbin/jamf policy -trigger manualRecon or something that would call an additional policy set up to only run on that trigger from the JSS to do the inventory collection.
Finally, if using version 9.x you could use something like the Network State Change trigger to do an inventory collection, so every time a Mac reports a change in its network state it will push updated inventory to the JSS. That might end up giving you more recons in a day than you actually want though.

And those are only 3 out of probably many ways to approach this.

bgreeno
New Contributor III

@acdesigntech We're using v9.x.

@boettchs

It used to be in (8.x) under jss.company.com:8443/tasks.html
I read that it was not a good solution so they took it out of v9.x

@mm2270 Thanks for confirming what I figured. I think I'll keep it simple and live with what I've got. Hopefully policy triggers can become a bit more granular over time, though, what is currently available in v9.x is great.

Thanks everyone for all your help!

mm2270
Legendary Contributor II

@bgreeno][/url, I was knocking this discussion around in my head last night a bit and I think I figured out a relatively simple way for you to get what you're looking for with minimal effort.
The process I came up with only involves one policy, one script and a small change to your normal inventory collection policy.

The policy would be set up to be scoped to all Macs, or perhaps a subset if you wanted, with a frequency set to Ongoing and the trigger set to the normal every X minutes check-in or "Recurring Check-in" as I think its called now.
The policy would not have the "Collect Inventory" box checked.

This is the script that would be run in the policy-

#!/bin/sh

## Script name: recon_every_x_hours.sh

## Variable to store # of hours before a new inventory collection is needed
Hours="4"

## Path to local last recon time stamp file
lastReconFile="/Library/Application Support/JAMF/.last_recon_time"

function checkDifference ()
{
## Convert hours into seconds
Secs=$((60*60*Hours))

## Get current time in Unix seconds
timeNow=$( date +%s )

## Grab the last recon time stamp from file and store into variable
lastReconTime=$( cat "$lastReconFile" )

## Determine difference in seconds between the last time stamp and current time
timeDiff=$(( timeNow-lastReconTime ))

if [[ "$timeDiff" -ge "$Secs" ]]; then
    echo "Has been at least 4 hours since last recon. Starting inventory collection..."
    jamf recon
    echo "Updating the time stamp file with new current time information…"
    echo "$( date +%s )" > "$lastReconFile"
else
    echo "Has not been at least 4 hours since last recon. Exiting..."
    exit 0
fi
}

## Check to see if the last recon timestamp file is there
if [[ -e "$lastReconFile" ]]; then
    ## Run the function to check the time difference
    checkDifference
else
    echo "last recon timestamp file was not found. Starting inventory collection..."
    jamf recon
    echo "Creating last recon timestamp file with current time information..."
    echo "$( date +%s )" > "$lastReconFile"
fi

Quick explanation on what its doing.
1 - A variable up top defines how many hours you would like to have between inventory submissions.
2 - The script first checks to see if a local timestamp file exists on the Mac that should be in /Library/Application Support/JAMF/
3 - If its there it grabs a value from it which should be the last time in Unix seconds that the policy ran and performed a full recon on that Mac.
4 - If the timestamp file is not there it runs an immediate inventory collection, then creates the timestamp file by echoing the current time in Unix seconds into the file
5 - If the file is there and there's a value in it when the script runs, it does some math to compare the current time and the time recorded in the timestamp file. If the difference between them is equal to or greater than the number of hours specified in the script in seconds, it runs a recon. It then updates the timestamp file with a new value of Unix time in seconds after its done recon-ing.
6 - If the time difference is less than the X number of hours in seconds, it notes that and exits silently.

What will happen is, every time a Mac checks in it will run this script, determine whether its been 4 hours or whatever value you specify and then take action, or not, depending on when it last needed to submit inventory.

While this means the policy will run each time a check in happens, its a very quick process to determine if a new inventory collection is needed or not. This process keeps everything in the JSS in the normal policy/script functions rather than deploying something like a LaunchDaemon and needing to keep on top of that to make sure its working.

In addition to the above, to prevent the normal daily inventory collection and this process from happening one after the other, you can add the following line to the Run Command field in your built in inventory collection policy-

echo "$( date +%s )" > /Library/Application Support/JAMF/.last_recon_time

This updates the timestamp file with the current time in seconds after the regular daily collection happens, That way if the custom Recurring Check In policy runs in the next 15 minutes it will see that a recent inventory collection happened not long ago and simply exit until the next run.

Hopefully the above makes some sense and will be helpful. While this won't capture inventory exactly every X hours, it will be pretty close. There is always the random delay that happens when check in occurs that will shift the time a little bit when it runs.

As an added bonus, we could flip that "Hours" variable at the top of the script over to a script parameter that gets passed down to it from the JSS. That way a single script could be used with different sites and policies to have different timeframes for each one. Like at one site collect inventory every 6 hours, another site collect it every 4 hours. Another one every 12, for example.

Let me know what you think or if you have any questions.

Edit: Fixed a un-commented line in script

bgreeno
New Contributor III

@mm2270 This is brilliant! Thank you for doing this, much less thinking about it. It makes perfect sense. I'll test it today and let you know how it goes.

bgreeno
New Contributor III

So far this works beautifully! Thanks again.external image link

mm2270
Legendary Contributor II

@bgreeno - That's great to hear!
Just curious though - I'm wondering what that line in the log that states "No such file or directory" is about. It seems its definitely running the script so its not related to that. Not sure where that's coming from.

bgreeno
New Contributor III

@mm2270 Should there be a # in front of

Script name: recon_every_x_hours.sh

?

mpermann
Valued Contributor II

You probably need to comment out the "Script name: recon_every_x_hours.sh" line. Try putting ## at the beginning of that line.

mm2270
Legendary Contributor II

Yep, that's what it is. My bad on that. It was the last item i added and I didn't catch that. Commenting it out should fix that error.

bgreeno
New Contributor III

Yep, changed it. Should be resolved next time it runs.

daniel_jacobson
New Contributor II

Thanks for writing this. What is the idea behind adding this:

echo "$( date +%s )" > /Library/Application Support/JAMF/.last_recon_time

Versus disabling the default inventory policy?

mcs-jamf
New Contributor

hey guys,

New to Jamf Pro.

Is there a way to make Jamf complete an inventory update on a give tie stamp? Say - 8:30am each day and 4pm each afternoon?

I have an always on VPN with our students which I need to disable during school hours and turn back on out of hours.

I am using 10.3.1 and so far can't see any specific ways on how to do this other than modding the API (which I am totally new to).

Aaron