Posted on 07-22-2013 01:48 PM
I've been playing with some more robust ways to run softwareupdate than the built in implementation in Casper and came up with this. Modify as you like to make it work for your environment, it currently only works with 10.8 because 10.7 uses a slightly different structure for index.plist (and I just didn't have time to modify for it). Basically it checks if you are on 10.8, then if you have any updates, and if you do and they requires a restart, download them all and modify the proper files so that when someone does go to Apple - Restart, it'll bring up the built in Apple environment to show them a pretty progress bar on how their updates are going, and if there are updates but none of them require a restart, install them silently. This can be used in conjunction with a Policy so that you can warn users that it's running, that if it finds updates that require restart that it'll install those updates when they restart the computer, etc. etc. etc.
Enjoy!
#!/bin/bash SWUL=/usr/sbin/softwareupdate -l | /usr/bin/awk '{printf "%s", $0}'
SWULER=/usr/sbin/softwareupdate -l 2>&1 | /usr/bin/head -1
NoRestartUpdates=/usr/sbin/softwareupdate -l | /usr/bin/grep -v restart | /usr/bin/grep -B1 recommended | /usr/bin/grep -v recommended | /usr/bin/awk '{print $2}' | /usr/bin/awk '{printf "%s ", $0}'
osvers=sw_vers -productVersion | awk -F. '{print $2}'
if [[ $osvers -eq 7 ]]; then /bin/echo "Script only for 10.8 ONLY" exit 1 elif [ "$SWULER" == "No new software available." ]; then /bin/echo "$SWULER" exit 1 elif [[ "$SWUL" == *"[restart]"* ]]; then echo "Installing Updates that require Restart" /usr/bin/sudo /usr/sbin/softwareupdate -d -a /usr/libexec/PListBuddy -c "Copy CompletedProducts InstallAtLogout" /Library/Updates/index.plist /usr/bin/touch /var/db/.SoftwareUpdateAtLogout /bin/chmod og-r /var/db/.SoftwareUpdateAtLogout /usr/libexec/PListBuddy -c "Add -RootInstallMode STRING YES" /var/db/.SoftwareUpdateOptions /usr/libexec/PListBuddy -c "Add -SkipConfirm STRING YES" /var/db/.SoftwareUpdateOptions /bin/chmod og-r /var/db/.SoftwareUpdateOptions elif [[ "$SWUL" == *"[recommended]"* ]]; then /bin/echo "Installing Updates that does not require Restart" /usr/bin/sudo /usr/sbin/softwareupdate -i $NoRestartUpdates fi exit 0
Posted on 07-22-2013 07:16 PM
Awesome work! We have not been 100% satisfied with our update policies, and had some issues recently. I will give this a shot in our environment. Thanks for sharing.
Posted on 07-23-2013 05:11 AM
This looks great! I'll be checking it out this morning. Very well thought out!
Posted on 07-23-2013 01:41 PM
Beautiful script! Thanks
Posted on 07-23-2013 09:23 PM
Thanks.
I had this URL not found issue reported but installed updates as you described. Excellent script.
softwareupdate[1889]: No alternate URLs found for packageId amds
App Store[688]: No alternate URLs found for packageId amds
Have you seen this before?
Posted on 07-24-2013 06:38 AM
I need to give credit where credit is due. After reading http://managingosx.wordpress.com/2009/10/12/apple-software-update-options/ and talking with Greg briefly, and given my really limited (i.e. none) ability in Python but trying to read Munki code (which is very readable without Python knowledge by the way) gave me the inspiration of what you see above. The article above does give a way to do it in 10.6 (and maybe in 10.7) but I wanted to use PlistBuddy (which I realize I did misspell in the script, gotta love HFS+ for ignoring case in this case I guess) instead of defaults because technically it's not a Apple preferences I was modifying (trying to be a good doobie about "proper" procedures when it comes to Plist editing)
installarray=defaults read /Library/Updates/index ProductPaths | grep -v "[{}]" | awk -F "=" '{print $1}' | grep -o "[^" ]+"
defaults write /Library/Updates/index InstallAtLogout -array "$installarray"
As this evolves, I'll think about putting something together in GitHub. I just hope this helps others who want to keep machines up to date silently, but aren't happy with the built in Apple softwareupdate command on it's own.
I also want to stress that this script should probably be used in environments where you can control what updates get installed since it's going to install all of them from whatever URL is set on that computer to look for updates. Last thing you'd want is Apple pushing an update, you pushing it out to your users, and then having that update be faulty, history tells us this happens more often than it should.
Posted on 07-24-2013 06:40 AM
@Kumarasinghe yes I have seen that in my environment, but since I'm using this as a silent updater for my users, and the end results does the job intended, I didn't really look into why that's happening, nor at this time do I care.
Posted on 07-24-2013 01:36 PM
this was the result when I ran the script on a test box...
Script result: Installing Updates that require Restart
Software Update Tool
Copyright 2002-2010 Apple
Done.
Packages have been saved to /Library/Updates
Copy: Entry, "CompletedProducts", Does Not Exist
File Doesn't Exist, Will Create: /var/db/.SoftwareUpdateOptions
Unmounting file server...
Running Recon...
Locating mobile device records...
Posted on 07-24-2013 06:00 PM
softwareupdate[1889]: No alternate URLs found for packageId amds App Store[688]: No alternate URLs found for packageId amds Have you seen this before?
Yes. It has nothing to do with the script; you'd see it if you ran /usr/sbin/softwareupdate manually as well.
Posted on 07-25-2013 06:12 AM
I ran it on a box last night... when I asked the user if anything unexpected happened when they powered off for the night, they said their system went to a grey screen and sat there. He let it set for about 5minutes and finally powered it off.
Posted on 07-25-2013 06:29 AM
@jwojda - check the files that are being modified by the script, check on the box what softwareupdate -l returns, check if index.plist is being changed properly to reflect what was downloaded versus what was listed as available updates. It looks like initially it found updates that require restart under softwareupdate -l, but when you ran softwareupdate -d -a it didn't find anything to install.
Again, modify it to suit your needs, if you don't want to auto install updates that require restarts, you could comment out those lines.
Posted on 07-25-2013 07:39 AM
I'm okay with auto-installing updates that require restarts...
Maybe it is working as expected...this is the results of things you said to check. I guess that I was expecting the progress bar to show and that's what never did... I will do s'more testing.
sudo softwareupdate -l
Password:
Software Update Tool
Copyright 2002-2010 Apple
Software Update found the following new or updated software:
* MacBookProRetinaSMCUpdate1.1-1.1
MacBook Pro Retina SMC Update (1.1), 165K [recommended] [restart]
* AirPortUtility-6.3.1
AirPort Utility (6.3.1), 21104K [recommended]
ls
041-9657 ProductMetadata.plist
091-7170 index.plist
nano index.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs$
<plist version="1.0">
<dict>
<key>CompleteProducts</key>
<array>
<string>041-9657</string>
<string>091-7170</string>
</array>
<key>InstallAtLogout</key>
<array>
<string>041-9657</string>
<string>091-7170</string>
</array>
<key>ProductPaths</key>
<dict>
<key>041-9657</key>
<string>041-9657</string>
<key>091-7170</key>
Posted on 07-25-2013 07:39 AM
I'm okay with auto-installing updates that require restarts...
Maybe it is working as expected...this is the results of things you said to check. I guess that I was expecting the progress bar to show and that's what never did... I will do s'more testing.
sudo softwareupdate -l
Password:
Software Update Tool
Copyright 2002-2010 Apple
Software Update found the following new or updated software:
* MacBookProRetinaSMCUpdate1.1-1.1
MacBook Pro Retina SMC Update (1.1), 165K [recommended] [restart]
* AirPortUtility-6.3.1
AirPort Utility (6.3.1), 21104K [recommended]
ls
041-9657 ProductMetadata.plist
091-7170 index.plist
nano index.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs$
<plist version="1.0">
<dict>
<key>CompleteProducts</key>
<array>
<string>041-9657</string>
<string>091-7170</string>
</array>
<key>InstallAtLogout</key>
<array>
<string>041-9657</string>
<string>091-7170</string>
</array>
<key>ProductPaths</key>
<dict>
<key>041-9657</key>
<string>041-9657</string>
<key>091-7170</key>
Posted on 07-25-2013 08:48 AM
I wonder if the SMC firmware updates install differently than other updates, and if the script just doesn't work with those. Haven't run across a computer needing firmware updates but thanks for the feedback, I appreciate it.
Posted on 07-25-2013 01:36 PM
I have noticed that many firmware updates will not install unless a laptop is using the power adaptor, versus running on the battery. If you attempt to install the updates via the command line, it will reboot but will not actually install the update. I haven't seen any just hang indefinitely at a grey screen though.
Posted on 07-26-2013 07:50 AM
It may have been the firmware updates. I just built a machine using an 10.8.3 image, but the machine already had all the firmware updates. it downloaded everything, installed the non-restart updates, and when I shut down it went to a grey screen for about 1-2 seconds then switched to teh apple progress bar..
Posted on 07-26-2013 07:59 AM
Firmware updates might be handled differently that other requires restart updates, since I'm manually triggering the Software Update loginwindow using the SoftwareUpdateAtLogout and SoftwareUpdateOptions, there might be either different options, or different mechanisms that need to be called for that to work properly.
Again thanks for the feedback, it's good food for thought for me to investigate later if I can get my hands on a machine that needs said update (kinda hard to test something that only happens once after all)
Posted on 07-26-2013 08:33 AM
Personally I don't know that I'd want to install any Firmware updates on our Macs in an automated way anyhow. We keep those blocked on our SUS for clients for the most part and feed those out in a manual way once they've been through enough testing. So it may be good that it doesn't really handle those type of updates.
Posted on 09-24-2013 04:29 AM
@hkim
Thanks Han. Please post here if you have made any improvements/logic to the original script.
Posted on 10-24-2013 07:45 PM
@hkim
Have you tested the script for OS X 10.9?
It doesn't seem to work with OS X 10.9.
Thanks
Posted on 05-13-2014 11:09 AM
@hkim I really like your approach to software updates. I decided to try your script on 10.9.2 and have found that it does succeed in caching the packages and install them at logout. However, it is producing this error:
May 13 10:43:00 computer_name softwareupdate CLI[1220] : /usr/sbin/softwareupdate: XPC error in __60-[SUCommandLineTool _runSessionWithUpdates:skippingInstall:]_block_invoke (Error Domain=NSCocoaErrorDomain Code=4099 "Couldn’t communicate with a helper application." (The connection was invalidated from this process.) UserInfo=0x7ff5a1c12f90 {NSDebugDescription=The connection was invalidated from this process.})
Any thoughts on this?
Posted on 06-24-2014 10:46 PM
Just to chime in and say @UESCDurandal that I too have this error pretty much word for word.
I wonder if the action is trying to spawn the GUI dialog to prompt for a restart, but is being interrupted through the use of the script or JAMF policy...
I am using 10.9.3 with V.8.73 of the JSS.
Posted on 06-24-2014 11:14 PM
I'd have a look at loceee's patchoo scripts, they handle apple softwareupdates very nicely including different catalogs for different OS versions
Posted on 06-25-2014 09:20 AM
We have our own custom patching script (reads in a list of updates we've "blessed" and downloads/installs only those with some CocoaDialog UI elements for user interaction/deferral and a restart timer), but I am definitely going to steal some bits of your script. I like the "install on logout" bit mainly, I would much rather use the native Software Update interface.
Posted on 07-10-2014 01:07 AM
Is anyone using this method with Mavericks?
For me, it seems to work only on every 2nd boot, it's like:
- Run script, everything looks fine, reboot -> nothing happens. Install.log says
Software Update.app (0)[1595]: Software Update.app: None of the keys registered for post-logout install () are available
- Run script again, everything looks like the first time, reboot -> Updates are being installed. Install.log:
Software Update.app (0)[989]: Software Update.app: Starting post-logout install of 031-04361 ... ...
Just wondering which "keys" it refers to in the error message...
Posted on 08-26-2014 10:53 PM
This script works very well. Nice transparent install in the background, or on restart with standard Apple GUI.
Appears to work on 10.8, 10.9 and also tested on a single 10.10 machine.
Posted on 09-09-2014 03:25 AM
@UESCDurandal @chop I am too getting the same error you were getting when installing updates. Did you manage to find a fix for this?
Posted on 10-17-2014 12:42 AM
I've revisited this regarding the
Software Update.app (0)[1595]: Software Update.app: None of the keys registered for post-logout install () are available
error i mentioned above.
Turns out that kickstarting softwareupdated makes it work for me on Mavericks and Yosemite.
I've added
launchctl unload /System/Library/LaunchDaemons/com.apple.softwareupdated.plist
launchctl load /System/Library/LaunchDaemons/com.apple.softwareupdated.plist
to the end of the script.
Posted on 03-02-2015 12:13 PM
msimpson - did you implement this script without making any changes to it when testing on 10.8, 10.9 and 10.10 ?
Posted on 05-25-2015 12:51 AM
msimpson's script was implemented as a run-on-demand from Self Service. Limitations placed on the script to only allow running 10.8.x, 10.9.x, 10.10.x
A slight modification was made to the script at the beginning for removal of our internal update server plist we added to earlier mac builds.
Another difference is slight formatting and use of "`" - probably because the original script was posted as a quote and not script, perhaps breaking the script? HTML does funny things to scripts if not properly attached to a forum post. It breaks.
Below is verbatim what we use.
#!/bin/bash
## Remove swupdate preferences to use default server
jamf removeSWUSettings
rm /Library/Preferences/com.apple.SoftwareUpdate.plist
rm /Library/Managed Preferences/com.apple.SoftwareUpdate.plist
##
SWUL=`/usr/sbin/softwareupdate -l | /usr/bin/awk '{printf "%s", $0}'`
SWULER=`/usr/sbin/softwareupdate -l 2>&1 | /usr/bin/head -1`
NoRestartUpdates=`/usr/sbin/softwareupdate -l | /usr/bin/grep -v restart | /usr/bin/grep -B1 recommended | /usr/bin/grep -v recommended | /usr/bin/awk '{print $2}' | /usr/bin/awk '{printf "%s ", $0}'`
osvers=`sw_vers -productVersion | awk -F. '{print $2}'`
if [[ $osvers -eq 7 ]]; then
/bin/echo "Script only for 10.8 ONLY"
exit 1
elif [ "$SWULER" == "No new software available." ]; then
/bin/echo "$SWULER"
exit 1
elif [[ "$SWUL" == *"[restart]"* ]]; then
echo "Installing Updates that require Restart"
/usr/bin/sudo /usr/sbin/softwareupdate -d -a
/usr/libexec/PListBuddy -c "Copy CompletedProducts InstallAtLogout" /Library/Updates/index.plist
/usr/bin/touch /var/db/.SoftwareUpdateAtLogout
/bin/chmod og-r /var/db/.SoftwareUpdateAtLogout
/usr/libexec/PListBuddy -c "Add -RootInstallMode STRING YES" /var/db/.SoftwareUpdateOptions
/usr/libexec/PListBuddy -c "Add -SkipConfirm STRING YES" /var/db/.SoftwareUpdateOptions
/bin/chmod og-r /var/db/.SoftwareUpdateOptions
elif [[ "$SWUL" == *"[recommended]"* ]]; then
/bin/echo "Installing Updates that does not require Restart"
/usr/bin/sudo /usr/sbin/softwareupdate -i $NoRestartUpdates
fi
exit 0
Posted on 03-22-2024 03:03 AM
This is a fantastic approach, and I really appreciate you sharing this innovative solution for managing software updates more efficiently. Your script is a clever workaround that significantly enhances the update process on OS X 10.8, making it more seamless for users and administrators alike. Great job!