Posted on 03-14-2012 07:55 AM
Greetings JAMF Nationers
I am looking to create a uptime Extension Attribute.
I have created an Extension Attribute with the data type: Integer
Input Type: Populated by Script
Mac OS C Script Contentes:
#!/bin/sh
echo -n"<result>"
uptime
"</result>"
exit 0
This results in:
23:40 up 14:02, 2 users, load averages: 0.50 0.35 0.35 /private/tmp/extensionAttributeScript: line 7:
I would like a simple number in days, so I need to edit the result.
Something like:
uptime | awk -F'( |,)' '{print $2}'
Results in:
up 45 mins or up 4 days
How do I get a simple number in days?
Thanks in advance for any help!
Solved! Go to Solution.
Posted on 03-14-2012 12:06 PM
#!/bin/bash
# Commands required by this script
declare -x awk="/usr/bin/awk"
declare -x sysctl="/usr/sbin/sysctl"
declare -x perl="/usr/bin/perl"
declare -xi DAY=86400
declare -xi EPOCH="$($perl -e "print time")"
declare -xi UPTIME="$($sysctl kern.boottime |
$awk -F'[= ,]' '/sec/{print $6;exit}')"
declare -xi DIFF="$(($EPOCH - $UPTIME))"
if [ $DIFF -le $DAY ] ; then
echo "<result>1</result>"
else
echo "<result>$(($DIFF / $DAY))</result>"
fi
https://gist.github.com/2046271
Here is an epoch style calculation using sysctl
Posted on 03-14-2012 08:27 AM
try:
uptime | cut -d "," -f 1 | awk '{print $3,$4;}'
You could go straight from uptime into awk, but that'll leave you with a trailing ",". You could sed it out, but I think this is a bit easier to understand.
Result:
uptime
11:32 up 35 mins, 3 users, load averages: 2.93 2.93 2.34
With some cut and awk:
uptime | cut -d "," -f 1 | awk '{print $3,$4;}'
35 mins
Posted on 03-14-2012 08:47 AM
I like Jared's method, although once you have gone past an hour of uptime you would not have a $4 variable for the print command. So instead of "35 mins" for your response, you'd have something like "1:18".
If you are not concerned with anything less than 1 day in uptime, and not concerned with the "extra" time past 1 day (1 day 11:04 for example), then you could do something like this:
#!/bin/sh
days=`uptime | awk '{ print $4 }' | sed 's/,//g'`
num=`uptime | awk '{ print $3 }'`
# now check how long they've been awake
if [ $days = "days" ];
<result>$num</result>
fi
That is part of a larger script I use to irritate users that do not restart at least every 5 days.
Steve
Posted on 03-14-2012 08:59 AM
if this appeals to you, you can install facter (part of puppet but can be used standalone) and get 'facter uptime_days' to plug into your results.
http://downloads.puppetlabs.com/mac
if you use facter to generate all these system facts, you don't need to add more complexity by scripting them in an ad hoc fashion.
Posted on 03-14-2012 09:21 AM
stevewood, I like your script idea.
#!/bin/sh
days=`uptime | awk '{ print $4 }' | sed 's/,//g'`
num=`uptime | awk '{ print $3 }'`
# now check how long they've been awake
if [ $days = "days" ];
<result>$num</result>
fi
But the result I get from the JSS is:
$num
Any ideas?
Wi11
Posted on 03-14-2012 09:29 AM
Oops...there's an echo missing. Change the <result> line to this:
<result>echo $num</result>
That should do the trick.
Steve
Posted on 03-14-2012 09:53 AM
+1 Steve
Posted on 03-14-2012 10:18 AM
Oops...there's an echo missing. Change the <result> line to this: <result>echo $num</result> That should do the trick. Steve
Unfortunately it did not.
#!/bin/sh
days=`uptime | awk '{ print $4 }' | sed 's/,//g'`
num=`uptime | awk '{ print $3 }'`
# now check how long they've been awake
if [ $days = "days" ];
<result>echo $num</result>
fi
Result:
Uptime: echo $num
My knowledge of scripting is obviously limited. Comparing this script to other Extension Attribute scripts it looks like they have the <result> in " like:
"<result>echo $num</result>"
And have the echo before the <result>
echo "<result>$lastUser</result>"
But I have tried booth variations to no avail.
Thoughts?
Seems like JAMF should just make something like available from a template.
:-/
Posted on 03-14-2012 10:37 AM
+1. That would be a great idea!!
Posted on 03-14-2012 10:39 AM
Well, if I had the right syntax in there for the if/then statement, it might work better. I had cut out pieces that you didn't need and missed the crucial "then":
Try this instead:
#!/bin/sh
days=`uptime | awk '{ print $4 }' | sed 's/,//g'`
num=`uptime | awk '{ print $3 }'`
# now check how long they've been awake
if [ $days = "days" ];
then
echo "<result>$num</result>"
fi
I tested on a machine here and it gave the expected results.
Sorry about that. Guess I gotta wait until the Full Throttle energy drink kicks in before responding.....
Steve
Posted on 03-14-2012 12:06 PM
#!/bin/bash
# Commands required by this script
declare -x awk="/usr/bin/awk"
declare -x sysctl="/usr/sbin/sysctl"
declare -x perl="/usr/bin/perl"
declare -xi DAY=86400
declare -xi EPOCH="$($perl -e "print time")"
declare -xi UPTIME="$($sysctl kern.boottime |
$awk -F'[= ,]' '/sec/{print $6;exit}')"
declare -xi DIFF="$(($EPOCH - $UPTIME))"
if [ $DIFF -le $DAY ] ; then
echo "<result>1</result>"
else
echo "<result>$(($DIFF / $DAY))</result>"
fi
https://gist.github.com/2046271
Here is an epoch style calculation using sysctl
Posted on 03-14-2012 12:15 PM
how would you like your yak shaved today, sir?
Posted on 03-14-2012 12:18 PM
Nice scripts. I had done something like this a while ago, but wanted to get a more accurate picture of uptime when the Macs recon'ed, not just whether it had been more than one day. Here is the script I made. It has perhaps too many "seds", so if anyone has suggestions on a better way, I'm all ears/eyes.
Basically this will check to see if the Mac has been up for more than one day and then pull the days + hours values from uptime and clean up the output to make it more readable. If it hasn't been up for more than one day, it just pulls the hrs. It can probably be modified to check for systems only up for 1 day and some num hrs and pull that properly, but I haven't bothered with that.
This would also be a little hard to use in a SmartGroup to nag users as is, like with Steve's script, so YMMV. Maybe use both.
#!/bin/sh
DAYS="days,"
HRS=" hrs"
DAYScheck=$(uptime | awk {'print $4'})
if [ $DAYScheck = "$DAYS" ]; then
result=$(uptime | awk {'print $3.$4.$5'} | sed 's/,/ /g' | sed 's/d/ d/g')
echo "<result>$result$HRS</result>"
else
result=$(uptime | awk {'print $3'} | sed 's/,//g')
echo "<result>$result$HRS</result>"
fi
exit
Posted on 03-14-2012 12:29 PM
how would you like your yak shaved today, sir?
LOL!
Posted on 03-14-2012 12:57 PM
I gave the answer to acidprime as his script returned a 1 when uptime is less then one day, Steve your script returned nothing when uptime is less then one day but worked just fine when uptime was more then one day.
Thank you all for your help!
Now if you will excuse me I have some recon to run.
:-)
Getting some crazy results some over 30 days!
Posted on 01-09-2013 05:38 AM
Another variation that I hacked together, taking some cues from the above:
#! /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>"
This will return a compact string suitable for display in a Search field, such as:
5d 2h 29m 12h 42m 52m
Posted on 01-25-2024 08:11 AM
Thank you, chris_kemp! I wish everyone wrote code and comments this. It helps people learn how to write their own scripts.
There's an old saying about writing clear, readable code: Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
To that, I would only add "The same goes for commenting your code."
Posted on 01-13-2014 01:41 PM
Snook, muchas gracias senor. I needed this in a big way.
Posted on 11-21-2014 07:11 AM
Cheers, all, for this thread! Thanks @chris.kemp for your modified script, it's currently working well with our 10.10 machines.
Posted on 11-25-2014 08:23 AM
I'd have probably just gone with:
#!/bin/bash
RESULT=`ps -p 1 -o etime | sed -n '2p'`
echo "<result>"$RESULT"</result>"
exit 0
or if as requested you just want days:
#!/bin/bash
getDays=`ps -p 1 -o etime | grep "-" | cut -d "-" -f 1`
if [[ "$getDays" == "" ]]
then
theDays="0 days"
else
theDays="$getDays days"
fi
echo "<result>"$theDays"</result>"
exit 0
Posted on 03-28-2021 03:31 AM
Thanks for all your ideas, guys!
I especially like the script of @stevewood and added an else in case the uptime is less than 1 day. I tested it on Catalina and Big Sur and it seems to work.
#!/bin/sh
#grab uptime and save time in num and unit in days
days=`uptime | awk '{ print $4 }' | sed 's/,//g'`
num=`uptime | awk '{ print $3 }'`
# now check how long they've been awake; if less than one day it echoes 0
if [ $days = "days" ];
then
echo "<result>$num</result>"
else
echo "<result>0</result>"
fi
Posted on 08-05-2022 01:10 PM
I'm looking for a way to create a SmartGroup with the criteria of "greater than" or "less than" for this extension attribute string. I only have the options of "is, is not, like, not like, etc..."
Anyone have any ideas on how to get a SmartGroup to work that meets the criteria if uptime is greater than a specified "n" of days?
Posted on 08-05-2022 01:53 PM
Never mind, I had to change the input type to "Integer" and I can now see it. Great script by the way!