Posted on 04-13-2018 02:16 PM
With the goal of having better user interaction options that what is provided within Jamf's Patch Management Policies (not having the app quit 5 minutes later without warning) I have been testing different options with my existing update workflow and open source tools like Yo. I ended up using Alerter which will wait for user interaction within a script and allows the calling of a command with sudo permissions in order to execute a policy trigger.
I haven't deployed it to my fleet yet but figured I would see what feedback the community might have. It takes a 2 policies and 1 smart group per software title, which is a bit cumbersome, and currently never forces the update as the user could infinitely defer the installation if the app is never quit. I use a deferral counter for macOS software updates that could be integrated but I have not taken the time to do so yet.
I'm open to any and all feedback, thanks!
Setup Prior to Workflow
Script
By setting up the Script Parameters it can be adapted to any title
#!/bin/bash
# If app is open, alert user with the option to quit the app or defer for later. If user chooses to install it will quit the app, trigger the installation,
# then alert the user the policy is complete with the option to reopen the app. If the app is not open it will trigger the installation without alerting
# $4 = Title
# $5 = ParameterID
# $6 = Process Name
# $7 = Jamf Policy Event
# $8 = App Path
# Define currently logged in user
currentUser="$(ls -la /dev/console | cut -d " " -f 4)"
# Look if app is open via process name
appOpen="$(pgrep -ix "$6" | wc -l)"
if [[ $appOpen -gt 0 ]]; then
updateAnswer="$(/Library/Application Support/JAMF/alerter -title "$4" -sender $5 -message "must be quit in order to update. Save all data before quitting." -closeLabel Later -actions "Quit & Update")"
if [[ $updateAnswer == "Quit & Update" ]]; then
sudo -u $currentUser killall "$6"
jamf policy -event "$7"
reopenAnswer="$(/Library/Application Support/JAMF/alerter -title "$4" -sender "$5" -message "has been updated. Thank you." -closeLabel Ok -actions Reopen -timeout 60)"
if [[ $reopenAnswer == Reopen ]]; then
sudo -u $currentUser open "$8"
fi
else
echo "User deferred"
fi
else
jamf policy -event "$7"
fi
Policy
1. Create package that installs the alerter
executable to /Library/Application Support/JAMF/
2. Push pkg via policy to install Alerter pkg to All Manage Clients (or whatever scope will utilize this workflow)
Patch Management Title
Create a Patch Management Title for 'Google Chrome'. If the app you are looking to update is not available as a patch Management Title setup your smart group to have Application Version
instead of Patch Reporting
.
Testing Rings
To allow the update to be pushed out in rings for testing, pre-defined Static/Smart Groups are setup with the following logic:
Ring 1 - Smart Group based IT computers
Ring 2 - Static Group of manually selected group with various roles and use cases across organization, around 15-20% of computer count
Ring 3 - all computers not in Ring 1 or Ring 2
Workflow Setup
Smart Computer Group
Create a Smart Computer Group to scope to any computer with the app installed and not running the desired version
1) Smart Group name: *Google Chrome Smart Update
(Asterisk to keep Smart Update groups grouped at the top of your Smart Computer Group list)
2) Application Title
is
Google Chrome.app
3) Patch Reporting: Google Chrome
is not
65.0.3325.181
Policies
Create a Policy used to trigger the installation of the pkg
1) Policy name: Install Latest Google Chrome Trigger
2) Custom Trigger: install_googleChromeUpdate
3) Execution Frequency: Ongoing
4) Packages: GoogleChrome-65.0.3325.181.pkg
5) Scope: *Google Chrome Smart Update
6) Maintenance: Update Inventory
Create policy that will prompt user if app is open, install if it is not open
1) Policy Name: Install Latest Google Chrome Alerter
2) Scripts: Alerter App Updates
3) Parameter Values
a. Title: Google Chrome
b. Sender ID: com.google.chrome
c. Process Name: Google Chrome
d. Jamf Policy Event: install_googleChromeUpdate
e. App Path: /Applications/Google Chrome.app
4) Scope:
a. Target: *Google Chrome Smart Update
b. Exclusions: Ring 1
, Ring 2
, Ring 3
Ongoing Maintenance
When a new update is release the following maintenance would be required
1) Upload new pkg release for Google Chrome
2) Change Smart Computer Group the Patch Reporting version to new release number
3) Update the pkg within Install Latest Google Chrome Trigger
policy
4) Reset Ring Exclusions - Based on testing schedule remove a group from the exclusions as needed (start with Ring 2
and Ring 3
as excluded, one week later remove Ring 2
, one week after that remove Ring 3
)
Solved! Go to Solution.
Posted on 10-18-2018 11:33 AM
Realized I never posted what I finally settled on and put in production in case others want to give it a try. Been running with it for a while and seems to be working pretty well! Thanks for all the input and testing from others in the thread.
#!/bin/bash
# If app is open, alert user with the option to quit the app or defer for later. If user chooses to install it will quit the app, trigger the installation,
# then alert the user the policy is complete with the option to reopen the app. If the app is not open it will trigger the installation without alerting
# Quit and Open path have 2 entries for the times you are quiting/uninstalling an old version of an app that is replaced by a new name (for example quiting Adobe Acrobat Pro, which is replaced by Adobe Acorbat.app)
################################DEFINE VARIABLES################################
# $4 = Title
# $5 = App ID
# $6 = Process Name
# $7 = Jamf Policy Event
# $8 = Quit App Path
# $9 = Open App Path
#Defining the Sender ID as self service due to setting the Sender ID as the actual app being updated would often cause the app to crash
sender="com.jamfsoftware.selfservice.mac"
#Jamf parameters can't be passed into a function, redefining the app path to be used within the funciton
quitPath="$8"
openPath="$9"
################################SETUP FUNCTIONS TO CALL################################
fGetCurrenUser (){
currentUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");'`
# Identify the UID of the logged-in user
currentUserUID=`id -u "$currentUser"`
}
fQuitApp (){
cat > /private/tmp/quit_application.sh <<EOF
#!/bin/bash
/bin/launchctl asuser "$currentUserUID" /usr/bin/osascript -e 'tell application "$quitPath" to quit'
EOF
/bin/chmod +x /private/tmp/quit_application.sh
/bin/launchctl asuser "$currentUserUID" sudo -iu "$currentUser" "/private/tmp/quit_application.sh"
/bin/rm -f "/private/tmp/quit_application.sh"
}
fOpenApp (){
cat > /private/tmp/open_application.sh <<EOF
#!/bin/bash
/usr/bin/open "$openPath"
EOF
/bin/chmod +x /private/tmp/open_application.sh
/bin/launchctl asuser "$currentUserUID" sudo -iu "$currentUser" "/private/tmp/open_application.sh"
/bin/rm -f "/private/tmp/open_application.sh"
}
################################SETUP TIMER FILE################################
## Set up the software update time if it does not exist already
if [ ! -e /Library/Application Support/JAMF/.$5.timer.txt ]; then
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
fi
## Get the timer value
timer=`cat /Library/Application Support/JAMF/.$5.timer.txt`
################################ALERTER MESSAGE OPTIONS################################
saveQuitMSG="must be quit in order to update. Save all data before quitting."
updatedMSG="has been updated. Thank you."
################################START 'UPDATE WITH ALERTER' PROCESS################################
# Look if app is open via process name
appOpen="$(pgrep -ix "$6" | wc -l)"
# if the app is open and the defer timer is not zero
if [[ $appOpen -gt 0 && $timer -gt 0 ]]; then
fGetCurrenUser
updateAnswer="$(/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/alerter -title "$4" -sender "$sender" -message "$saveQuitMSG" -closeLabel "Defer ($timer)" -actions "Quit & Update" -timeout 3600)"
if [[ $updateAnswer == "Quit & Update" ]]; then
#quit app, install the update, then prompt the user when complete and ask if they want to reopen the app. Message will time out after 60 secs.
fQuitApp
/usr/local/bin/jamf policy -event "$7"
reopenAnswer="$(/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/alerter -title "$4" -sender "$sender" -message "$updatedMSG" -closeLabel Ok -actions Reopen -timeout 60)"
if [[ $reopenAnswer == Reopen ]]; then
fOpenApp
fi
#reset timer after updating
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
else
let CurrTimer=$timer-1
echo "User chose to defer"
echo "$CurrTimer" > /Library/Application Support/JAMF/.$5.timer.txt
echo "Defer count is now $CurrTimer"
exit 0
fi
# if app is open and defer timer has run out
elif [[ $appOpen -gt 0 && $timer == 0 ]]; then
fGetCurrenUser
/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/alerter -title "$4" -sender "$sender" -message "$saveQuitMSG" -actions "Quit & Update" -closeLabel "No Deferrals Left " -timeout 3600
fQuitApp
/usr/local/bin/jamf policy -event "$7"
reopenAnswer="$(/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/alerter -title "$4" -sender "$sender" -message "$updatedMSG" -closeLabel Ok -actions Reopen -timeout 60)"
if [[ $reopenAnswer == Reopen ]]; then
fOpenApp
fi
#reset timer after updating
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
else
# app is not open, reset timer and run updates
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
/usr/local/bin/jamf policy -event "$7"
fi
Posted on 06-07-2020 11:23 PM
hmm - it still just shows the same picture(see in botom). Script looks like below. It is been working probably before is it because some kind of files is some where hidden that it act like this and does not show defer option ?
Script I execute is this
#!/bin/bash
# If app is open, alert user with the option to quit the app or defer for later. If user chooses to install it will quit the app, trigger the installation,
# then alert the user the policy is complete with the option to reopen the app. If the app is not open it will trigger the installation without alerting
# Quit and Open path have 2 entries for the times you are quiting/uninstalling an old version of an app that is replaced by a new name (for example quiting Adobe Acrobat Pro, which is replaced by Adobe Acorbat.app)
################################DEFINE VARIABLES################################
title="Google Chrome"
appID="com.google.chrome"
process="Google Chrome"
policy="install_googleChromeUpdate"
openpath1="/Applications/Google Chrome.app"
quitpath1="/Applications/Google Chrome.app"
#Defining the Sender ID as self service due to setting the Sender ID as the actual app being updated would often cause the app to crash
sender="com.jamfsoftware.selfservice.mac"
#Jamf parameters can't be passed into a function, redefining the app path to be used within the funciton
quitPath="$8"
openPath="$9"
################################SETUP FUNCTIONS TO CALL################################
fGetCurrenUser (){
currentUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");'`
# Identify the UID of the logged-in user
currentUserUID=`id -u "$currentUser"`
}
fQuitApp (){
cat > /private/tmp/quit_application.sh <<EOF
#!/bin/bash
/bin/launchctl asuser "$currentUserUID" /usr/bin/osascript -e 'tell application "$quitPath" to quit'
EOF
/bin/chmod +x /private/tmp/quit_application.sh
/bin/launchctl asuser "$currentUserUID" sudo -iu "$currentUser" "/private/tmp/quit_application.sh"
/bin/rm -f "/private/tmp/quit_application.sh"
}
fOpenApp (){
cat > /private/tmp/open_application.sh <<EOF
#!/bin/bash
/usr/bin/open "$openPath"
EOF
/bin/chmod +x /private/tmp/open_application.sh
/bin/launchctl asuser "$currentUserUID" sudo -iu "$currentUser" "/private/tmp/open_application.sh"
/bin/rm -f "/private/tmp/open_application.sh"
}
################################SETUP TIMER FILE################################
## Set up the software update time if it does not exist already
if [ ! -e /Library/Application Support/JAMF/.$5.timer.txt ]; then
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
fi
## Get the timer value
timer=`cat /Library/Application Support/JAMF/.$5.timer.txt`
################################ALERTER MESSAGE OPTIONS################################
saveQuitMSG="must be quit in order to update. Save all data before quitting."
updatedMSG="has been updated. Thank you."
################################START 'UPDATE WITH ALERTER' PROCESS################################
# Look if app is open via process name
appOpen="$(pgrep -ix "$6" | wc -l)"
# if the app is open and the defer timer is not zero
if [[ $appOpen -gt 0 && $timer -gt 0 ]]; then
fGetCurrenUser
updateAnswer="$(/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/alerter -title "$4" -sender "$sender" -message "$saveQuitMSG" -closeLabel "Defer ($timer)" -actions "Quit & Update" -timeout 3600)"
if [[ $updateAnswer == "Quit & Update" ]]; then
#quit app, install the update, then prompt the user when complete and ask if they want to reopen the app. Message will time out after 60 secs.
fQuitApp
/usr/local/bin/jamf policy -event "$7"
reopenAnswer="$(/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/alerter -title "$4" -sender "$sender" -message "$updatedMSG" -closeLabel Ok -actions Reopen -timeout 60)"
if [[ $reopenAnswer == Reopen ]]; then
fOpenApp
fi
#reset timer after updating
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
else
let CurrTimer=$timer-1
echo "User chose to defer"
echo "$CurrTimer" > /Library/Application Support/JAMF/.$5.timer.txt
echo "Defer count is now $CurrTimer"
exit 0
fi
# if app is open and defer timer has run out
elif [[ $appOpen -gt 0 && $timer == 0 ]]; then
fGetCurrenUser
/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/alerter -title "$4" -sender "$sender" -message "$saveQuitMSG" -actions "Quit & Update" -closeLabel "No Deferrals Left " -timeout 3600
fQuitApp
/usr/local/bin/jamf policy -event "$7"
reopenAnswer="$(/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/alerter -title "$4" -sender "$sender" -message "$updatedMSG" -closeLabel Ok -actions Reopen -timeout 60)"
if [[ $reopenAnswer == Reopen ]]; then
fOpenApp
fi
#reset timer after updating
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
else
# app is not open, reset timer and run updates
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
/usr/local/bin/jamf policy -event "$7"
fi
Posted on 06-08-2020 01:19 AM
What version of Alerter are you using? I haven't upgraded yet. Version 2 seems to work for me.
Posted on 06-08-2020 02:04 AM
have downloaded the latest with catalina support and also worked before. I guess there must be somekind of trigger that causes this message to show instead of the defer option
Posted on 01-07-2021 02:43 AM
Anyone got this working in Big Sur ?. I see the same issue as @Captainamerica I see the notification, but there is not any defer or install button that is seen ?
Posted on 01-07-2021 03:14 AM
Update: It seems the button are now in the "option" dropdown, but the option button does not appear before hovering on it - not to smart. but I just want the buttons to be shown right away as it used to work ?!
Posted on 01-07-2021 08:35 AM
@jameson Looks like is an Apple notification change, not Alerter. The same thing applies for certain native Apple notifications, but not ones like AirDrop receiving.
One project I haven't taken the time to test out but might have different results would be Notifier by dataJAR. Biggest difference I've seen so far is if you want custom logos you would have to modify the Xcode project and re-sign it since it is an App.
Posted on 01-07-2021 10:16 PM
The strange thing is that the alerter notifications does not stay active on the screen but dissapear again. Before Big Sur they stayed active until user did something. If that just could work it would be usable
Posted on 01-08-2021 08:36 AM
@jameson How long until they disappear for you? I'm not having that experience, or at least yet. It's been about 20min and my test notification is still there while I continue to work.
Posted on 01-10-2021 10:27 PM
It just stay 2-3 seconds and then dissapear. Can you try and show the script you are using, so I can compare. I am on Big sur BTW.
EDIT: also tried to test on catalina 10.15.7 - but then just got an message that "alerter will damage the computer". even the file is not in qurantine. So if it works for you which version of alerter do you use ? - I have downloaded the latest on the github that should support big sur
Posted on 01-11-2021 08:12 AM
@jameson I haven't started deploying the newest version of Alerter, but I am running Big Sur on my computer with Alerter working without issue and a lot of our fleet is on 10.15.7 and I haven't heard or noticed any issues.
Here's what I use in my script, with variables being either defined within the policy script options or in a different section of the script:
/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/alerter -title "$4" -sender "$sender" -message "$saveQuitMSG" -closeLabel "Defer ($timer)" -actions "Quit & Update" -timeout 3600)
Posted on 01-11-2021 10:04 AM
Thanks - can you try and paste the hole script. Do you have any PPPC etc made ?
EDIT: I got this working now. Thanks
Posted on 01-11-2021 10:52 AM
This should still be accurate, with the only difference I can think of is I now use com.apple.AppStore
as the Sender ID for all alerts. I wonder if that could be part of your issue? I know at one point I was having crashing errors if I used the actual app ID of the app I was trying to update so I switched to have all use the App Store assuming that it probably wasn't open and would provide an App Icon with the impression of a legit app update being requested.
Posted on 01-11-2021 10:47 PM
I got it working with the new big sur release and did remove the quarantine flag on the file. But you write that you still use the old alerter release (and not the one that was released 3 weeks ago). But the old one will not work on big sur and is catched as malware, for me. So that wonders me you can get this working, unless of course you have disabled something on the build in spam catcher (if that is even possible to do)
Posted on 01-12-2021 10:59 AM
Not doing anything special besides deploying it via a pkg that puts in in the Jamf Application Support folder, not sure what would cause the difference in behavior.
Posted on 03-25-2021 01:31 AM
Anyone still using this on big sur ?. is A PPPC needed so the alerter notification will be showed ? Actually have a strange issue, where on one big sur client the notification from alerter appear, while on another mac also on big sur the message does not appear
Posted on 03-25-2021 10:12 AM
Just last week my computer started flagging Alerter for malware but I have not seen any other reports in our fleet seeing the same behavior. Even tried grabbing the more recent release and it is flagged as well. I have had it included in our Notifications payload since the beginning so there shouldn't be any connection between approving the notifications and it getting flagged.
Due to this issue, I have rewritten the process to use JamfHelper as it will be a more reliable method going forward. Definitely not the same interface I would prefer but it seems the most future proof method at this time. I haven't deployed it yet or done all my testing with it but seems to be keep the desired behavior.
The basic command structure I'm using in the script is this, note I have added a new Script variable for App Icon Path that calls on the .icns file within each app's App Bundle:
/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -heading "Update Available" -description "$4 must be quit in order to update. Save all data before quitting." -button1 "Quit & Update" -button2 "Defer ($timer)" -timeout 3600
Posted on 03-25-2021 01:18 PM
OK. What I think is really strange that I use the exact same policy and on one big sur it works as expected and other not?. Have you tried it on M1 mac´s, as it is actually on M1 I see the issue where the notification never show up
Posted on 03-26-2021 12:28 AM
I have tried to change to jamf helper - but seems something is wrong
#!/bin/sh
#!/bin/bash
# If app is open, alert user with the option to quit the app or defer for later. If user chooses to install it will quit the app, trigger the installation,
# then alert the user the policy is complete with the option to reopen the app. If the app is not open it will trigger the installation without alerting
# Quit and Open path have 2 entries for the times you are quiting/uninstalling an old version of an app that is replaced by a new name (for example quiting Adobe Acrobat Pro, which is replaced by Adobe Acorbat.app)
################################DEFINE VARIABLES################################
#$4 = Title
#$5 = App ID
#$6 = Process Name
#$7 = Jamf Policy Event
#$8 = Quit App Path
#$9 = Open App Path
quitPath="$8"
openPath="$9"
################################SETUP FUNCTIONS TO CALL################################
fGetCurrenUser (){
currentUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");'`
# Identify the UID of the logged-in user
currentUserUID=`id -u "$currentUser"`
}
fQuitApp (){
cat > /private/tmp/quit_application.sh <<EOF
#!/bin/bash
/bin/launchctl asuser "$currentUserUID" /usr/bin/osascript -e 'tell application "$quitPath" to quit'
EOF
/bin/chmod +x /private/tmp/quit_application.sh
/bin/launchctl asuser "$currentUserUID" sudo -iu "$currentUser" "/private/tmp/quit_application.sh"
/bin/rm -f "/private/tmp/quit_application.sh"
}
fOpenApp (){
cat > /private/tmp/open_application.sh <<EOF
#!/bin/bash
/usr/bin/open "$openPath"
EOF
/bin/chmod +x /private/tmp/open_application.sh
/bin/launchctl asuser "$currentUserUID" sudo -iu "$currentUser" "/private/tmp/open_application.sh"
/bin/rm -f "/private/tmp/open_application.sh"
}
################################SETUP TIMER FILE################################
## Set up the software update time if it does not exist already
if [ ! -e /Library/Application Support/JAMF/.$5.timer.txt ]; then
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
fi
## Get the timer value
timer=$(cat /Library/Application Support/JAMF/.$5.timer.txt)
################################ALERTER MESSAGE OPTIONS################################
################################START 'UPDATE WITH ALERTER' PROCESS################################
# Look if app is open via process name
appOpen=$(pgrep -ix "Google Chrome" | wc -l)
# if the app is open and the defer timer is not zero
if [[ $appOpen -gt 0 && $timer -gt 0 ]]; then
fGetCurrenUser
updateAnswer="$(/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -heading "Update Available" -description "Micorosoft Outlook must be quit in order to update. Save all data before quitting." -button1 "Quit & Update" -button2 "Defer ($timer)" -timeout 3600)
if [[ $updateAnswer == "Quit & Update" ]]; then
#quit app, install the update, then prompt the user when complete and ask if they want to reopen the app. Message will time out after 60 secs.
fQuitApp
/usr/local/bin/jamf policy -event "$7"
reopenAnswer="$(/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -heading "Update Available" -description "Micorosoft Outlook must be quit in order to update. Save all data before quitting." -button1 "Quit & Update" -button2 "Defer ($timer)" -timeout 3600)
if [[ $reopenAnswer == Reopen ]]; then
fOpenApp
fi
#reset timer after updating
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
else
let CurrTimer=$timer-1
echo "User chose to defer"
echo "$CurrTimer" > /Library/Application Support/JAMF/.$5.timer.txt
echo "Defer count is now $CurrTimer"
exit 0
fi
# if app is open and defer timer has run out
elif [[ $appOpen -gt 0 && $timer == 0 ]]; then
fGetCurrenUser
/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -heading "Update Available" -description "Micorosoft Outlook must be quit order to update. Save all data before quitting" -button1 "Quit & Update" -button2 "Defer ($timer)" -timeout 3600)
fQuitApp
/usr/local/bin/jamf policy -event "$7"
reopenAnswer="$(/bin/launchctl asuser "$currentUserUID" /Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -heading "Update Available" -description "Micorosoft Outlook must be quit in order to update. Save all data before quitting." -button1 "Quit & Update" -button2 "Defer ($timer)" -timeout 3600)
if [[ $reopenAnswer == Reopen ]]; then
fOpenApp
fi
#reset timer after updating
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
else
# app is not open, reset timer and run updates
echo "2" > /Library/Application Support/JAMF/.$5.timer.txt
/usr/local/bin/jamf policy -event "$7"
fi
Posted on 03-26-2021 10:35 AM
You would also have to update the if
statements since JamfHelper's output is different than Alerter and I don't think it hurts having it but JamfHelper doesn't require the launchctl asuser
aspect. Here's my full script that I've been playing with so far:
#!/bin/bash
# If app is open, alert user with the option to quit the app or defer for later. If user chooses to install it will quit the app, trigger the installation,
# then alert the user the policy is complete with the option to reopen the app. If the app is not open it will trigger the installation without alerting
################################DEFINE VARIABLES################################
# $4 = Title
# $5 = App ID
# $6 = Process Name
# $7 = App Icon Path
# $8 = Jamf Policy Event
# $9 = Quit App Path
# $10 = Open App Path
#Jamf parameters can't be passed into a function, redefining the app path to be used within the funciton
iconPath="$7"
quitPath="$9"
openPath="$10"
################################SETUP FUNCTIONS TO CALL################################
fGetCurrenUser (){
currentUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");'`
# Identify the UID of the logged-in user
currentUserUID=`id -u "$currentUser"`
}
fCheckAppIconPath (){
#Check if iconPath is still valid, use PLNU logo if not found
if [ -f "$iconPath" ]; then
echo "App Icon Path still valid"
else
echo "App Icon not found, use generic logo"
iconPath="/Applications/App Store.app/Contents/Resources/AppIcon.icns"
fi
}
fQuitApp (){
cat > /private/tmp/quit_application.sh <<EOF
#!/bin/bash
/bin/launchctl asuser "$currentUserUID" /usr/bin/osascript -e 'tell application "$quitPath" to quit'
EOF
/bin/chmod +x /private/tmp/quit_application.sh
/bin/launchctl asuser "$currentUserUID" sudo -iu "$currentUser" "/private/tmp/quit_application.sh"
/bin/rm -f "/private/tmp/quit_application.sh"
}
fOpenApp (){
cat > /private/tmp/open_application.sh <<EOF
#!/bin/bash
/usr/bin/open "$openPath"
EOF
/bin/chmod +x /private/tmp/open_application.sh
/bin/launchctl asuser "$currentUserUID" sudo -iu "$currentUser" "/private/tmp/open_application.sh"
/bin/rm -f "/private/tmp/open_application.sh"
}
################################SETUP TIMER FILE################################
## Set up the software update time if it does not exist already
if [ ! -e /Library/Application Support/JAMF/.$5.timer ]; then
echo "2" > /Library/Application Support/JAMF/.$5.timer
fi
## Get the timer value
timer=`cat /Library/Application Support/JAMF/.$5.timer`
################################ALERTER MESSAGE OPTIONS################################
saveQuitMSG="must be quit in order to update. Save all data before quitting."
updatedMSG="has been updated. Thank you."
################################START 'UPDATE WITH ALERTER' PROCESS################################
# Look if app is open via process name
appOpen="$(pgrep -ix "$6" | wc -l)"
# if the app is open and the defer timer is not zero
if [[ $appOpen -gt 0 && $timer -gt 0 ]]; then
fGetCurrenUser
fCheckAppIconPath
updateAnswer="$(/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -heading "Update Available" -description "$4 must be quit in order to update. Save all data before quitting." -button1 "Quit & Update" -button2 "Defer ($timer)" -timeout 3600)"
if [[ $updateAnswer == "0" ]]; then
#quit app, install the update, then prompt the user when complete and ask if they want to reopen the app. Message will time out after 60 secs.
fQuitApp
/usr/local/bin/jamf policy -event "$8"
reopenAnswer="$(/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -description "$4 has been updated" -button1 "Reopen" -button2 "Ok" -timeout 60)"
if [[ $reopenAnswer == "0" ]]; then
fOpenApp
fi
#reset timer after updating
echo "2" > /Library/Application Support/JAMF/.$5.timer
else
let CurrTimer=$timer-1
echo "User chose to defer"
echo "$CurrTimer" > /Library/Application Support/JAMF/.$5.timer
echo "Defer count is now $CurrTimer"
exit 0
fi
# if app is open and defer timer has run out
elif [[ $appOpen -gt 0 && $timer == 0 ]]; then
fGetCurrenUser
fCheckAppIconPath
/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -heading "Update Available" -description "$4 must be quit in order to update. Save all data before quitting." -button1 "Quit & Update" -button2 "No Deferrals Left" -timeout 3600
fQuitApp
/usr/local/bin/jamf policy -event "$8"
reopenAnswer="$(/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -description "$4 has been updated" -button1 "Reopen" -button2 "Ok" -timeout 60)"
if [[ $reopenAnswer == "0" ]]; then
fOpenApp
fi
#reset timer after updating
echo "2" > /Library/Application Support/JAMF/.$5.timer
else
# app is not open, reset timer and run updates
echo "2" > /Library/Application Support/JAMF/.$5.timer
/usr/local/bin/jamf policy -event "$8"
fi
Posted on 03-28-2021 04:57 AM
Great thanks - I will give it a go
Posted on 03-30-2021 08:31 AM
Thanks a lot
Posted on 03-31-2021 10:18 AM
Just discovered one issue with the script above when performing the reopen process: the $10
parameter needs to be ${10}
. It was interpreting $1
and then a 0
, so it it became /0
.
Edit line 20 to be:
openPath="${10}"
Posted on 04-09-2021 07:28 AM
this looks pretty slick mac@ibm-notification-tool
Posted on 04-09-2021 10:23 AM
Whoa, nice. Playing with it a little and it seems like the notification appears and then hides pretty quickly where our goal would be to have the notification stay on screen. The -timeout
option only applies to the Pop-Up option and not the notification banner. I'll definitely keep an eye on this project to see where it goes, thanks for the reference!
Posted on 04-12-2021 02:11 AM
cool
Posted on 04-20-2021 06:35 AM
Has anyone played around with making this script be able to close multiple apps? For example for Acrobat Reader update you need Reader and Safari to be closed I believe.
Posted on 06-11-2021 01:45 AM
Funny - I am having the exact same issue. I guess the key is this one, if there can be build in more applications
appOpen="$(pgrep -ix "$6" | wc -l)"
Posted on 07-14-2021 04:06 PM
Anyone else running into this notarization issue and have a fix? I tried creating a new package for version .004 of alerter and signing the package with our Developer ID and it's still throwing this prompt on 11.4 😞 Thanks!
Posted on 11-15-2021 06:13 AM
Hi @kendalljjohnson this looks very useful, going to test it out. Can you post the most recent version of the script you are using with JAMF Helper?
nice work!
Posted on 11-15-2021 08:11 AM
Yeah @tender, no problem. Good opportunity to make sure my comments are up to date!
#!/bin/bash
# If app is open, alert user with the option to quit the app or defer for later. If user chooses to install it will quit the app, trigger the installation,
# then alert the user the policy is complete with the option to reopen the app. If the app is not open it will trigger the installation without alerting
################################DEFINE VARIABLES################################
# $4 = Title
# Example: "Google Chrome"
# $5 = App ID
# Example: "com.google.chrome"
# $6 = Process Name
# Example: "Google Chrome"
# $7 = App Icon Path
# Example: "/Applications/Google Chrome.app/Contents/Resources/app.icns"
# $8 = Jamf Policy Event
# Example: "install_googleChromeUpdate"
# $9 = Quit App Path
# Example: "/Applications/Google Chrome.app"
# $10 = Open App Path
# Example: "/Applications/Google Chrome.app"
#Jamf parameters can't be passed into a function, redefining the app path to be used within the funciton
iconPath="$7"
quitPath="$9"
openPath="${10}"
################################SETUP FUNCTIONS TO CALL################################
fGetCurrenUser (){
currentUser=`/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'`
# Identify the UID of the logged-in user
currentUserUID=`id -u "$currentUser"`
}
fCheckAppIconPath (){
#Check if iconPath is still valid, use App Store logo if not found
if [ -f "$iconPath" ]; then
echo "App Icon Path still valid"
else
echo "App Icon not found, use generic logo"
iconPath="/Applications/App Store.app/Contents/Resources/AppIcon.icns"
fi
}
fQuitApp (){
cat > /private/tmp/quit_application.sh <<EOF
#!/bin/bash
/bin/launchctl asuser "$currentUserUID" /usr/bin/osascript -e 'tell application "$quitPath" to quit'
EOF
/bin/chmod +x /private/tmp/quit_application.sh
/bin/launchctl asuser "$currentUserUID" sudo -iu "$currentUser" "/private/tmp/quit_application.sh"
/bin/rm -f "/private/tmp/quit_application.sh"
}
fOpenApp (){
cat > /private/tmp/open_application.sh <<EOF
#!/bin/bash
/usr/bin/open "$openPath"
EOF
/bin/chmod +x /private/tmp/open_application.sh
/bin/launchctl asuser "$currentUserUID" sudo -iu "$currentUser" "/private/tmp/open_application.sh"
/bin/rm -f "/private/tmp/open_application.sh"
}
################################SETUP TIMER FILE################################
## Set up the software update time if it does not exist already
if [ ! -e /Library/Application\ Support/JAMF/.$5.timer ]; then
echo "2" > /Library/Application\ Support/JAMF/.$5.timer
fi
## Get the timer value
timer=`cat /Library/Application\ Support/JAMF/.$5.timer`
################################ALERT MESSAGE OPTIONS################################
saveQuitMSG="must be quit in order to update. Save all data before quitting."
updatedMSG="has been updated. Thank you."
################################START 'UPDATE WITH JAMFHELPER' PROCESS################################
# Look if app is open via process name
appOpen="$(pgrep -ix "$6" | wc -l)"
# if the app is open and the defer timer is not zero
if [[ $appOpen -gt 0 && $timer -gt 0 ]]; then
fGetCurrenUser
fCheckAppIconPath
updateAnswer="$(/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -heading "Update Available" -description "$4 must be quit in order to update. Save all data before quitting." -button1 "Quit & Update" -button2 "Defer ($timer)" -timeout 3600)"
if [[ $updateAnswer == "0" ]]; then
#quit app, install the update, then prompt the user when complete and ask if they want to reopen the app. Message will time out after 60 secs.
fQuitApp
/usr/local/bin/jamf policy -event "$8"
reopenAnswer="$(/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -description "$4 has been updated" -button1 "Reopen" -button2 "Ok" -timeout 60)"
if [[ $reopenAnswer == "0" ]]; then
fOpenApp
fi
#reset timer after updating
echo "2" > /Library/Application\ Support/JAMF/.$5.timer
else
let CurrTimer=$timer-1
echo "User chose to defer"
echo "$CurrTimer" > /Library/Application\ Support/JAMF/.$5.timer
echo "Defer count is now $CurrTimer"
exit 0
fi
# if app is open and defer timer has run out
elif [[ $appOpen -gt 0 && $timer == 0 ]]; then
fGetCurrenUser
fCheckAppIconPath
/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -heading "Update Available" -description "$4 must be quit in order to update. Save all data before quitting." -button1 "Quit & Update" -button2 "No Deferrals Left" -timeout 3600
fQuitApp
/usr/local/bin/jamf policy -event "$8"
reopenAnswer="$(/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -windowPosition ur -icon "$iconPath" -iconSize 50 -description "$4 has been updated" -button1 "Reopen" -button2 "Ok" -timeout 60)"
if [[ $reopenAnswer == "0" ]]; then
fOpenApp
fi
#reset timer after updating
echo "2" > /Library/Application\ Support/JAMF/.$5.timer
else
# app is not open, reset timer and run updates
echo "2" > /Library/Application\ Support/JAMF/.$5.timer
/usr/local/bin/jamf policy -event "$8"
fi
Posted on 11-15-2021 05:21 PM
Thanks @kendalljjohnson, I am working on adapting this to my needs. Great stuff you put together in your script.
-steven
Posted on 05-23-2022 01:11 PM
Am I correct in understanding that using this alternative workflow would mean that a pending patch would not appear in Self Service.app? For example:
Is that correct or am I missing something? The user would only ever have the opportunity to trigger the update when the script runs and asks them?
Posted on 05-24-2022 08:35 AM
@allpurposeben Correct, I never built in a logic for Self Service. It would need to be a separate policy created since the alerting policy is only available to be run once a day. Theoretically you could clone the daily alerting policy but change it to be ongoing within Self Service, using the same scope of only available to those not on the current version.