Posted on 09-06-2017 08:20 AM
Hey Guys,
Just wondering what you guys are using for EA on checking uptime on the macs. I did find this :https://www.jamf.com/jamf-nation/discussions/10009/uptime-or-last-shutdown-restart
Curious to see if you guys have an EA that works to report back in Days/Minutes and works on macOS Sierra!
Solved! Go to Solution.
Posted on 09-06-2017 08:31 AM
Our System Uptime EA looks like this:
#!/usr/bin/python2.7
import plistlib
import subprocess
data = subprocess.check_output(['/usr/sbin/system_profiler', 'SPSoftwareDataType', '-xml', '-detailLevel', 'mini'])
plist = plistlib.readPlistFromString(data)
uptime_string = plist[0]['_items'][0]['uptime']
time_list = uptime_string.split('up ')[1].split(':')
time_stamp = '{} d {} h {} m {} s'.format(*time_list)
print("<result>{}</result>".format(time_stamp))
And it looks like this in inventory:
Posted on 09-06-2017 08:31 AM
Our System Uptime EA looks like this:
#!/usr/bin/python2.7
import plistlib
import subprocess
data = subprocess.check_output(['/usr/sbin/system_profiler', 'SPSoftwareDataType', '-xml', '-detailLevel', 'mini'])
plist = plistlib.readPlistFromString(data)
uptime_string = plist[0]['_items'][0]['uptime']
time_list = uptime_string.split('up ')[1].split(':')
time_stamp = '{} d {} h {} m {} s'.format(*time_list)
print("<result>{}</result>".format(time_stamp))
And it looks like this in inventory:
Posted on 09-06-2017 08:41 AM
thanks @jmahlman ! works like a charm!
Posted on 09-06-2017 08:59 AM
No problemo.
If you want more accurate uptime, you'll have to have something run every check-in instead of Inventory time. We haven't found the need for that but if you do something like that post it here for reference.
Posted on 09-06-2017 09:23 AM
Just to throw in another variation, here's one that I extracted from another script I built. We don't actually use this for our uptime EA, preferring instead to use a straight hours value, so we can use it in Smart Groups with greater than/less than if needed.
This looks like a long script, but it actually only takes about .02 seconds to run
real 0m0.020s
user 0m0.006s
sys 0m0.011s
The script is below. It uses the boot time from sysctl.kern.boottime
and compares against the current unix time and does a bunch of calculations from there.
#!/bin/bash
lastBootTime=$(sysctl kern.boottime | awk -F'[ |,]' '{print $5}') ## Raw unix time in seconds of last boot up
currentTime=$(date +"%s") ## Current time in unix seconds
upTimeRaw=$((currentTime-lastBootTime)) ## Calculation of difference between boot and current time ( total time up in seconds )
upTimeMin=$((upTimeRaw/60)) ## Calculation of uptime in minutes total ( uptime in seconds div by 60 )
upTimeHours=$((upTimeMin/60)) ## Calculation of uptime in hours total ( uptime in minutes div by 60 )
upTimeDays=$((upTimeHours/24)) ## Calculation of uptime in whole days total ( uptime in hours div by 24 )
minusMinutes=$((((upTimeDays*24))*60)) ## Total minutes up in whole days ( [uptime in whole days x 24] x 60 minutes )
remainingMin=$((upTimeMin-minusMinutes)) ## Calculation of remaining minutes to subtract
remainingHrs=$((remainingMin/60)) ## Calculation of remaining hours to subtract
minusHours=$((upTimeHours-remainingHrs))
## Figure out minutes value for uptime display
total1=$((upTimeDays*24*60))
total2=$((remainingHrs*60))
minusMinutes2=$((total1+total2))
remainingMinFin=$((upTimeMin-minusMinutes2))
UptimeThreshold1alt=$((UptimeThreshold1-1))
UptimeThreshold2alt=$((UptimeThreshold2-1))
if [ "$upTimeDays" == "1" ]; then
daysText="Day"
else
daysText="Days"
fi
if [ "$remainingHrs" == "1" ]; then
hrsText="Hour"
else
hrsText="Hours"
fi
if [ "$remainingMinFin" == "1" ]; then
minsText="Minute"
else
minsText="Minutes"
fi
echo "<result>$upTimeDays $daysText, $remainingHrs $hrsText, $remainingMinFin $minsText</result>"
How it displays as an example:
3 Days, 10 Hours, 48 Minutes
As @jmahlman mentioned, this will only be as accurate as your last full inventory collection, so it could be off by quite a few hours in either direction. Just something to keep in mind, and true with any uptime EA, no matter what you use.
Posted on 09-06-2017 10:57 AM
nm. Extension Attribute.
Posted on 09-06-2017 01:33 PM
I built one that just returns the value in days, if it is under 1 day it will return 0
.
#!/usr/bin/python
'''
This will track last reboot time and flag systems that have rebooted on their own
'''
# import modules
import subprocess
import time
# global varibles if any
# start functions
def get_last_reboot():
'''use system control binary to read reboot time from kernel
use sub process to grab that'''
cmd = ['sysctl', '-h', 'kern.boottime']
ps = subprocess.check_output(cmd)
output = ps.strip()
output_list = output.split()
epoch_reboot_date = output_list[4].replace(',','')
return epoch_reboot_date
def diff_times(reboot_time):
'''get current epoch time to get a difference of seconds a system has been running'''
current_epoch_time = int(time.time())
epoch_since_reboot = current_epoch_time - int(reboot_time)
return epoch_since_reboot
def get_days_reboot(seconds):
'''return days since reboot'''
days = int(seconds) / 86400
return days
def run():
reboot = get_last_reboot()
reboot_diff = diff_times(reboot)
reboot_days = get_days_reboot(reboot_diff)
print "<result>%s</result>" % reboot_days
run()
output:
/usr/bin/python /Users/tlarkin/IdeaProjects/python/reboot_check.py
<result>10</result>
Process finished with exit code 0
My EA is labeled: Days Since Last Reboot
EDIT -
The reason I went with an integer based on days is that makes it easier to scope things and report on things. At a high level if something needs a sanity check (like we patch/update/deploy something and ask an end user to nicely reboot) I would rather deal with how many days have passed since a reboot occurred.
Posted on 02-17-2021 12:26 PM
I too like the simplicity of reporting Days only and having the EA type be an integer which allows for less-than/greater than scoping, here's that same thing in shell only:
#!/bin/bash
#Joel Bruner
#Jamf EA - Uptime Days (integer)
#get uptime output
uptimeOutput=$(uptime)
#detect "day" by removal and then string comparison, awk gets number of days between "up " and " day"
[ "${uptimeOutput/day/}" != "${uptimeOutput}" ] && uptimeDays=$(awk -F "up | day" '{print $2}' <<< "${uptimeOutput}")
#less than a day echo 0
echo "<result>${uptimeDays:-0}</result>"