JAMF Helper: Echo 243 Timeout + Only Run If A User Is Logged On

sepiemoini
Contributor III
Contributor III

Greetings, all! I'm fine tuning a JAMF Helper script that I have in place to upgrade with an OS X installer using simple caching. Between the caching and the actual installation of the OS X installer, I want to use a JAMF Helper window to notify the end user of the process, allowing them to opt-in and opt-out.

I am noticing that the notification (running at recurring check-in, once per day) is capable of running when no one is logged onto the computer. This displays the JAMF Helper window at the login screen and eventually just times out. Here is what I would like to accomplish, with your help:

  1. Echo that a timeout has been reached using "243 - The window timed-out with no buttons on the screen."

  2. Before the JAMF Helper command runs, check to see if the logged in user (loggedInUser=$(stat -f%Su /dev/console)) is actually logged onto the computer.

#!/bin/bash

/usr/bin/curl -s -o /tmp/elcapitan_icon.png http://assets.materialup.com/uploads/ec819071-7140-4c6d-89ac-81b712642fcb/512x512bb-85.png
loggedInUser=$(stat -f%Su /dev/console)
jamfHelper="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
windowType="hud"
description="Your <Organization>-issued computer is not currently running the latest OS X version. To perform the OS X El Capitan update, select 'UPDATE' below and the upgrade will begin to run. Once complete, your computer will restart immediately. If you are unable to perform this update at the moment, please select 'Cancel.'

*Please save all working documents before selecting 'UPDATE.'

If you require assistance, please contact the Helpdesk by phone at <PhoneNumber> or by email at <EmailAddress>."

button1="UPDATE"
button2="Cancel"
icon="/tmp/elcapitan_icon.png"
title="Update Available: Install OS X El Capitan"
alignDescription="left" 
alignHeading="center"
defaultButton="2"
timeout="10"

userChoice=$("$jamfHelper" -windowType "$windowType" -lockHUD -title "$title" -timeout "$timeout" -defaultButton "$defaultButton" -icon "$icon" -description "$description" -alignDescription "$alignDescription" -alignHeading "$alignHeading" -button1 "$button1" -button2 "$button2")

if [ "$userChoice" == "0" ]; then
    echo "$loggedInUser clicked UPDATE; now running OS X El Capitan Installer via JSS policy ID 547."
    jamf policy -id 547
elif [ "$userChoice" == "2" ]; then
    echo "$loggedInUser clicked Cancel; now exiting."
    exit 0
elif [ "$userChoice" == "243" ]; then
    echo "Timeout was reached; now exiting."
    exit 0
fi
1 ACCEPTED SOLUTION

sepiemoini
Contributor III
Contributor III

Thanks, @mm2270! This did the trick :)

#!/bin/bash

/usr/bin/curl -s -o /tmp/elcapitan_icon.png http://assets.materialup.com/uploads/ec819071-7140-4c6d-89ac-81b712642fcb/512x512bb-85.png
## Collect current logged in user
loggedInUser=$(stat -f%Su /dev/console)
## Collect the UID of $loggedInUser, or rather, who owns console
loggedInPID=$(id -u "$loggedInUser")

## Define JAMF Helper variables
jamfHelper="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
windowType="hud"
description="Your <Organization>-issued computer is not currently running the latest OS X version. To perform the OS X El Capitan update, select 'UPDATE' below and the upgrade will begin to run. Once complete, your computer will restart immediately. If you are unable to perform this update at the moment, please select 'Cancel.'

*Please save all working documents before selecting 'UPDATE.'

If you require assistance, please contact the Helpdesk by phone at <PhoneNumber> or by email at <EmailAddress>."

button1="UPDATE"
button2="Cancel"
icon="/tmp/elcapitan_icon.png"
title="Update Available: Install OS X El Capitan"
alignDescription="left" 
alignHeading="center"
defaultButton="2"
timeout="5"

## Collect a count of processes that match ScreenSaverEngine
ScreenSaverCheck=$(ps axc | grep "ScreenSaverEngine" | awk 'END {print NR}')

if [[ "$loggedInPID" != 0 ]] && [[ "$ScreenSaverCheck" == 0 ]]; then
     ## ScreenSaverEngine.app and/or loginwindow.app is/are not active; run JAMF Helper
     echo "The computer is not at the login window nor is the screen saver active."
     userChoice=$("$jamfHelper" -windowType "$windowType" -lockHUD -title "$title" -timeout "$timeout" -defaultButton "$defaultButton" -icon "$icon" -description "$description" -alignDescription "$alignDescription" -alignHeading "$alignHeading" -button1 "$button1" -button2 "$button2" 2>&1)
else
     ## ScreenSaverEngine.app and/or loginwindow.app is/are active; exit script
     echo "The computer is at the login window and/or has the screen saver active."
     exit 0
fi

## JAMF Helper functions for opt-in and opt-out options
if [ "$userChoice" == "0" ]; then
    echo "$loggedInUser clicked UPDATE; now running OS X El Capitan Installer via JSS policy ID 547."
    jamf policy -id 547
elif [ "$userChoice" == "2" ]; then
    echo "$loggedInUser clicked Cancel or timeout was reached; now exiting."
    exit 0
fi

View solution in original post

11 REPLIES 11

McLeanSchool
New Contributor III

How I do it is the have a policy that caches the installer on all machines, and just have it run once per computer on check-in.

Then, I have another policy that runs the cached installer, but I allow deferral under the User Interaction tab in JSS for the policy. I then put messages using the built in message fields on the policy, explaining the implications of allowing the policy to run vs. selecting a deferral time.

Then, before I activate this policy, I send an email a few days in advance explaining the upgrade process, the implications, and why it is necessary. This allows the majority of users who would have concerns to contact me ahead of time and discuss the upgrade.

I attached an example image as well:a8b0c7ebd0964a31a320d265c10f96d8

sepiemoini
Contributor III
Contributor III

@McLeanSchool That's a great workflow but I need to stay within this custom JAMF Helper script as it allows for further customization. Any others able to assist?

McLeanSchool
New Contributor III

Ah, I see. Sorry, I don't know any fixes for the timeout issue.

sepiemoini
Contributor III
Contributor III

I effectively want this to run if loginwindow.app is not running or if it’s locked or if ScreenSaverEngine.app is running. Is this still possible to accomplish within this JAMF Helper script?

mm2270
Legendary Contributor III

@sepiemoini So, if you're already getting the logged in user with stat -f%Su /dev/console, you can check who owns the console and if its "root" then the Mac is at the login window (username & password fields)

if [ "$loggedInUser" == "root" ]; then
     exit 0
fi

As for screensaver being active, I think you can just run a ps axc or similar to see if that process is running. Since the ScreenSaverEngine should never be running when someone is using the Mac, that should be a good indication if the screen saver is up.

screenSaverProc=$(ps axc | grep ScreenSaverEngine)

The above should yield no results when the Mac is in use, or one or more results if the screensaver is on.

I'm not certain how to determine if the Mac is locked but the ScreenSaver isn't active, since I think that's a unique state that's different from the others. I'd have to research that. I have a feeling there's a way, but not certain on how.

sepiemoini
Contributor III
Contributor III

@mm2270 Great minds think alike! I think we're on a similar track. How does the below script look to you?

#!/bin/bash

/usr/bin/curl -s -o /tmp/elcapitan_icon.png http://assets.materialup.com/uploads/ec819071-7140-4c6d-89ac-81b712642fcb/512x512bb-85.png
loggedInUser=$(stat -f%Su /dev/console)
jamfHelper="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
windowType="hud"
description="Your <Organization>-issued computer is not currently running the latest OS X version. To perform the OS X El Capitan update, select 'UPDATE' below and the upgrade will begin to run. Once complete, your computer will restart immediately. If you are unable to perform this update at the moment, please select 'Cancel.'

*Please save all working documents before selecting 'UPDATE.'

If you require assistance, please contact the Helpdesk by phone at <PhoneNumber> or by email at <EmailAddress>."

button1="UPDATE"
button2="Cancel"
icon="/tmp/elcapitan_icon.png"
title="Update Available: Install OS X El Capitan"
alignDescription="left" 
alignHeading="center"
defaultButton="2"
timeout="5"

loginwindow="/System/Library/CoreServices/loginwindow.app"
loginwindowCheck="/bin/ps -e | grep '$loginwindow' | grep -vc grep"

ScreenSaver="/System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/"
ScreenSaverCheck="/bin/ps -e | grep '$ScreenSaver' | grep -vc grep"

if [[ "$loginwindowCheck"=="0" || "$ScreenSaverCheck"=="0" ]]; then
    echo "The computer is not at the login window nor is the screen saver active."
    userChoice=$("$jamfHelper" -windowType "$windowType" -lockHUD -title "$title" -timeout "$timeout" -defaultButton "$defaultButton" -icon "$icon" -description "$description" -alignDescription "$alignDescription" -alignHeading "$alignHeading" -button1 "$button1" -button2 "$button2" 2>&1)
elif [[ "$loginwindowCheck"=="1" || "$ScreenSaverCheck"=="1" ]]; then
    echo "The computer is at the login window and/or has the screen saver active."
    exit 0
fi

#userChoice=$("$jamfHelper" -windowType "$windowType" -lockHUD -title "$title" -timeout "$timeout" -defaultButton "$defaultButton" -icon "$icon" -description "$description" -alignDescription "$alignDescription" -alignHeading "$alignHeading" -button1 "$button1" -button2 "$button2" 2>&1)

if [ "$userChoice" == "0" ]; then
    echo "$loggedInUser clicked UPDATE; now running OS X El Capitan Installer via JSS policy ID 547."
    jamf policy -id 547
elif [ "$userChoice" == "2" ]; then
    echo "$loggedInUser clicked Cancel or timeout was reached; now exiting."
    exit 0
fi

mm2270
Legendary Contributor III

Its not exactly how I would do it, but if it works, then it works.

For example, I tend to use ps axc | grep <something> which avoids needing to a grep -v later to exclude grep itself from the results. This avoids an extra process (pipe).

Second, I would probably just check to see who owns console, since you already need to get that up front. As I mentioned, when the loginwindow is up, console gets owned by root. I doubt very much any actual user account would be called "root" outside of the actual root account, but if you really wanted to be sure, you could get the UID of the logged in account. Only root would have a UID of 0.

loggedInUser=$(stat -f%Su /dev/console)
## Get the UID of the logged in account, or rather, who owns console
loggedInPID=$(id -u "$loggedInUser")

## Get a count of processes that match ScreenSaverEngine
ScreenSaverCheck=$(ps axc | grep "ScreenSaverEngine" | awk 'END {print NR}')

if [[ "$loggedInPID" != 0 ]] && [[ "$ScreenSaverCheck" == 0 ]]; then
     ## Someone is logged in and the screen saver isn't running. Continue
     <do your stuff here>
else
     ## Either the screen saver is running, or no-one is logged in, so exit
     exit 0
fi

But I'm just showing an alternate way to do it. There's no right or wrong, just different approaches, so by all means, if you like what you have and its working as you expect, then use it.

McLeanSchool
New Contributor III

I'm liking this script. Perhaps add in a check to make sure device is plugged in to power before the update runs using the following command?

pmset -g ps

sepiemoini
Contributor III
Contributor III

Thanks, @mm2270! This did the trick :)

#!/bin/bash

/usr/bin/curl -s -o /tmp/elcapitan_icon.png http://assets.materialup.com/uploads/ec819071-7140-4c6d-89ac-81b712642fcb/512x512bb-85.png
## Collect current logged in user
loggedInUser=$(stat -f%Su /dev/console)
## Collect the UID of $loggedInUser, or rather, who owns console
loggedInPID=$(id -u "$loggedInUser")

## Define JAMF Helper variables
jamfHelper="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
windowType="hud"
description="Your <Organization>-issued computer is not currently running the latest OS X version. To perform the OS X El Capitan update, select 'UPDATE' below and the upgrade will begin to run. Once complete, your computer will restart immediately. If you are unable to perform this update at the moment, please select 'Cancel.'

*Please save all working documents before selecting 'UPDATE.'

If you require assistance, please contact the Helpdesk by phone at <PhoneNumber> or by email at <EmailAddress>."

button1="UPDATE"
button2="Cancel"
icon="/tmp/elcapitan_icon.png"
title="Update Available: Install OS X El Capitan"
alignDescription="left" 
alignHeading="center"
defaultButton="2"
timeout="5"

## Collect a count of processes that match ScreenSaverEngine
ScreenSaverCheck=$(ps axc | grep "ScreenSaverEngine" | awk 'END {print NR}')

if [[ "$loggedInPID" != 0 ]] && [[ "$ScreenSaverCheck" == 0 ]]; then
     ## ScreenSaverEngine.app and/or loginwindow.app is/are not active; run JAMF Helper
     echo "The computer is not at the login window nor is the screen saver active."
     userChoice=$("$jamfHelper" -windowType "$windowType" -lockHUD -title "$title" -timeout "$timeout" -defaultButton "$defaultButton" -icon "$icon" -description "$description" -alignDescription "$alignDescription" -alignHeading "$alignHeading" -button1 "$button1" -button2 "$button2" 2>&1)
else
     ## ScreenSaverEngine.app and/or loginwindow.app is/are active; exit script
     echo "The computer is at the login window and/or has the screen saver active."
     exit 0
fi

## JAMF Helper functions for opt-in and opt-out options
if [ "$userChoice" == "0" ]; then
    echo "$loggedInUser clicked UPDATE; now running OS X El Capitan Installer via JSS policy ID 547."
    jamf policy -id 547
elif [ "$userChoice" == "2" ]; then
    echo "$loggedInUser clicked Cancel or timeout was reached; now exiting."
    exit 0
fi

rqomsiya
Contributor III

Hi all,

I ran across this and was trying to figure out a similar workflow, but instead of checking to see if no user is logged in, I was hoping to check to see if the user is logged in but at a locked screen.

swapple
Contributor III

Does 243 still work? Its nice to see when it times out vs clicks cancel

elif [ "$userChoice" == "243" ]; then
    echo "Timeout was reached; now exiting."
    exit 0