Skip to main content
Solved

Uptime Extension Attribute script help needed.


Forum|alt.badge.img+6

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!

Best answer by acidprime

#!/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

View original
Did this topic help you find an answer to your question?

22 replies

Forum|alt.badge.img+24
  • Valued Contributor
  • 1892 replies
  • March 14, 2012

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

stevewood
Forum|alt.badge.img+35
  • Employee
  • 1797 replies
  • March 14, 2012

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


Forum|alt.badge.img+13

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.


Forum|alt.badge.img+6
  • Author
  • Contributor
  • 79 replies
  • March 14, 2012

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


stevewood
Forum|alt.badge.img+35
  • Employee
  • 1797 replies
  • March 14, 2012

Oops...there's an echo missing. Change the <result> line to this:

<result>echo $num</result>

That should do the trick.

Steve


Forum|alt.badge.img+24
  • Valued Contributor
  • 1892 replies
  • March 14, 2012

+1 Steve


Forum|alt.badge.img+6
  • Author
  • Contributor
  • 79 replies
  • March 14, 2012
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.
:-/


rob_potvin
Forum|alt.badge.img+23
  • Employee
  • 209 replies
  • March 14, 2012

+1. That would be a great idea!!


stevewood
Forum|alt.badge.img+35
  • Employee
  • 1797 replies
  • March 14, 2012

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


Forum|alt.badge.img+7
  • Contributor
  • 28 replies
  • Answer
  • March 14, 2012
#!/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


Forum|alt.badge.img+13

how would you like your yak shaved today, sir?


mm2270
Forum|alt.badge.img+16
  • Legendary Contributor
  • 7880 replies
  • March 14, 2012

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

Forum|alt.badge.img+6
  • Author
  • Contributor
  • 79 replies
  • March 14, 2012
how would you like your yak shaved today, sir?

LOL!


Forum|alt.badge.img+6
  • Author
  • Contributor
  • 79 replies
  • March 14, 2012

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!


chris_kemp
Forum|alt.badge.img+20
  • Jamf Heroes
  • 339 replies
  • January 9, 2013

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

Forum|alt.badge.img+4
  • New Contributor
  • 8 replies
  • January 13, 2014

Snook, muchas gracias senor. I needed this in a big way.


Forum|alt.badge.img+8
  • Contributor
  • 35 replies
  • November 21, 2014

Cheers, all, for this thread! Thanks @chris.kemp for your modified script, it's currently working well with our 10.10 machines.


Forum|alt.badge.img+12
  • Contributor
  • 529 replies
  • November 25, 2014

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

Forum|alt.badge.img+10
  • Valued Contributor
  • 71 replies
  • March 28, 2021

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

Forum|alt.badge.img+10
  • Valued Contributor
  • 108 replies
  • August 5, 2022

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?


Forum|alt.badge.img+10
  • Valued Contributor
  • 108 replies
  • August 5, 2022

Never mind, I had to change the input type to "Integer" and I can now see it.  Great script by the way!


Forum|alt.badge.img+6
  • Contributor
  • 83 replies
  • January 25, 2024
chris_kemp wrote:

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

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


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings