#!/bin/sh
HELPER=`/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -icon /Library/Application Support/JAMF/bin/jamfHelper.app/Contents/Resources/Message.png -heading "Software Updates are Available" -description "Would you like to install updates? System may need to be rebooted." -button2 "Install" -button1 "Cancel" -cancelButton "1"`
echo"jamf helper result was $HELPER";
if [ "$HELPER" == "2" ]; then
/usr/sbin/jamf policy -trigger SWUJH
exit0elseecho"user chose No";
exit1fi
I also tweaked the cancel button due to when I was using it in it's default form everything returned "user chose No" and it wouldn't run the trigger.
Now when I select install, the box disappears then immediately reappears and I have to choose install again, and then teh box stays gone, but the trigger never starts the updates.
Best answer by acdesigntech
Hey John, I went a few steps further and added some logic into the script to count how many times the user chooses no before the script runs automatically anyway. To me, it gives the user a greater sense of control even if only perceived.
#!/bin/sh
fRunUpdates ()
{
## Once the user OKs the updates or they run automatically, reset the timer to 5 echo"5" > /Library/Application Support/JAMF/.SoftwareUpdateTimer.txt
/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType hud -lockhud -heading 'ISD is updating software on your computer' -description 'We are now updating your Mac System software. These updates should not take longer than 30 to 45 minutes depending on how many updates your Mac needs. If you see this screen for more than 45 minutes please call our Service Desk at X4949. Please do not turn off this computer. This message will go away when updates are complete.' -icon /Library/Application Support/JAMF/EndUserSupport/AGRose.icns > /dev/null 2>&1 &
## We'll need the pid of jamfHelper to kill it once the updates are complete
JHPID=`echo"$!"`
/usr/sbin/jamf policy -trigger SoftwareUpdate &
## Get the Process ID of the last command run in the background ($!) and wait for it to complete (wait)
SUPID=`echo"$!"`
wait $SUPID## kill the jamfHelper. If a restart is needed, the user will be prompted. If not the hud will just go away
kill -s KILL $JHPIDexit0
}
######### Set variables for the script ###################### Get the group membership for the client ####################### Get MAC Address using networksetup
MAC=$( networksetup -getmacaddress en0 | awk '{ print $3 }' | sed 's/:/./g' )
## Use the JSS API to get the Mac's group memberships
JSSGroups=$( curl -s -u username:password https://<casper server>:8443/JSSResource/computers/macaddress/$MAC
| xpath //computer/groups_accounts/computer_group_memberships[1]
| sed -e's/<computer_group_memberships>//g;s/</computer_group_memberships>//g;s/<group>//g;s/</group>/
/g' )
## Set up the software update time if it does not exist alreadyif [ ! -e /Library/Application Support/JAMF/.SoftwareUpdateTimer.txt ]; thenecho"5" > /Library/Application Support/JAMF/.SoftwareUpdateTimer.txt
fi## Get the timer value
Timer=`cat /Library/Application Support/JAMF/.SoftwareUpdateTimer.txt`
## Get the currently logged in user, if any. Also check for updates that require a restart and ones that do not.
UpdatesNoRestart=`softwareupdate -l | grep recommended | grep -v restart`
RestartRequired=`softwareupdate -l | grep restart | grep -v '*' | cut -d , -f1`
LoggedInUser=`who | grep console | awk '{print $1}'`
################ End Variable Set ################## Use echo and grep to find known-core (non system) software update groups. If these groups are found, run these installers silently since no restarts are required for these updates. Use an array to see which updates we take account of. The names of the array elements are also trigger names for each update. This way when there's a new software package to keep updated, we add the trigger name into the array, and the update policy to the JSS. Casper does the rest
NonSysCore=( 'SoftwareUplift-FlashPlayer''SoftwareUplift-Flip4Mac''SoftwareUplift-FontNuke''SoftwareUplift-PrintWindow''SoftwareUplift-MicrosoftOffice''SoftwareUplift-MicrosoftOutlook' )
for (( i = 0; i < ${#NonSysCore[@]}; i++ ))
do
CheckUpdate=`echo"$JSSGroups" | grep "${NonSysCore[$i]}"`
if [ "$CheckUpdate" != "" ]; then
jamf policy -trigger "${NonSysCore[$i]}"fidone## If there are no system updates, quitif [ "$UpdatesNoRestart" == ""-a"$RestartRequired" == "" ]; thenecho"No updates at this time"exit0fi## If we get to this point and beyond, there are updates. ## if there is no one logged in, just run the updatesif [ "$LoggedInUser" == "" ]; then
/usr/sbin/jamf policy -trigger SoftwareUpdate
else## someone is logged in. prompt if any updates require a restart ONLY IF the update timer has not reached zeroif [ "$RestartRequired" != "" ]; then## If someone is logged in and they have not canceled 5 times already, prompt them to install updates that require a restart and state how many more times they can press 'cancel' before updates run automatically.if [ $Timer-gt0 ]; then
HELPER=`/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -icon /Library/Application Support/JAMF/EndUserSupport/AGRose.icns -heading "AG ISD Approved Software Updates are Available for Your Mac" -description "These updates will require you to restart your Mac. If you would like to install these now, click 'Install Updates.' If you would not like to install now, click 'Cancel Updates.' You may choose not to install updates $Timer more times before this computer will automatically install them. These updates require a restart of your Mac: $RestartRequired" -button1 "Install Updates" -button2 "Cancel Updates" -cancelButton "2" -defaultButton 2 -timeout 60`
echo"jamf helper result was $HELPER";
## If they click Install Updates then run the updatesif [ "$HELPER" == "0" ]; then
fRunUpdates
else## If no, then reduce the timer by 1. The script will run again the next day let CurrTimer=$Timer-1echo"user chose No"echo"$CurrTimer" > /Library/Application Support/JAMF/.SoftwareUpdateTimer.txt
exit1fielse## If Timer is already 0, run the updates automatically, the user has been warned!
fRunUpdates
fififi## Install updates that do not require a restartif [ "$UpdatesNoRestart" != "" ]; then
/usr/sbin/jamf policy -trigger SoftwareUpdate
fi
Hey John, I went a few steps further and added some logic into the script to count how many times the user chooses no before the script runs automatically anyway. To me, it gives the user a greater sense of control even if only perceived.
#!/bin/sh
fRunUpdates ()
{
## Once the user OKs the updates or they run automatically, reset the timer to 5 echo"5" > /Library/Application Support/JAMF/.SoftwareUpdateTimer.txt
/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType hud -lockhud -heading 'ISD is updating software on your computer' -description 'We are now updating your Mac System software. These updates should not take longer than 30 to 45 minutes depending on how many updates your Mac needs. If you see this screen for more than 45 minutes please call our Service Desk at X4949. Please do not turn off this computer. This message will go away when updates are complete.' -icon /Library/Application Support/JAMF/EndUserSupport/AGRose.icns > /dev/null 2>&1 &
## We'll need the pid of jamfHelper to kill it once the updates are complete
JHPID=`echo"$!"`
/usr/sbin/jamf policy -trigger SoftwareUpdate &
## Get the Process ID of the last command run in the background ($!) and wait for it to complete (wait)
SUPID=`echo"$!"`
wait $SUPID## kill the jamfHelper. If a restart is needed, the user will be prompted. If not the hud will just go away
kill -s KILL $JHPIDexit0
}
######### Set variables for the script ###################### Get the group membership for the client ####################### Get MAC Address using networksetup
MAC=$( networksetup -getmacaddress en0 | awk '{ print $3 }' | sed 's/:/./g' )
## Use the JSS API to get the Mac's group memberships
JSSGroups=$( curl -s -u username:password https://<casper server>:8443/JSSResource/computers/macaddress/$MAC
| xpath //computer/groups_accounts/computer_group_memberships[1]
| sed -e's/<computer_group_memberships>//g;s/</computer_group_memberships>//g;s/<group>//g;s/</group>/
/g' )
## Set up the software update time if it does not exist alreadyif [ ! -e /Library/Application Support/JAMF/.SoftwareUpdateTimer.txt ]; thenecho"5" > /Library/Application Support/JAMF/.SoftwareUpdateTimer.txt
fi## Get the timer value
Timer=`cat /Library/Application Support/JAMF/.SoftwareUpdateTimer.txt`
## Get the currently logged in user, if any. Also check for updates that require a restart and ones that do not.
UpdatesNoRestart=`softwareupdate -l | grep recommended | grep -v restart`
RestartRequired=`softwareupdate -l | grep restart | grep -v '*' | cut -d , -f1`
LoggedInUser=`who | grep console | awk '{print $1}'`
################ End Variable Set ################## Use echo and grep to find known-core (non system) software update groups. If these groups are found, run these installers silently since no restarts are required for these updates. Use an array to see which updates we take account of. The names of the array elements are also trigger names for each update. This way when there's a new software package to keep updated, we add the trigger name into the array, and the update policy to the JSS. Casper does the rest
NonSysCore=( 'SoftwareUplift-FlashPlayer''SoftwareUplift-Flip4Mac''SoftwareUplift-FontNuke''SoftwareUplift-PrintWindow''SoftwareUplift-MicrosoftOffice''SoftwareUplift-MicrosoftOutlook' )
for (( i = 0; i < ${#NonSysCore[@]}; i++ ))
do
CheckUpdate=`echo"$JSSGroups" | grep "${NonSysCore[$i]}"`
if [ "$CheckUpdate" != "" ]; then
jamf policy -trigger "${NonSysCore[$i]}"fidone## If there are no system updates, quitif [ "$UpdatesNoRestart" == ""-a"$RestartRequired" == "" ]; thenecho"No updates at this time"exit0fi## If we get to this point and beyond, there are updates. ## if there is no one logged in, just run the updatesif [ "$LoggedInUser" == "" ]; then
/usr/sbin/jamf policy -trigger SoftwareUpdate
else## someone is logged in. prompt if any updates require a restart ONLY IF the update timer has not reached zeroif [ "$RestartRequired" != "" ]; then## If someone is logged in and they have not canceled 5 times already, prompt them to install updates that require a restart and state how many more times they can press 'cancel' before updates run automatically.if [ $Timer-gt0 ]; then
HELPER=`/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -icon /Library/Application Support/JAMF/EndUserSupport/AGRose.icns -heading "AG ISD Approved Software Updates are Available for Your Mac" -description "These updates will require you to restart your Mac. If you would like to install these now, click 'Install Updates.' If you would not like to install now, click 'Cancel Updates.' You may choose not to install updates $Timer more times before this computer will automatically install them. These updates require a restart of your Mac: $RestartRequired" -button1 "Install Updates" -button2 "Cancel Updates" -cancelButton "2" -defaultButton 2 -timeout 60`
echo"jamf helper result was $HELPER";
## If they click Install Updates then run the updatesif [ "$HELPER" == "0" ]; then
fRunUpdates
else## If no, then reduce the timer by 1. The script will run again the next day let CurrTimer=$Timer-1echo"user chose No"echo"$CurrTimer" > /Library/Application Support/JAMF/.SoftwareUpdateTimer.txt
exit1fielse## If Timer is already 0, run the updates automatically, the user has been warned!
fRunUpdates
fififi## Install updates that do not require a restartif [ "$UpdatesNoRestart" != "" ]; then
/usr/sbin/jamf policy -trigger SoftwareUpdate
fi
Because it might help people.. I originally posted an extract of the script.. this is the whole original script with extra logic to prevent the disappearing jamf helper. I like the extra modifications you have done and may add to mine.
#!/bin/sh
######### This script checks to see if there is a logged in user, if no user is logged in software update will run and install all udpates.# If a user is logged in the script checks if the updates need a restart - if so the user is prompted whether this is ok before proceeding.# Where no restart is required software update will run without interrupting the user.#see if user logged in
USER=`/usr/bin/who | /usr/bin/grep console | /usr/bin/cut -d" "-f1`;
echo"logged in user is $USER...";
#check if user logged inif [ -n "$USER" ]; then#Check if restarts required
AVAILABLEUPDATES=`/usr/sbin/softwareupdate --list`;
NOUPDATES=`echo$AVAILABLEUPDATES | wc -l | cut -d" "-f8`;
RESTARTREQUIRED=`echo$AVAILABLEUPDATES | /usr/bin/grep restart | /usr/bin/cut -d","-f1`;
if [ -n "$RESTARTREQUIRED" ]; thenecho"$RESTARTREQUIRED needs a restart";
#ask user whether ok to restart
OKTORESTART=`/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -icon /Library/Application Support/JAMF/bin/jamfHelper.app/Contents/Resources/Message.png -heading "Software Updates are Available" -description "Your computer will need to restart, would you like to install the udpates now?" -button1 "Yes" -button2 "Cancel" -cancelButton "2"`
echo"ok to restart was $OKTORESTART";
if [ "$OKTORESTART" == "0" ]; then
/usr/sbin/jamf policy -trigger runsoftwareupdate
exit0elseecho"User said NO to updates";
exit1fielseecho"No restart is needed";
if [ "$NOUPDATES" != "1" ]; thenecho"So running Software Update";
/usr/sbin/jamf policy -trigger runsoftwareupdate
exit0elseecho"because there were no updates";
exit0fifielse#No logged in user
/usr/sbin/jamf policy -trigger runsoftwareupdate
fiexit0
For some reason when I throw it on a test box, the script ends before JAMFHelper even appears, so when I click on Yes to install they don't do anything. I have the script set to run "before"
Running script softwareupdate_jamf_helper.sh...
Script exit code: 1
Script result: logged in user is jwojda...
Software Update Tool Copyright 2002-2010 Apple Software Updatefound the following new or updated software: Desktop Documents Library Movies Music Pictures Public OSXUpd10.8.2-10.8.2 OS X Update (10.8.2) needs a restart
ok to restart was
User said NOto updates
Unmounting file server...
Lisa/ACDesign,
Is it possible to incorporate the countdown timer from the other script into this?
Hey John, I was getting the same output when capturing softwareupdate -l into a variable. For some reason it wants to list the contents of your home folder. Weird, but I also noticed that all updates are [recommended]. If i do a softwareupdate -l | grep recommended and stuff that into a variable, it gives me the right output:
updates=`softwareupdate -l | grep recommended`
ag2025:~ acaldwell$ echo $updates
Remote Desktop Admin Update (3.5.3), 25748K [recommended] Digital Camera Raw Compatibility Update (3.14), 8012K [recommended] Digital Camera Raw Compatibility Update (3.12), 7740K [recommended] Security Update2012-004 (1.0), 263587K [recommended] [restart] Digital Camera Raw Compatibility Update (3.13), 7979K [recommended] Remote Desktop Admin Update (3.5.2), 25738K [recommended] HP Printer Software Update (2.9), 8740K [recommended]
Unfortunately, you won't be able to grep out the [restart] without running softwareupdate -l again since this method throws it all into a single line.
That awkward moment when you look back at a script you wrote some time ago, and decide you don't like the logic/style that you thought was a great idea at the time.. A revised version which I'm testing.. removes some duplicate checks, and less noise.
#!/usr/bin/perl -wuse strict;
my$AVAILABLEUPDATES="";
$AVAILABLEUPDATES=`/usr/sbin/softwareupdate --list`;
chomp$AVAILABLEUPDATES;
printf"available updates is %s
", "$AVAILABLEUPDATES";
# If available updates contains * there are updates availableif ($AVAILABLEUPDATES=~/*/){
printf"there are updates available
";
if ($AVAILABLEUPDATES=~/restart/){
printf"updates need a restart
";
my$LOGGEDINUSER='';
$LOGGEDINUSER=`/usr/bin/who | /usr/bin/grep console | /usr/bin/cut -d " " -f 1`;
chomp$LOGGEDINUSER;
printf"value of logged in user is $LOGGEDINUSER..
";
if ($LOGGEDINUSER=~/[a-zA-Z]/) {
printf"as there is a logged in user checking whether ok to restart
";
my$RESPONSE = "";
$RESPONSE=`'/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper' -windowType utility -icon '/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/Resources/Message.png' -heading "Software Updates are available" -description "Your computer will need to restart, would you like to install the updates now?" -button1 "Yes" -button2 "Cancel" -cancelButton "2"`;
printf"response was $RESPONSE
";
if ($RESPONSE == "0") {
printf"User said YES to Updates
";
system"/usr/sbin/jamf policy -trigger runsoftwareupdate";
exit0;
} else {
printf"User said NO to Updates
";
exit0;
}
}
else {
printf"no logged in user so ok to run updates
";
system"/usr/sbin/jamf policy -trigger runsoftwareupdate";
exit0;
}
}
else {
printf"no restart required
";
system"/usr/sbin/jamf policy -trigger runsoftwareupdate";
exit0;
}
}
else {
printf"there are no updates available
";
exit0;
}
exit0;
The forcing updates is because the users had X amount of days to install them. I understand that sometimes people are busy and can't do them immediately, but I still have to adhere to our corporate patching standards, and I actually like to be ahead of the curve for anything I can be. The mac's are the black sheep of the company, yet all the executives have/want them, so they also have a spotlight on it if something doesn't go as smooth.
I've got the 10.8.x systems running through the MAS currently, and I submitted a request via our Apple Service Agreement to add the countdown timer to force install as well.
Thank you for your continued tweaks and support of the script! I will try it out when i'm back in the office tomorrow.
Thanks a bunch for making this script! I've been looking all over the place for a solution like this.
It works flawlessly for most users. However, I am encountering instances where I am seeing this in the log:
there are updates available updates need a restart value of logged in user is HDConsole.. as there is a logged in user checking whether ok to restart Argument "" isn't numeric in numeric eq (==) at /private/tmp/softwareupdate_jamf_helper_2.sh line 39. response was
User said YES to Updates Checking for policies triggered by "runsoftwareupdate"...
The user does not end up seeing a message asking if they want to install, it assumes a Yes response was given.
I'm not an expert in scripting yet, but can the script be changed so that if a user presses "Yes" then a numeric is produced as the trigger to run "jamf policy -trigger runsoftwareupdate" instead of using "Cancel"?
I've literally just got back to work after the conference.
In the post above there is an extra argument that can be added, which I think will sort that out. I need to add in and test.. I will update this discussion probably early next week, once I've done some testing, and will fix the issues with the script then. (Posting an updated version).
Made the quick changes to the comparison check, and added the startlaunchd.. seems to be running well. Still doing some testing.. But here it is:
#!/usr/bin/perl -wuse strict;
my$AVAILABLEUPDATES="";
$AVAILABLEUPDATES=`/usr/sbin/softwareupdate --list`;
chomp$AVAILABLEUPDATES;
printf"available updates is %s
", "$AVAILABLEUPDATES";
# If available updates contains * there are updates availableif ($AVAILABLEUPDATES=~/*/){
printf"there are updates available
";
if ($AVAILABLEUPDATES=~/restart/){
printf"updates need a restart
";
my$LOGGEDINUSER='';
$LOGGEDINUSER=`/usr/bin/who | /usr/bin/grep console | /usr/bin/cut -d " " -f 1`;
chomp$LOGGEDINUSER;
printf"value of logged in user is $LOGGEDINUSER..
";
if ($LOGGEDINUSER=~/[a-zA-Z]/) {
printf"as there is a logged in user checking whether ok to restart
";
my$RESPONSE = "";
$RESPONSE=system''/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper' -startlaunchd -windowType utility -icon '/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/Resources/Message.png' -heading "Software Updates are available" -description "Your computer will need to restart, would you like to install the updates now?" -button1 "Yes" -button2 "Cancel" -cancelButton "2"';
if ($RESPONSE eq "0") {
printf"
User said YES to Updates
";
system"/usr/sbin/jamf policy -trigger runsoftwareupdate";
exit0;
} else {
printf"
User said NO to Updates
";
exit0;
}
}
else {
printf"no logged in user so ok to run updates
";
system"/usr/sbin/jamf policy -trigger runsoftwareupdate";
exit0;
}
}
else {
printf"no restart required
";
system"/usr/sbin/jamf policy -trigger runsoftwareupdate";
exit0;
}
}
else {
printf"there are no updates available
";
exit0;
}
exit0;
The last version I pasted seems to be going well so far in my testing. Just some clients dropping off before finishing the download for the larger updates. Happy for feedback if you see any problems. Thank you.
I've made a few tweaks because I couldn't get the jamf trigger softwareupdates to work reliably, I could get the script to run when I did a manual jamf policy -id on it, but not when I ran it on the every 15 trigger.
So I submitted a ticket to Jamf and this is what they came back with.
I did some testing on this and found the following.
If I run this script by any of the following it will work:
- Self Service - Manually call the script - Manually call the policy via terminal
What will not work
- Running script on the every15 trigger - In terminal logging in as the root user and then running the script
I talked with a co-worker about this we think that this has to do with the root user running this script that is trying to open the MAS from another user.
So the root user can not open the MAS for say the user admin.
I am in no way familiar with Pearl here so what I might suggest is that we find a way to run the command that opens the MAS as the currently logged in user and that might fix our issue here.
So far in testing I have not seen the issues you have described. I made a second policy with a custom trigger of runsoftwareupdate, with payload to install all available software updates. this policy is set to ongoing to allow repeated calls.
The first policy which displays the popup is triggered on everyHour, with a frequency of once a day. Most days exiting silently as there are no new updates enabled on SUS.
I will try to reproduce what you have described later in the week. With the previous version I was seeing the popup ignore user input and always taking the cancel option regardless of what was selected. Adding the "-startlaunchd" sorted that out - doublecheck you have that argument in the line which invokes the jamf helper popup.
I think the jamf trigger command was not working for the same reason, i thought maybe because it was trying to call a 2nd policy, so thats why I changed to just launch the mac app store directly.
#!/usr/bin/perl -wuse strict;
my$AVAILABLEUPDATES="";
$AVAILABLEUPDATES=`/usr/sbin/softwareupdate --list`;
chomp$AVAILABLEUPDATES;
printf"available updates is %s
", "$AVAILABLEUPDATES";
# If available updates contains * there are updates availableif ($AVAILABLEUPDATES=~/*/){
printf"there are updates available
";
if ($AVAILABLEUPDATES=~/restart/){
printf"updates need a restart
";
my$LOGGEDINUSER='';
$LOGGEDINUSER=`/usr/bin/who | /usr/bin/grep console | /usr/bin/cut -d " " -f 1`;
chomp$LOGGEDINUSER;
printf"value of logged in user is $LOGGEDINUSER..
";
if ($LOGGEDINUSER=~/[a-zA-Z]/) {
printf"as there is a logged in user checking whether ok to restart
";
my$RESPONSE = "";
$RESPONSE=system''/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper' -startlaunchd -windowType utility -icon '/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/Resources/Message.png' -heading "Software Updates are available" -description "Your computer will need to restart, would you like to install the updates now?" -button1 "Yes" -button2 "Cancel" -cancelButton "2"';
if ($RESPONSE eq "0") {
printf"
User said YES to Updates
";
system'/System/Library/CoreServices/Software Update.app/Contents/MacOS/Software Update';
exit0;
} else {
printf"
User said NO to Updates
";
exit0;
}
}
else {
printf"no logged in user so ok to run updates
";
system'/System/Library/CoreServices/Software Update.app/Contents/MacOS/Software Update';
exit0;
}
}
else {
printf"no restart required
";
system'/System/Library/CoreServices/Software Update.app/Contents/MacOS/Software Update';
exit0;
}
}
else {
printf"there are no updates available
";
exit0;
}
exit0;
Lisa - I just discovered that when the restart required check looks at the Mac Pro EFI Update 1.5 item it returns the response "shut down" instead of "restart"... Hence my user was prompted to restart his Mac in 5 minutes while he's in the middle of editing in FCP. :(
Is it possible to add "shut down" as a response that will trigger the pop-up box?
available updates is Software Update Tool Copyright 2002-2009 Apple
Software Update found the following new or updated software: * MacProEFIUpdate1.5-1.5 Mac Pro EFI Firmware Update (1.5), 2059K [recommended] [shut down]
there are updates available no restart required Checking for policies triggered by "runsoftwareupdate"...
...
Writing files… Optimizing system for installed software… Writing package receipts… Installed Mac Pro EFI Firmware Update Done.
You have installed one or more updates that requires that you restart your computer. Please restart immediately.
A reboot was required with one or more of the installed updates. Blessing i386 OS X System on /... Creating Reboot Script...
I'll give that a try. Sadly I already reached out to all my MPs that needed that update and pushed it through manually so they're not interrupted. But it's good to know that the line is there in case Apple wants to do that again.
ok, not a perl guy by a long shot. How would I get the PID of the last executed command in a perl script, and then force the script to continue while that one command ran?
ex: ``` /Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType fs -heading 'American Greetings ISD is updating software on your computer' -description 'We are now updating your Mac System software. This update should not take longer than 30 to 45 minutes, depending on how many updates your Mac needs. If you see this screen for more than 45 minutes, please call our helpdesk at X4949. Please do not turn off this computer. This message will go away when updates are complete.' -icon /Library/Application Support/JAMF/EndUserSupport/AGRose.icns > /dev/null 2>&1 &
## In case we need the process ID for the jamfHelper
JHPID=echo "$!" ```
Thanks everyone for these. Since I do most of my scripting in Python, I thought I'd take a stab at rewriting it. Hopefully someone will find it useful. Let me know if you have any questions about what it's doing. I've tested it on several systems and haven't run across any showstoppers, but if you find something, please pass it on.
#!/usr/bin/python# import required modules
import os
import re
import shutil
from datetime import datetime
from sys import exit# set log filename/location
curDate = datetime.now().date()
logFile = 'swupd-%s-%s.log' % (curDate.year,curDate.month)
logLocation = '/your/preferred/log/directory'
curLog = '%s/%s' % (logLocation,logFile)
# create functions for installing updates, logging postponements, and exiting
def installUpdates():
os.popen('/usr/sbin/jamf policy -trigger runswupd')
attempts = 6
logData(attempts)
exit(0)
def postponeUpdates(attempts):
print"User chose to postpone the updates."
attempts = attempts + 1
logData(attempts)
exit(0)
def forceUpdates():
response = os.popen('"{filename}" -startlaunchd -windowType utility -icon "{icon}" -title "{title}" -heading "{heading}" -description "{description}" -button1 "Ok"'.format(
description='Your computer has updates availble that may require a reboot. You've postponed the updates 5 times. As such, the installation is being forced now. Please save your work immediately.',
filename='/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper',
heading='Software Updates are installing!',
icon='/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/Resources/Message.png',
title='Company Software Updates'
)).read()
if response == 0:
installUpdates()
else:
print "Something went wrong with the jamfHelper. Fix it."
attempts = 7
logData(attempts)
exit(1)
def logData(content): # writes 'content' to the log, overwriting any previous contents. There should never be anything other than a single number in there anyway. 1 - 5 indicates the number of times it has been postponed. 6 indicates complete for the month. 7 indicates the forced attempt at updates failed.
logContent = open(curLog, 'w')
logContent.write(str(content))
logContent.close()
# create log path if it doesn't exist
if not os.path.isdir(logLocation):
os.makedirs(logLocation)
# create monthly log file if it doesn't exist and read file contents if it doesif not os.path.isdir(curLog) and not os.path.exists(curLog):
logNew = open(curLog, 'w')
attempts = 0
logNew.write(str(attempts))
logNew.close()
elif os.path.isdir(curLog):
print"The path for the current log file was a directory. How this happened, the world may never know. The path %s, and everything under it is now toast, and will be recreated as a file." % curLog
shutil.rmtree(curLog)
logNew = open(curLog, 'w')
attempts = 0
logNew.write(str(attempts))
logNew.close()
elif os.path.isfile(curLog): # read the number of attempts that have been postponed
logIn = open(curLog, 'r+')
try:
attempts = int(logIn.read())
except ValueError:
attempts = 0
logIn.write(str(attempts))
logIn.close()
# check for updates
updatesAvail = os.popen('/usr/sbin/softwareupdate --list').read().rstrip()
print"Available updates: %s" % updatesAvail
if"*" in updatesAvail:
print"There are updates available"
os.popen('/usr/sbin/jamf recon') # running recon to make sure the JSS knows the system has updates available. In theory, it should always know.
avail = 1else:
avail = 0if avail == 0:
print"No updates were available"
os.popen('/usr/sbin/jamf recon') # running recon to make sure the JSS knows that there really aren't updates available.
logData('complete')
exit(0)
# check if available updates require a restart if'restart' in updatesAvail or'shut down' in updatesAvail:
print"These updates require a restart"
restart = 1else:
restart = 0# find currently logged in console user
curUser = os.popen('/usr/bin/who | grep console | cut -d " " -f 1').read().rstrip()
print"Current user is: %s" % curUser
# if there is a logged in user, we must ask for permission to restart, otherwise we go forward!if avail == 1:
if attempts < 5:
if restart == 1:
if re.match(r'[a-zA-Z]', curUser):
response = int(os.popen('"{filename}" -startlaunchd -windowType utility -icon "{icon}" -title "{title}" -heading "{heading}" -description "{description}" -button1 "Yes" -button2 "No" -cancelButton "2"'.format(
description='Your computer has updates availble that will require a reboot. Would you like to install these updates now? After clicking yes, please wait until you receive an indication that the computer is ready to reboot.',
filename='/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper',
heading='Software Updates are available!',
icon='/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/Resources/Message.png',
title='Company Software Updates'
)).read())
else:
installUpdates()
if response == 0:
installUpdates()
elif response == 2:
postponeUpdates(attempts)
elif response == 1:
print"There was a problem spawning the dialog box. You need to make sure the system is properly enrolled in Casper."exit(1)
else:
print"Something that should be impossible happened. Your return code was %s. Please check the code against the jamfHelper return values by running jamfHelper with the -help flag." % response
exit(1)
else:
installUpdates()
elif attempts == 5:
forceUpdates()
else:
print"Something unknown is wrong with this machine. Exiting with an error status code."exit(1)
We use 3 different kinds of cookies. You can choose which cookies you want to accept. We need basic cookies to make this site work, therefore these are the minimum you can select. Learn more about our cookies.