Restarting Computer Within JAMF Helper Script

sepiemoini
Contributor III

JAMF Nation folks! I am in need of some advice on how to restart a computer within a if-else/else-if loop of a JAMF Helper script. The script's purpose is to perform software and security updates and then reboot the computer if the user decides to opt in. If not, an echo command is sent and they'll be prompted again the following day. The opt-in and opt-out portions work great and the updates are applied. The only issue here is with the actual restarting of the computer.

if [ "$userChoice" == "0" ]; then
   echo "User clicked UPDATE; now downloading and installing all available updates."
   softwareupdate --install --all
   osascript -e 'tell application "System Events" to restart'
elif [ "$userChoice" == "2" ]; then
   echo "User clicked Cancel or timeout was reached; now exiting."
   exit 0    
fi

The problematic line is osascript -e 'tell application "System Events" to restart'. An error is generated as well within the JSS logs. Here's the error that is received.

36:43: execution error: An error of type -10810 has occurred. (-10810)

The error here pertains to access rights and not being able to run with elevated permissions--i.e. sudo. Is there a work-around to get this to restart?
53f61b988a444a60a7d62d270d9e7d4d

2 ACCEPTED SOLUTIONS

sepiemoini
Contributor III

This did the trick!

osascript -e 'tell app "loginwindow" to «event aevtrrst»'

ce821d87ce0d479a85de03b190e65cde

View solution in original post

sepiemoini
Contributor III

@hcodfrie As requested, here you go!

#!/bin/bash

# Grab icon image from specified URL and place into /tmp
/usr/bin/curl -s -o /tmp/lock_icon.png http://core0.staticworld.net/images/article/2014/11/security-and-privacy-icon-100529575-large.png
loggedInUser=$(stat -f%Su /dev/console)
jamfHelper="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
windowType="hud"
description="There is a critical security update avaialble for your <CompanyName>-issued computer. To perform the update, select 'UPDATE' below and the security update will begin to run. Once complete, you will be prompted to 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/lock_icon.png"
title="Critical: Apple Security Update Available"
alignDescription="left" 
alignHeading="center"
defaultButton="2"
timeout="900"

# JAMF Helper window as it appears for targeted computers
userChoice=$("$jamfHelper" -windowType "$windowType" -lockHUD -title "$title" -timeout "$timeout" -defaultButton "$defaultButton" -icon "$icon" -description "$description" -alignDescription "$alignDescription" -alignHeading "$alignHeading" -button1 "$button1" -button2 "$button2")

# If user selects "UPDATE"
if [ "$userChoice" == "0" ]; then
   echo "User clicked UPDATE; now downloading and installing all available updates."
   # Install ALL available software and security updates
   softwareupdate --install --all
   # Present user with 60 second countdown to restart computer; user may opt out of restart
   osascript -e 'tell app "loginwindow" to «event aevtrrst»'
# If user selects "Cancel"
elif [ "$userChoice" == "2" ]; then
   echo "User clicked Cancel or timeout was reached; now exiting."
   exit 0    
fi

Here's the policy that the above script is being used in. Pretty basic stuff here; once per day at recurring check-in with a smart computer group and an inventory update at the end.

2691a57c64f44126acb4b02db625e613

This is the smart computer group that I am using. Right now, I am in testing so it's scoped to the "it-15434" computer. When I am ready to go live in production, I will remove this line. You'll also noticed the other nested computer group being used. The "OS X Yosemite 10.10.5, El Capitan 10.11.6" is pretty self-explanatory but I've used it elsewhere so thought of just using it again here instead of specifying the same criteria again.

8c2f9a3e3c4d415cbaf8a9665bebb2b7

And lastly, here's the restart window. Hope this helps 🙂

osascript -e 'tell app "loginwindow" to «event aevtrrst»'

4a32e811b4bc4c48b39b17c00fccb3ed

View solution in original post

20 REPLIES 20

sepiemoini
Contributor III

This did the trick!

osascript -e 'tell app "loginwindow" to «event aevtrrst»'

ce821d87ce0d479a85de03b190e65cde

View solution in original post

talkingmoose
Honored Contributor II

You're using osascript, which is essentially running an AppleScript command inside your shell script. I suggest instead using the shutdown command directly within your shell script:

shutdown -r now

hcodfrie
Contributor

Hi @sepiemoini interested in the rest of that script since i was working to do the same yesterday 🙂

sepiemoini
Contributor III

@hcodfrie As requested, here you go!

#!/bin/bash

# Grab icon image from specified URL and place into /tmp
/usr/bin/curl -s -o /tmp/lock_icon.png http://core0.staticworld.net/images/article/2014/11/security-and-privacy-icon-100529575-large.png
loggedInUser=$(stat -f%Su /dev/console)
jamfHelper="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
windowType="hud"
description="There is a critical security update avaialble for your <CompanyName>-issued computer. To perform the update, select 'UPDATE' below and the security update will begin to run. Once complete, you will be prompted to 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/lock_icon.png"
title="Critical: Apple Security Update Available"
alignDescription="left" 
alignHeading="center"
defaultButton="2"
timeout="900"

# JAMF Helper window as it appears for targeted computers
userChoice=$("$jamfHelper" -windowType "$windowType" -lockHUD -title "$title" -timeout "$timeout" -defaultButton "$defaultButton" -icon "$icon" -description "$description" -alignDescription "$alignDescription" -alignHeading "$alignHeading" -button1 "$button1" -button2 "$button2")

# If user selects "UPDATE"
if [ "$userChoice" == "0" ]; then
   echo "User clicked UPDATE; now downloading and installing all available updates."
   # Install ALL available software and security updates
   softwareupdate --install --all
   # Present user with 60 second countdown to restart computer; user may opt out of restart
   osascript -e 'tell app "loginwindow" to «event aevtrrst»'
# If user selects "Cancel"
elif [ "$userChoice" == "2" ]; then
   echo "User clicked Cancel or timeout was reached; now exiting."
   exit 0    
fi

Here's the policy that the above script is being used in. Pretty basic stuff here; once per day at recurring check-in with a smart computer group and an inventory update at the end.

2691a57c64f44126acb4b02db625e613

This is the smart computer group that I am using. Right now, I am in testing so it's scoped to the "it-15434" computer. When I am ready to go live in production, I will remove this line. You'll also noticed the other nested computer group being used. The "OS X Yosemite 10.10.5, El Capitan 10.11.6" is pretty self-explanatory but I've used it elsewhere so thought of just using it again here instead of specifying the same criteria again.

8c2f9a3e3c4d415cbaf8a9665bebb2b7

And lastly, here's the restart window. Hope this helps 🙂

osascript -e 'tell app "loginwindow" to «event aevtrrst»'

4a32e811b4bc4c48b39b17c00fccb3ed

View solution in original post

mm2270
Legendary Contributor II

@sepiemoini Any particular reason for curling down that icon, when it exists on any recent OS X system by default? Its in the following path:

/System/Library/CoreServices/loginwindow.app/Contents/Resources/FileVault_logo.tiff

Its possible in some versions of OS X its not a .tiff. but a .png format or other, but in general that path should work.

Its also in the following path as well, although its an icns format, and somehow looks slightly different than the tiff version.

/System/Library/PreferencePanes/Security.prefPane/Contents/Resources/FileVault.icns

You should be able to use either one of those as a path to the icon with jamfHelper.

sepiemoini
Contributor III

@mm2270 Greetings! Using .icns files isn't ideal as the best file format, in my experience, has been using .png files. Since users will need network connectivity to check-in and run the script/software updates, I didn't see the harm in using ones online. I guess I could package an icon bundle and deploy those; that'd be pretty cool, eh?

hcodfrie
Contributor

Thanks

jhuls
Contributor III

@talkingmoose I've used the "reboot" command for something similar. Is there an advantage of using "shutdown -r now" over it that you're aware of?

jhuls
Contributor III

@sepiemoini Thanks for posting your script. I do have a question about your policy though.

Does the inventory update actually serve a purpose? From what I can tell your script is going to run and then either reboot or not reboot. If it doesn't reboot, the inventory would be unchanged. If it does reboot, doesn't it reboot before gathering the inventory?

If I'm wrong on this, feel free to say. I worked on something similar once and the inventory aspect just didn't seem to work that way for me so I have my systems all currently set to update inventory each time they start up. If I'm right, I guess it doesn't hurt anything functionally but am curious if it really works for you.

sepiemoini
Contributor III

@jhuls Our environment is not terribly large and the added inventory traffic does not contribute to a significant load on our server or network. I typically configure this payload so that dynamic group memberships are updated following the completion of certain actions. Does that answer your question?

jhuls
Contributor III

@sepiemoini Not really. Hopefully long story short I'm interested in knowing how the Update Inventory portion of the policy would completely run if the script that runs before it has told the computer to restart. I can see where in some cases it might still collect the inventory before it shuts down on the restart but it doesn't seem like it would be reliable in some cases. Like I said I had some trouble with it in the past for a script that did a restart.

sepiemoini
Contributor III

@jhuls Upon deeper investigation, it in fact, is not doing much for reasons that you raised. A separated "Update Inventory" policy which runs once per day is kicking in after the software update policy runs. I'll keep this in mind for future policies instead of relying on muscle memory. Thanks for the suggestion/input!

sepiemoini
Contributor III

@mm2270 @jhuls On a related note with another JAMF Helper script, is it possible to run a sudo command within this script? Say if I wanted to run a JSS policy based on the user's input?

#!/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 <CompanyName>-issued computer is not currently running the latest OS X version. To perform the update, select 'UPDATE' below and the security update will begin to run. Once complete, you will be prompted to 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"
cancelButton="2"
timeout="300"

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

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

The problematic line being this one:

sudo jamf policy -id 547

sepiemoini
Contributor III

Ahhh worth noting that when I created a test JSS policy, I am all set -- please ignore the above post 🙂

talkingmoose
Honored Contributor II

@jhuls, both commands will restart the Mac. Using the osascript command, you will get the dialog prompting to press a button to complete the restart. That may or may not be what you want.

I mentioned using the "shutdown" command because it just reduces complexity in your script. You started in bash but dipped into AppleScript (another scripting language) by calling the osascript command. My advice for anyone creating scripts is to do as much in one language as possible and only call another scripting language when necessary.

The less complex your code, the easier it is to read and troubleshoot.

Not applicable

@sepiemoini

The script works great, is it possible to add an option of two deferrals of 1-4 hours each before a forced restart.

Many thanks

EdLuo
Contributor

@dmhlanga008

Instead of deferrals for restart, we use the deferrals option for installing updates. If interested, read on.

Deferrals is not working correctly in policies but we manage to work around the bug by setting the policy frequency to ongoing and scoping to a smart group that have pending updates. See discussion here regarding the deferral bug...
Link

If you are running JSS 9.96, you will have to work around another bug. The Software Update count does not show the proper number of updates available. The workaround is shown in forum link below...
Link

Once updates are installed and system reboot, another policy is needed to remove the system form the smart group. To do so we have an ongoing policy that runs on login to update inventory, scoped to the same smart group that have pending updates.

Summary of our Install Apple Critical Updates policy.
71cb9fe3ce8649798b19ebd32728e283

kadams
Contributor

@dmhlanga008 I need the exact same thing. I need a deferral option for users. I need a force restart after a set amount of time as well..

Cayde-6
Valued Contributor

Ditto here, we are currently making a script of this exact process

mojo21221
Contributor II

@sepiemoini Love the script. We have recently had some push back from our more vocal associates on not wanting to have their updates forced upon them. This script does exactly what we needed. A gentle "Nudge" so to say update your darn MAC... Also utilizing it in combo with a second script to kick off in place upgraded. Instead of using the policy id I am using custom triggers. But anyway, just wanted to say thanks.