Ooops – forgot to mention the script changes…

My  mind is a little elsewhere at the moment – I’ve been finishing an album of awesome music (more details at – and I’ve been a little distracted.

So please accept my apologies for failing to mention that there a couple of important changes in the script.

The first is that just run straight from the bundled package, the script will default to downloading from Apple’s own servers.

You’ll need to comment out a couple of lines and add your own server details into the relevant fields.

The second important note is that the script also now supports different branches of software update repositories, as software such as the very useful Reposado provides. This means you can have separate “release” and “testing” branches, or different application updates for separate departments etc.

You’ll need to check the script to see how to enable these options, and you’ll probably want to repackage up different versions for each branch offered, or just replace the single script in /usr/local/bin/macsoftwareupdate with your custom version .



Posted November 21, 2011 by mrwinter in Uncategorized

Lion compatible version of Mac User Software Update

I’ve just uploaded an OSX 10.7 Lion compatible version of the Mac User Software Update scripts and package.

You can also download the disk image containing the package and individual scripts HERE.

The new version also includes a list of the available updates in the first pop-up window.

I haven’t had a chance to update the documentation yet, which has changed slightly.

I am also still working on a completely new version of the script in Ruby with additional features such as update selection etc, but it’s a while away yet.

Please fire an email to if you encounter any bugs or unusual behaviour.


Posted November 21, 2011 by mrwinter in Uncategorized

Minor updates to Mac User Software Update application.

I’ve posted a slightly newer version of the MacSoftwareUpdate.dmg containing bug fixes for the previous version which were kindly pointed out by Bill Strube. (Thanks Bill!)

Specifically, there was an error with the script which contained a call to a legacy launchd script. This has now been fixed.

Posted January 26, 2011 by mrwinter in Code

Tagged with , , , , ,

Mac non-admin User Software Updater

One of my main daily activities (see for the others) is working as a systems administrator at a fairly high profile, and very busy, company.

One of our regular issues was that necessary security updates and new versions of applications released by Apple weren’t being updated because our user accounts don’t have administrator privileges. The usual dialog box just doesn’t show up if you’re not an admin.

Our users are very mobile and are often on and off wired and wireless networks, which means catching every laptop when pushing out software updates via Apple Remote Desktop (ARD) is very difficult, to say the least.
Users could run the application themselves from the Apple menu but needed to contact the support team to enter admin details to install the updates.

We needed a way of the non-admin users being able to install the updates themselves when it suited them in their busy schedule.

While many people think this isn’t such a great idea (it could mean users install buggy versions of software, which Apple occasionally let slip through), this isn’t as much of an issue in our facility as we run our own Software Update Server and vet the releases before the users are allowed to install them.

I’ve been allowed, by the powers that be, to share the little application I created, which adds a slightly more user friendly user interface and schedule options to a script originally written by Mike Zeller, with the open source community I’ve been helped by for years. It feels good to start giving (albeit a little) back.

This little series of scripts and .plist files allows non-admin Apple Mac users on OSX 10.5 and OSX 10.6 to set their own schedule and run the standard Apple Mac updates from either a local Software Update Server (SUS) or direct from Apple’s usual software update servers.

It’s still at version 1, it was my first real attempt at scripting when I wrote it about a year ago, but version 2 is in the works… very slowly.

It looks like this when it first starts up:

Script files and what they do.

The main script uses which you’ll need to download and install to /usr/local/bin/ before you install anything else. (I’m currently writing an updated version which uses Pashua for updated functionality but it’s a wee way away yet.)

Files which will be installed by the package are:

/usr/local/bin/macsoftwareupdate/ – The main script, runs the majority of the functions. Makes changes to swud_sched.conf when the schedule function is used.            – A script which monitors changes to the schedule config file (swud_sched.conf) and writes the defaults commands once the main script is done.
swud_sched.conf          – The file containing required schedule commands
/Library/LaunchDaemons/ – the schedule preference file (set by the Schedule button)              – used to set default watch and  script paths

When I use the app at work, it has access to a deployment NFS server containing the default preference file and the CocoaDialog app for easy retrieval by the script if necessary.

This means that I can globally change the default (or fix broken manually edited files!) by simply removing the local copy on the client and the script picks up the default again automatically next time it runs. This option is commented out by default but easy to implement.

You could also use other transfer methods of course if you wish to play with it.

How It Works.

The main script goes through the following steps:

  • Set up the variable defaults. This is where you can customise it to your organisation.
  • Checks for the files it needs. NFS default file options are available as mentioned above.
  • Turns off the standard software update app for the duration of the script.
  • Checks there is at least 2GB of space left on the boot drive. It’s a rough hack at the moment but I plan to make it better…
  • Agrees to the license agreements.
  • Sets a standard error dialogue. Easily customisable to include contact email addresses etc.
  • Sets up the setup_prefs function. Known as the “Schedule” in the GUI. Users get to choose Daily + Time of Day, Weekly + Day of Week + Time of Day, Monthly + Day + Time of Day.
  • Sets up the detection_prompt function. The initial prompt alerting the user to new software and giving them the option to “Download”, “Postpone”, or set their “Schedule”.
  • Sets up the noreboot_prompt function. If a reboot isn’t required, the user gets to “Install now”, a fake progress bar pops up for the duration of the install, then the user is thanked for their patience on completion. The Schedule function is also available.
  • Sets up the leo_reboot function. If the mac is running OS10.5 and requires a reboot this function is called. It pops up a dialog alerting the user a reboot is required and asks to “Download” files, re-checks for updates, sets up the files to install on restart, installs the updates, then prompts the user to “Restart”. The Schedule function is also available during most of this.
  • Sets up the reboot_install function. First checks the OS version and defers to the leo_reboot prompt if required. OS10.6 deals with things slightly differently so the reboot_install function differs from the leo_reboot function. It alerts the user a reboot is required, requires the “Restart” button without an intermediary download button, downloads the packages while a fake progress bar pops up, issues the reboot command to the mac which goes into the standard Apple Software Update installation dialogue requiring the user to “Install and Restart”. The Schedule function is also available during the first “Restart” dialogue.

So everything up to this point is now setup as functions and is ready to be called in the next part of the script. This is the part that figures out what actually needs to happen.

  • Runs a softwareupdate -l (list available updates) and writes the output to a file in the /tmp/ directory.
  • Checks the file to see if there are any updates available. If there are none, it quits silently. If there are updates it continues…
  • Pops up the first detection prompt asking whether the user would like to start the process.
  • Checks to see whether a restart is required.
  • Calls the noreboot_prompt if a reboot is not required and calls the reboot_install function if one is needed.

Customisation Options

swserver – local Software Update Server (SUS) URL. Enter the address and port number. The script will default to Apple’s servers unless set.

cdtitle – customise the header of the dialog box. I usually just add the company name etc.

deployserverpath – path to CocoaDialog and default preference files on a network location. You’ll need to enter details and un-comment two sections in the script, as well as putting the needed files on a server in a directory named “MacSoftwareUpdate” .

cdialog and cdialogapp – path to CocoaDialog application on local machine.

Packaging it yourself.

I’ve provided a package for easy installation of the application, but if you’d like to configure the main script  before deployment to the rest of your organisation, I’ve also provided the script files for you to modify.

If you’d like to create a customised package, I’ve included a small script in the disk image named “” which you can use as a postflight script in your package to automatically load it and get it working. It won’t work until the first scheduled time to run (which defaults to 2.35pm daily).

You will probably wish to bundle them up and re-distribute them within your local organisation yourself using Apple’s provided PackageMaker or Iceberg, Composer or similar. Usage of those applications is outside the scope of this article.

How to install.

To install in a GUI: double-click the package and follow the instructions.

To install from the command line:

ssh into the target laptop

run this command

sudo installer -pkg /path/to/installer/MacUserSoftwareUpdate.pkg -target /

You can check it has installed correctly by running sudo launchctl list If you don’t see see “launchctl list returned unknown response”, but instead get information about the launchd script, the install has worked.

To install from ARD:

Click the Install icon.

Click the + icon or drag the package into the window.

You won’t need to force a restart to make it work.

Click Install.

How to run the app manually.

Carefully edit the values in /usr/local/bin/macsoftwareupdate/swud_sched.conf to reflect when you’d like it to run. As soon as you finish editing it, the watcher will write the values into the main plist and it will run when you said it should.

Correct format for defaults commands.

Before writing any of these commands to the conf file, delete the current contents to ensure consistency.

Lines have been split at the “\\” for easier WordPress display. Please remove the “\\” if copying and pasting and ensure there is only one space between MacSoftwareUpdate and StartCalendarInterval.


Run one day a month on the date specified in -int “$date” (“15” to run on every 15th of the month.)

defaults write /Library/LaunchDaemons/ \\
StartCalendarInterval -dict-add 'Day' -int "$date"

You’ll also need to include the Hour and Minute to specify the time of day (Hour = the hour in 24 hour time: 2pm = 14):

defaults write /Library/LaunchDaemons/ \\
StartCalendarInterval -dict-add 'Hour' -int "14"
defaults write /Library/LaunchDaemons/ \\
StartCalendarInterval -dict-add 'Minute' -int "00"



Run one day a week on the day specified in -int “$day”. (Sunday = “0”, Monday = “1”, Saturday =  “6”)

defaults write /Library/LaunchDaemons/ \\
StartCalendarInterval -dict-add 'Weekday' -int "$day"


You’ll also need to include the Hour and Minute to specify the time of day (Hour = the hour in 24 hour time: 2pm = 14):

defaults write /Library/LaunchDaemons/ \\
StartCalendarInterval -dict-add 'Hour' -int "14"
defaults write /Library/LaunchDaemons/ \\
StartCalendarInterval -dict-add 'Minute' -int "00"



Only needs the time variable set to run every day (Hour = the hour in 24 hour time: 2pm = 14).

defaults write /Library/LaunchDaemons/ \\
StartCalendarInterval -dict-add 'Hour' -int "14"
defaults write /Library/LaunchDaemons/ \\
StartCalendarInterval -dict-add 'Minute' -int "00"

Useful copy and paste commands for troubleshooting

Read the contents of the launchd scripts:
sudo defaults read /Library/LaunchDaemons/
sudo defaults read /Library/LaunchDaemons/
Check the launchd script is loaded:
sudo launchctl list | grep littleboyblue
sudo launchctl list
Unload (stop) the script from running at the scheduled time:
sudo launchctl unload /Library/LaunchDaemons/

Load (start) the script to run at the scheduled time:

sudo launchctl load /Library/LaunchDaemons/

User Facing Documentation…

I was lucky enough to have Jack Elder ( ),  one of our resident document writers, write up some user facing instructions which may help with explain how to use it a little more succinctly than I can. Check for the “User Facing Documentation” document included in the disk image.

I hope this is useful for you, and please let me know if you find errors, or good ideas for the scripts.


Posted January 22, 2011 by mrwinter in Code

Tagged with , , , , ,

Little Boy Blue

Welcome to

I have no idea what this site is going to turn into – at the moment it’s a place to put a little code I’ve been working on, and may well end up being a completely different entity.

This is the beginning…

Posted January 19, 2011 by mrwinter in Uncategorized