Another Update for Packaging Book

I pushed another update for “Packaging for Apple Adminstrators.”

Greg Neagle posted an article recently where he describes how he sleuthed a way past an annoying High Sierra bug.

In High Sierra when you add more than one package to a custom NetInstall workflow with System Image Utility or startosinstall all the custom packages will fail.

Greg’s workaround involves adding an identifier and version to each of the distribution packages. It is still an open question why this data is required, but the workaround is easy enough.

I have added a section on how to do this to the “Building Distribution Packages” section of the book. As always: if you have already purchased the book, you can download the update with new content for free in the iBooks application on your Mac, iPad or iPhone. Or go and get the book now!

Rich Trouton also updated his “First Boot Package Install Generator Tool” to provide this data.

On the macOS Version

In many administration scripts, you need to check the version of macOS, to make sure you don’t try to access features that are not present on other versions.

Getting the Version

On macOS you can get details on the version of the currently running system with the sw_vers command:

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.13.1
BuildVersion:   17B48

You can add the -productVersion argument to get just the product version number:

$ sw_vers -productVersion

The first part of the version number (“major” version) is always 10 (so far). The second part (“minor” version) denotes the version of macOS (11: El Capitan, 12: Sierra, 13: High Sierra, etc.) and the third (“patch” or update version) the update number. (Useful list of macOS versions and names on Wikipedia.)

Note: because the first part of the version for macOS is always 10, some call the second number the major version of macOS and the third the minor version. It does not really matter as long as you are explicit what you mean and remain consistent. Documentation in code helps avoid confusion.

You can test for a specific version with string comparison:

if [[ $(sw_vers -productName) == "10.12.6" ]]; then
    echo "Sierra"

This will get tedious when you need to check for many patch versions. The [[ operator let’s you use the asterisk * as a wildcard in string comparisons:

os_ver=$(sw_vers -productVersion)
if [[ "$os_ver" == 10.13.* ]]; then
    echo "macOS High Sierra"
elif [[ "$os_ver" == 10.12.* ]]; then
    echo "macOS Sierra"
    echo "(Mac) OS X something"

But even that can get tedious when you have a range of minor versions. Often you want to check for the minor version to be higher than a certain number (i.e. “Mavericks and later”)

Splitting the Version

You could split the version into its parts with awk:

echo "minor version:" $(sw_vers -productVersion | awk -F. '{ print $2; }')
echo "patch version:" $(sw_vers -productVersion | awk -F. '{ print $3; }')

This works well, but is a bit unwieldly.

You can also split the version string into a bash array:

os_ver=$(sw_vers -productVersion)

IFS='.' read -r -a ver <<< "$os_ver"

echo "minor version: ${ver[1]}"
echo "patch version: ${ver[2]}"

The read command splits the string into a bash array with the periods as a separator. There is a lot going in this command, so let’s have a look at the pieces.

First we assign the ‘.’ to the IFS environment variable. Characters in the IFS (“Internal Field Separator”) variable are used by bash to split strings into their pieces. The normal IFS variable consists of the whitespace characters: space, tab and newline. However, we want to change this so that the read command splits at the periods in our version string. This syntax with the variable assignment directly followed by the command without a separator tells bash to change the IFS variable just for the next command. This way the standard IFS variable is not affected.

The read command splits the input into an array and assigns it to the ver variable. Then we can get the elements in the ver array using the ${ver[index]} notation. (bash arrays are zero-indexed, so the first element ${ver[0]} will always be 10.

Once you have split out the parts of the version string, you can then use them for numerical comparisons:

if [[ "${ver[1]}" -ge 9 ]]; then
    echo "somewhere in California"
elif [[ "${ver[1]}" -ge 2 ]]; then
    echo "officially a feline"
    echo "secretly a feline"

Get the macOS version from other Volumes

The sw_vers command only show the version for the currently booted system. System administrators often need to know the version of the OS installed on a different volume. Usually this happens in the context of installations. In installation scripts the installer system will pass the path to the target volume as the third argument $3.

Learn all about installer packages and installation scripts, read my book “Packaging for Apple Administrators

On macOS the system version information is also stored in a property list file in /System/Library/CoreServices.plist. In an installation script (postinstall or preinstall you can get the target system with:

/usr/libexec/PlistBuddy -c "print :ProductVersion" "$3"/System/Library/CoreServices/SystemVersion.plist

Learn all about PlistBuddy and Property Lists in my book “Property Lists, Preferences and Profiles for Apple Administrators

macOS Installer applications have the version of macOS that will be installed in yet a different file. Tim Sutton has already documented this here.

Other Application’s versions

Obviously, you can use this approach on other version numbers as long as they follow the scheme of “numbers separated by dots.” (Not all applications do.)

To get the version of a macOS application you can read the CFBundleShortVersionString from the Info.plist file in the app bundle:

/usr/libexec/PlistBuddy -c "print :CFBundleShortVersionString" /Applications/

Some applications do not have a CFBundleShortVersionString and then you should fall back to the CFBundleVersion key.

appVersion=$(/usr/libexec/PlistBuddy -c "print :CFBundleShortVersionString" "$infoPath")
if [[ -z "$appVersion" ]]; then
    appVersion=$(/usr/libexec/PlistBuddy -c "print :CFBundleVersion" "$infoPath")

Build Number

Aside from the numerical version number or product version, macOS also has a build number, which follows a different schema. The first part is a number which matches the “Darwin version” of macOS. Mac OS X 10.0 had a Darwin version of 4 and that number has increased with every version of Mac OS X. Currently, macOS High Sierra 10.13 has a Darwin version of 17. Then follows a single capital letter, with A being the first release of a version (i.e the 10.x.0 version), B is the first patch update (10.x.1) and so on.).

Finally the last number is the build number. The build number usually incremented during Apple internal development. You can see the build number increasing during beta releases. (beta build numbers may have an ‘a’ at the end).

However, sometimes Apple will release hardware specific versions of macOS which usually have four digit build numbers (usually starting with a 1). Also security updates can change the build number (usually to four digits starting with a 2) without changing the numerical version number.

Because of this it can also be useful to parse the build number out of the build version. Since the first two parts of the build version are directly mapped to the numerical version, we are only interested in the number:

build_ver=$(sw_vers -buildVersion)
if [[ "${ver[1]}" -le 5 ]]; then # 10.5 was darwin 9, 10.6 darwin 10
    build_number="${build_ver:3}" # ignore first two characters
    build_number="${build_ver:4}" # ignore first three characters

if [[ ${build_number: -1} == 'a' ]]; then 

echo "build number: $build_number"

You can get all this code in a sample script I posted on gist.

Weekly News Summary for Admins — 2017-11-17

Another productive week. If you have to no time to read anything else, at least take a moment to bookmark Charles Edges list of tools for Apple Administrators.

Also, greetings to everyone at MacTech Conference this year! And the JNUC sessions are available on YouTube. Much to read/watch/listen and catch up to!

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

#! On Scripting OS X

📰News and Opinion

🔨Support and HowTos

🍏Apple Support

♻️Updates and Releases

MacTech Conference Session Notes

📺To Watch

🎧To Listen


To support Scripting OS X, consider buying one (or both) of my books. Thank you!

If you have already bought and read the books, please leave a review on the iBooks Store. Reviews are important to help new potential readers make the purchase decision. Thank you (again)!

One year of “Packaging for Apple Administrators”

I published my book “Packaging for Apple Administrators” one year ago. Flashback time (insert harp chord sounds)!

When I started out the goal was to write the big guide on everything a Mac Admin needs to know. It quickly dawned on me that this would result in a huge tome which would be impossible to write and maintain. I realized that with digital publications, I could publish smaller books and could “publish early and often.” I would publish a specialized book and update that when I learnt new information or when software updates revealed or retired certain strategies. That realiziation freed me of “perfection anxiety.”

The choice for the first topic was easy. Analysing and creating package installers is an essential skill for Mac Administrators. But it is also poorly documented. Apple has no real documentation on the package format on their website. Also no best practices. For years the Mac Admin community has been very helpful on guiding newcomers through the process, but in the end everyone relied some information transfer through “osmosis”. New admins would pick up bits and pieces on how to build packages, what to do and what not to do from posts in IRC and Slack, the occasional blog post and maybe a presentation or workshop at a conference.

This was the perfect “low-hanging fruit” topic to start out with. After about six months of part time writing it was in some form that I was not embarassed too much about any more. That was last November.

I have since pushed four updates to the books. (The first 1.1 update was to remove some placeholder text that was persisting in the default Glossary entries. The iBooks store reviewers don’t like that.) The other four updates have added two appendices, eight new sections and countless other fixes, extensions and clarifications. And everyone who bought the book got the updates for free.

I believe I now have included most of the fundamental concepts on packaging. However, some sections might profit form having more examples. In particular more complex examples would be useful. My main challenge in providing complex examples is that I cannot use software which requires pricey software licenses. However, this is usually the most problematic software which requires complex and challenging workarounds. (If you have recommendations for useful, free software, which requires complicated packaging workarounds, please let me know.)

So keep expecting updates and new content!

So what’s next? The obvious sequel for “Packaging” seemed to be “Automated Packaging” and would cover AutoPkg. The AutoPkg book is sitting, half-written, on my computer. However, it turns out that AutoPkg requires much more prerequisite knowledge. I found myself adding chapters and sections on other topics. One of these topics grew enough that I published it as its own booklet: “Property Lists, Preferences and Profiles for Apple Administrators” or “PR3” for short.

While “Packaging” and “PR3” are selling and I am getting lots of wonderful feedback from the readers, the numbers sold do not justify going in on writing full-time. This does not come as surprise, since Mac Administration is quite a niche market and I have neither time nor budget for any form of marketing, other than word-of-mouth. (So, please, if you liked the books and want to do me a favor, tell some fellow Mac admin about my books, and/or leave a review on the iBooks store.)

Also at that time (Spring 2017) the rumors of Apple drastically changing access to macOS, even (or especially) for administrators and their tools were rampant. Finally, Jamf was promising a great new “Patch” feature for the long-expected Jamf 10. All of these trends together might have invalidated the information in a book on AutoPkg (and maybe even the Packaging book). It seemed like a good time to put the AutoPkg book on the back burner and write about something else.

I have written a lot of blog articles over the summer. I am currently sorting through them, filling in the sections and chapters and trying to assemble useful books from them.

I have also presented at MacSysAdmin in Göteborg and am looking forward to presenting at more conferences in the future. Finally, I recently started working as a System Engineer/Consultant for a Dutch reseller. While all this other work is limiting the time available for writing, I also expect it to inspire real-world experiences which should lead to better writing, both on this weblog and the books.

So, one year after “Packaging”: the books are still being updated, the Macpocalypse did not happen and packaging is still a skill you need to have as a Mac Admin! Expect more books sometime in the future! Until then, buy the books I have!

(If you have already purchased and read the books, please leave a review on the iBooks store. The iBooks store segregates reviews per territory, so every single one counts! Thank you!)

Weekly News Summary for Admins — 2017-11-10

After a few weeks of many updates, things are quieting down a bit. You can tell because this newsletter has less on the news and updates sections and more in the how to. People are figuring out how to make the new updates work and are sharing their findings.

Well, not entirely without updates. iOS 11.1.1 dropped, which fixes a weird but annoying auto-correct bug.

As always, many thanks to all those who document and share.

Especially Rich Trouton, whose weblog “DerFlounder” – which is regularly featured in this newsletter – celebrates its eleventh year!

Congratulations, Rich! You are truly an inspiration to us all. Thank you!

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

#! On Scripting OS X

📰News and Opinion

🔨Support and HowTos

♻️Updates and Releases


To support Scripting OS X, consider buying one (or both) of my books. Thank you!

If you have already bought and read the books, please leave a review on the iBooks Store. Reviews are important to help new potential readers make the purchase decision. Thank you (again)!

Get the “Marketing Name” for a Mac

I am working on making our onboarding/installation process nicer. For that I decided it would be nice for SplashBuddy to say “Welcome to your ’MacBook (Air|Pro)/iMac/Mac (mini|Pro)”.

You can get the Mac model name easily enough from System Profiler:

$ system_profiler SPHardwareDataType
    Hardware Overview:
      Model Name: MacBook Pro
      Model Identifier: MacBookPro14,3

However, this is only the “model family.” When you go into “About this Mac” it give you a more detailed “name” like “MacBook Pro (15-inch, 2017).”

Friendly people on the MacAdmins Slack pointed me towards a property list file in the ServerInformation framework:


This contains the “Marketing Model Name” among other information for each type of Mac, sorted by the model identifier, which you can also get from system_profiler or with sysctl -n hw.model. Even better this plist is localized, so you can get the marketing name in the current user’s preferred language.

The easiest way to get the correct localization is to use the system’s NSBundle class and methods and the read the property list. I chose Python to do this, since it offers access to NSBundle with the Cocoa-bridge and reading and working with property lists is very easy. (Learn more about working with property lists in Python in my book: ‘Property Lists, Preferences and Profiles for Apple Administrators’)

You can run this script with a parameter:

$ ./ MacBookAir7,2
13" MacBook Air (Early 2015)

When you don’t give a parameter, it will use sysctl -n hw.model to determine the current Mac’s model identifier and use that:

$ ./
15" MacBook Pro with Thunderbolt 3 and Touch ID (Mid 2017)

Since the script uses NSBundle and does not go directly to a specific localization of the property list file, it will give different language results depending on the preferred language of the user:

$ ./     # (Dutch)
15-inch MacBook Pro met Thunderbolt 3 en Touch ID (medio 2017)

$ ./     # (Japanese)
15インチMacBook Pro、Touch Barを搭載(Mid 2017)

Weekly News Summary for Admins — 2017-11-03

Another big week: Apple sent out their *OS *.1 updates this week, Jamf 10 dropped, Apple Financial calls and iPhone X ships.

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

📰News and Opinion

🔨Support and HowTos

🍏Apple Support

Q4 2017 Earnings


♻️Updates and Releases

🎧To Listen


To support Scripting OS X, consider buying one (or both) of my books. Thank you!

If you have already bought and read the books, please leave a review on the iBooks Store. Reviews are important to help new potential readers make the purchase decision. Thank you (again)!

Weekly News Summary for Admins — 2017-10-27

Back from vacation, back into work. JamfNation User Conference was this week. Looks like everyone had a great time!

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

#! On Scripting OS X

📰News and Opinion

🔨Support and HowTos

🍏Apple Support

♻️Updates and Releases

📺To Watch

🎧To Listen


To support Scripting OS X, consider buying one (or both) of my books. Thank you!

If you have already bought and read the books, please leave a review on the iBooks Store. Reviews are important to help new potential readers make the purchase decision. Thank you (again)!

Imaging is Dead… Long Live the Installer!

The writing has been on the wall for a long time. With the release of macOS High Sierra, Apple has finally confirmed that imaging is dead.

Apple doesn’t recommend or support monolithic system imaging for macOS upgrades.

The Final Nail

The final nail in the coffin for imaging is this support article: Upgrade macOS on a Mac at your institution

It states the limitations to installing and upgrading macOS with High Sierra:

  • the Mac being installed or updated must be connected to the internet
  • installations and updates cannot be done on external devices, like those connected via Target Disk Mode, Thunderbolt, USB, or Firewire
  • there are four supported methods of installing macOS High Sierra

These methods are also re-iterated in this section in the macOS Deployment Reference


Apple’s stated reason for requiring the installer is to ensure that a Mac’s firmware is all up to date and matches the OS installed on it.

Only the macOS Installer can download and install the firmware update. Firmware updates can’t be done on external devices, like those connected via Target Disk Mode, Thunderbolt, USB, or Firewire.

This is especially important in High Sierra, because to boot into a system on an APFS formatted (or converted disk) the Mac’s firmware needs to be able to mount and read APFS. The firmware that was installed with 10.12 or earlier is not able to read APFS volumes and. When you image a Mac with High Sierra and APFS without updating the firmware, you will get the question mark at boot, because the firmware cannot find a system.

However, the EFI, which manages (among other things) the boot process is not the only “firmware” that needs to be managed on your Mac. Many of the hardware components in your Mac, such as the SSD, the power controller (SMC) and the TouchBar controller on the new MacBooks Pro, have their own firmware that needs to be installed and updated.

Apple has been increasing the protection of the vital parts of the system and hardware. The firmware in these components cannot just be changed by any process. Only the Apple macOS Installer application has sufficient privileges and entitlements to perform these updates. The installer process has to run on the Mac itself, it cannot run over target disk mode.

Future Mac hardware might introduce even more components that require firmware.

On iOS, a secure boot chain prevents tampering with the system on a device after it has been installed. The secure boot chain also prevents replacing the system with an image from another device.

It is conceivable that Apple wants to implement a secure boot system on future Macs as well. Current Macs probably do not have the hardware required to implement this. (The TouchBar MacBooks Pro have a Secure Enclave chip like the iPhone and iPad and might already have the necessary pieces in place.)

So now what?

This has been coming for a long time. Even though APFS is not, as originally predicted, the direct culprit. It is still end-of-the-line for imaging.

However, the news is not entirely dire. Apple has been surprisingly forthright about the direction they want to go. While the documentation is a bit lacking, there are instructions on what the solutions for Mac System Adminstrators should be.

The four supported means of installing and upgrading macOS and the firmware for Macs are a clear direction of what needs to be done. However, Apple is a bit shy on how administrators can and should implement them.

There are a few options:

Put the Burden on the Users

This will work in some deployments where users are in control of their Macs. Either a full BYOD (Bring Your Own Device) scenario, or one where devices provided by the organisation are in full control of the user.

Even when the devices are enrolled in an MDM, users are still administrators and in control. Administrators can use reporting tools, to determine which Macs are capable of installing High Sierra and not upgraded yet.

You can even use reporting tools to gather information on the firmware and whether it matches the latest version.

You can then instruct users with email or notifications to download the High Sierra installer and initiate the upgrade themselves. You should warn them to have a current backup and that the process might take some time, so it should be run overnight.

If you have a software management system in place, you can use that to load the macOS Installer application on the clients and notify the user when it is ready.

The Mac App Store only downloads a “stub” installer application which is then filled in with an extra download. If you have blocked access to Apple Software Update Servers or redirected clients to a local, managed Software Update Server, clients might not get the complete installer application. Greg Neagle has a great post on this.

To save download time for the users, you can also provide USB/Thunderbolt drives with a bootable installer drive. This might speed things up a bit, though it does not really change the process.

How do we Automate this?

As system administrators we want to automate the process, so that it ideally does not require any human interaction. That way we can replicate the process hundreds and thousands of times.

Ideally, we also want to inject some custom steps into the process. Apple provides two means of achieving both of these steps, and some open source tools are providing solutions as well.


A custom NetInstall set built with Apple’s System Image Utility is one of the supported means of installing and updating macOS (and the firmware) to High Sierra.

You can find System Image Utility in /System/Library/CoreService/Applications. You can customize the process and even add your own installer packages, scripts or profiles. Packages used in System Image Utility have to be Distribution Packages.

Since a NetInstall system is like a Recovery system, you can use scripts to control behavior of your Mac like allowed NetBoot IPs, or ‘User-Approved Kernel Extension Loading’ (UAKEL) here as well.

You can even automate the NetInstall process to a point where, once you have chosen the NetInstall volume (when holding the the option key at boot) the remaining process is without interaction. (Though this is a dangerous choice, as it might simply wipe and re-install Macs. Use the other limitation options such as by MAC address or hardware type to keep this safe.)

NetInstall requires Mac running macOS Server. However, BSDPy can replace a NetBoot/NetInstall server and runs on many platforms, including VMs.

Note: as of 10.13.0 there still seem to be a few bugs with NetInstall on HighSierra. It works mostly but seems exceedingly slow. Also some admins have reported problems with adding mulitple packages, profiles or scripts for configuration. 10.13.1 is already in beta and seeding and you should be testing that.

NetInstall on USB

If you do not have the infrastructure to run a NetInstall or BSDPy server, you can also restore the NetInstall.dmg image that System Image Utility creates to an external drive. When mounted on a Mac, it will the High Sierra installer applications, and double-clicking it will start the proper installation process.

Any additional packages, profiles or scripts will be included with this custom external install application as well.

The startosinstall Command

When you already have a management system (Munki, Jamf, Filewave, etc.) you want to initiate the update process with rules or policies. At first glance the supported means of installing macOS seem to be at odds with managed client workflows, since they require user interaction.

However, there is a tool hidden inside the macOS Installer application (since macOS 10.12 Sierra) called startosinstall. The full path to the tool is

/Applications/Install macOS High

Note: I believe it was Rich Trouton who first documented this tool in his notes for WWDC 2016. Since then many admins and open source projects have worked to figure out how to use this tool in the best way.

When you run it with the --usage argument you get the following:

$ /Applications/Install\ macOS\ High\ --usage
Usage: startosinstall

--applicationpath, a path to copy of the OS installer application to start the install with.
--license, prints the user license agreement only.
--agreetolicense, agree to license the license you printed with --license.
--rebootdelay, how long to delay the reboot at the end of preparing. This delay is in seconds and has a maximum of 300 (5 minutes).
--pidtosignal, Specify a PID to which to send SIGUSR1 upon completion of the prepare phase. To bypass "rebootdelay" send SIGUSR1 back to startosinstall.
--converttoapfs, specify either YES or NO on if you wish to convert to APFS.
--installpackage, the path of a package to install after the OS installation is complete; this option can be specified multiple times.
--usage, prints this message.

Example: startosinstall --converttoapfs YES 

There is also an undocumented --nointeraction flag which can be used to run the tool without any user interaction. This is obviously useful for management systems.

Once you have used to your management system to make sure the macOS Installer application is on the client system, you can execute a script with the startosinstall command to initiate the installation process. Remember that the installation process can take a long time, so it should be initiated by the user in a Self Management portal or run during off-hours for kiosk like Macs in labs or classrooms.

startosinstall --applicationpath /Applications/Install\ macOS\ High\ \
    --agreetolicense \

The --converttoapfs [YES|NO] argument allows you to suppress automatic APFS conversion on SSD Macs.

There is also a --volume argument to target the non-boot volume. However, this will only work when SIP is disabled or when you run startosinstall from a Recovery/NetInstall disk.

The --installpackage option allows you to add one or more custom packages that will be installed after the OS installation is complete. This is very useful for customization and cleanup. Packages used with startosinstall --installpackage also have to be Distribution Packages.

Note: even though the usage states that you can repeat the --installpackage argument, as of 10.13.0 only the first package given will run the installation with fail with more than one package. Make that one package count. (Note: edited this paragraph. Thanks to Greg for clarifying.)

Tool Support

Is Imaging completely dead?

The imaging tools (like Disk Utility, hdiutil and asr) will work with APFS volumes. However, the support article states:

You can use system images to re-install the existing operating system on a Mac.

So when you need a workflow that requires quick re-imaging, you can use one of the supported methods to install or update the Mac (Firmware and OS) and then use monolithic (or thin) imaging over network or thunderbolt for fast restores. This is useful for scenarios where fast imaging turnaround is required, such as classrooms and labs or loaner laptop setups. However, you have to use extra care to make sure the image system version matches the version that was installed.

Going forward, I expect imaging to be less and less feasible as future Mac hardware and security features will make it harder and harder to use. The times where we could have just one image which will run on all supported Macs might be over as hardware (and the software required to run the hardware) becomes more and more fractured. Note that there is not a unified single ‘iOS’ image/installer for all iOS devices.


macOS High Sierra 10.13.0 works well for individual users. However, there still are quite a few issues that are relevant for managed deployments. There are many problems with Active Directory and Filevault, NetInstall is slow and adding multiple packages to an installation is broken. Just to mention a few.

Even though it makes sense for some deployments to hold back from High Sierra right now, you will want or have to upgrade soon.

Apple said at WWDC the iMac Pro will ship in December 2017. Its tech specs page, states it will run High Sierra. You can expect it to require High Sierra.

Also, critical security patches might only be pushed for High Sierra.

Imaging is dead. In an unusual move Apple has come right out and said it loud and clear. If you have not done so already, start testing and implementing one of the above strategies right now, so you are ready to move to High Sierra.