Good stuff man, thanks for posting.
Hey all,
This is pretty cool.
I just ran a test and went to check the log file the script creates and there in plain text is the API user name and password.
Is there a way to stifle this? Is the log file necessary?
Thanks as always,
-pat
-pat
Ok. Was able to comment out lines in order to stop the log file.
### logPath='/Library/Logs' ### <--- enter a path to where you store log files locally
### if [[ ! -d "$logPath" ]]; then
### mkdir $logPath
### fi
### set -xv; exec 1> $logPath/checkUpTime.txt 2>&
Which is fine for me cause I really don't need to the log file. At least I don't think I do.
Then another error pops up, which has no bearing on the log file. Cause I was seeing the error before I commented the above lines:
Script result: /Library/Application Support/JAMF/tmp/checkUptime.sh: line 66: [: !=: unary operator expected
Which points to:
if [ $email != "" ]; then
echo "$message1
$message1b
$message2
$message3
$message3a
$message4
$message5" | mail -s "URGENT: Restart Your Machine" $email
fi
I can comment the above lines out and the error goes away. But I do like the idea of email the user.
Thanks again!!
-pat
Just FYI, you don't need to hardcode the API username and password into a script. You can assign them to parameters, like $4 and $5 respectively, and pass that down to the script from the JSS when it runs. That's always what I do. That way, if someone actually gets their hands on the script they still wouldn't see a username and password in it.
Regarding the unary operator error, there are two things you can try changing to fix that.
The first if to use double brackets, like so
if [[ $email != "" ]]; then
or, quote the $email variable
if [ "$email" != "" ]; then
Either one may help stop that error.
@mm2270 you're absolutely right. I didn't pass it as a $ variable for no real reason. Just being lazy, I guess. :-)
As for the unary operator error, I'll probably just change it to this:
if [ $email ]; then
Since really all I am testing for is if the email address is blank.
I just tried using the $4 and $5 and yes, it does work!!
For the email part, I've tried both ways:
if [[ $email != "" ]]; then
or
if [ "$email" != "" ]; then
And both no longer produce the error I posted.
But I don't receive the email even though my machine is 32 days uptime.
-pat
@pvader I'm assuming your email address is filled out in the JSS for your computer record, correct? You can troubleshoot by checking the mail log on your machine. It is located in /var/log/mail.log. Check to see if the email is getting sent out or if an error is popping up.
@stevewood
I do have a correct email entry that computer record. So that is good.
I do not have /var/log/mail.log on the client machine nor the JSS server (which is an Ubuntu 12.04 flavour.)
-pat
@pvader - you should probably throw an extra echo in there to print out what email address the script is pulling. Are you certain you have your API account set up correctly? You can easily test it in a browser with the same credentials ahead of time to be sure there are no problems with that.
As an alternative, if your user accounts are all primarily AD based, you could simply grab the email address from the locally cached account, based on either who is logged in at the moment, or who's the most frequently logged in account. The 'EMailAddress' attribute gets stored in AD based accounts on the local system and can be pulled pretty easily with dscl.
I'll check it soon. Busy with Universal Type Client 4 and Adobe CC roll out these past few days.
Thanks all as always!
-p
Can it pop up a message window instead of sending e-mail?
@jchin-ro
- We use an EA to tell us Days Since Last Reboot.
- We then create a smart group for machines with 14+ days since last reboot. In the criteria, we excluded servers.
- We then created a script using displayMessage that will put up a dialog that says "Just a friendly reminder that your Mac hasn't been restarted in a while. Please restart when you get a chance." - and requires the user click "OK" to acknowledge.
- We then ccreated a policy that calls the script and scoped it to the above smart group and set it to trigger on recurring checkin once a week.
So once a machine hasn't been rebooted in 14 days, the user will get a weekly reminder that they have to acknowledge until they reboot - causing their machine to leave the smart group.
I would love to do exactly the same thing. Can you shed a little more detail on how to do that display message setup? I am new to Jamf and any pointers would really help. Thanks.
@jchin-ro
Have a look at :
https://www.jamf.com/jamf-nation/feature-requests/751/jamfhelper-make-it-awesome
https://github.com/haircut/better-jamf-policy-deferral
I might suggest running such a policy after hours initially, or at least detect Power Point or Keynote running. (this can be complicated if they're set to launch on startup)
Also be sure to check you're collecting inventory sufficiently, keeping in mind that inventory collection doesn't always succeed on startup, you can end up with a client that doesn't leave the smart group, even after a reboot. To be safe, script uptime "precheck" before you kick off notify as in the original post.
@jchin-ro
Here's the EA for days since last reboot.
#!/bin/bash
# Commands required by this script
# credit to acidprime on jamfnation
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
Here's the script for pushing the reminder message to the user -
#!/bin/sh
/usr/local/jamf/bin/jamf displayMessage -message "Just a friendly reminder that your Mac hasn't been restarted in a while. Please restart when you get a chance."
We collect inventory once a day for all endpoints.
We scope the policy for the notification message to run once a week, and exclude servers.
So given these two things, it's very unlikely (but not impossible) that we'll encounter a situation where a user just rebooted right before getting the notification.
If this is something you want to do, it's easy enough to test the EA and the script to push the notification separately.
All that said. . .if you wanted to go nuts you could probably use the same EA, smart groups, and logic and do a more elegant Notification Center notification using Yo (https://github.com/sheagcraig/yo). We just haven't gone there yet and implemented this more quickly.
easier to get uptime in days with this one liner :
#!/bin/sh
uptime | cut -d "," -f 1 | awk '{print $3;}'
I might make the message less arbitrary and include something along the lines "In order to ensure installation of security/application updates and to improve performance, please reboot as soon as convenient"
Maybe start turning this on for clients that haven't rebooted in 30, and evaluate from there. Starting at even 14 will likely cause disruption and push back from a large group of users.
@lkrasno Your uptime script is definitely simpler. How does it handle displaying a value of less than one?
One of the reasons we use this particular methodology is that it shares a foundation with a few scripts/EAs we have that monitor things that use epoch time.
As for the message, the verbiage can definitely be whatever suits the personality and culture of your org. We've had this workflow in place for over a year across all of our clients (we're an MSP) and we've heard no complaints from anyone regarding frequency.
@jchin-ro if you look at the original post, I was using cocoaDialog to pop a bubble (Notification Center) dialog. If you have cocoaDialog installed and do not want to have an EA and a policy, you can use just the script in a policy. And the reason I was grabbing the uptime this way:
days=`uptime | awk '{ print $4 }' | sed 's/,//g'` # grabs the word "days" if it is there
num=`uptime | awk '{ print $3 }'` # grabs the number of hours or days in the uptime command
Was because if the machine had been up for 7 hours the script would see that as 7 days unless you checked for the word 'days' and would alert the user.
Cleaned up without email or logging:
#!/bin/sh
CD="/usr/local/bin/cocoaDialog.app/Contents/MacOS/cocoaDialog"
cdTitle="Machine Needs A Restart"
loggedInUser=`/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'`
## set minDays - we start bugging users at this level with just a dialog box
minDays=7
## set maxDays - after we reach maxDays we bug with dialog box AND email
maxDays=15
#### MAIN CODE ####
days=`uptime | awk '{ print $4 }' | sed 's/,//g'` # grabs the word "days" if it is there
num=`uptime | awk '{ print $3 }'` # grabs the number of hours or days in the uptime command
## now the logic
if [ $loggedInUser != "root" ]; then
if [ $days = "days" ]; then
if [ $num -gt $minDays ]; then
if [ $num -gt $maxDays ]; then
cdIcon="/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AlertStopIcon.icns"
cdText="Your computer has not been restarted in more than $maxDays days. Please restart ASAP. Thank you."
bubble=`$CD bubble --title "$cdTitle" --no-timeout --text "$cdText" --icon-file $cdIcon`
else
cdIcon="/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AlertCautionIcon.icns"
cdText="Your computer has not been restarted in $num days. Please restart ASAP. Thank you."
bubble=`$CD bubble --title "$cdTitle" --no-timeout --text "$cdText" --icon-file $cdIcon`
fi
fi
fi
fi
exit 0
Thanks for creating this thread @stevewood . I am going to use this as a baseline for what my original Google search was (which lead me here) to be able to email users who's Mac hasn't checked in to JAMF in over 30+ days. I know there has got to be a way!
@amartin253, you can use mailsend-go for that. smtp command line tool.