Home > Mac administration, Mac OS X, Packaging, Scripting > Understanding Payload-Free Packages

Understanding Payload-Free Packages

Back when Apple Remote Desktop 1.2 (ARD) was the main tool I used to administer my Macs remotely, I wanted to be able to run Unix commands remotely but needed a delivery vehicle that could send them over ARD. Payload-free installer packages were the answer.

Installer packages are Apple’s preferred way to install software. Apple built into ARD the ability to install software on remote machines using the Install Packages… function. One useful feature of installer packages is that you can have them run a script before or after the package is installed. You can even set up a number of scripts and have them run in the order you designate. Best of all, you can build a payload-free installer package that run scripts but does not install files. So, when I needed to run a Unix command on one or more of my managed Macs, I’d normally build a payload-free package and use the Install Packages… function to push it out to the relevant machines.

With Apple Remote Desktop 2 and later, Apple included a Send Unix Command… function. This gives you the ability to send a Unix command and get the feedback from the remote machine, without the extra work of building a payload-free installer package. However, the practice of building payload-free packages and using those to run my Unix commands stayed with me for the following reasons:

  

1. Ease of use – Running a script contained within a payload-free package does not require any special knowledge or training. All the person using it has to know is how to run an installation using an installer package.

2. Portability – When my management methods evolved beyond using ARD as my primary management tool, I found that different management tools had their own ways to deploy scripts but a common denominator of system management and deployment tools for Macs is that they can deploy installer packages. Using payload-free packages allows me to run scripts on managed machines in a consistent manner regardless of which management or deployment tool is being used.

Installer packages are available in two general categories:

1. Bundle-style installer packages – This style of installer package is created as a Mac OS X bundle that contains scripts and a description of the package requirements and behaviors. As part of creating a bundle-style package, you can define scripts that will execute before or after the installation.

2. Flat installer packages – This type of installer package was first introduced in Mac OS X 10.5 and is a single file. This style of installer package is created as a xar archive that contains scripts and a description of the package requirements and behavior.

Using Scripts with Bundle-Style Installer Packages

Six categories of scripts can be used in a bundle-style package. The categories and their execution conditions are described in the table below:

Preflight

The preflight script is run before files are being installed. If the script does not return an exit status of zero, Installer will cancel the installation.

Preinstall

The preinstall script is run before files are being installed and after the preflight script if one is defined. This script is run only if the component is being installed for the first time. If the script does not return an exit status of zero, Installer will cancel the installation.

Preupgrade

The preupgrade script is run before files are being installed and after the preflight script if one is defined. This script is run only if the component has been previously installed. If the script does not return an exit status of zero, Installer will cancel the installation.

Postinstall

The postinstall script is run after files have been installed and before the postflight script if one is defined. This script is run only if the component is being installed for the first time. If the script does not return an exit status of zero, Installer will declare the installation has failed.

Postupgrade

The postupgrade script is run after files have been installed and before the postflight script if one is defined. This script is run only if the component has been previously installed. If the script does not return an exit status of zero, Installer will declare the installation has failed.

Postflight

The postflight script is run after files have been installed. If the script does not return an exit status of zero, Installer will declare the installation has failed.

For bundle-style payload-free packages, only the following two categories of scripts are used:

preflight

postflight

The other categories of scripts used in bundle-style installer packages depend on something being installed. Since payload-free packages do not install files, these script categories would not execute properly.

Using Scripts with Flat Packages

Two categories of scripts have been defined for use with flat packages:

Preinstall

The preinstall script is run before files are being installed. If the script does not return an exit status of zero, Installer will cancel the installation.

Postinstall

The postinstall script is run after files have been installed. If the script does not return an exit status of zero, Installer will declare the installation failed.

When working with bundle-style and flat packages, one thing to keep in mind is that the script category names will not match up across the different types of installer packages. The table below shows the equivalents between the script types.

Bundle-style Package -> Flat Package Category Equivalents

Bundle-Style Script Category

Flat Script Category

preflight

=

preinstall

postflight

=

postinstall

A commonality between scripts used in bundle-style and flat installer packages is that the scripts must return an exit status of zero or else the Installer application will either cancel the installation process or report that the installation has failed.

Figure_1-Installer_reporting_failure_status

If you’re building a shell script for a payload-free package, one way to ensure that the script returns an exit status of zero to the Installer application is by including exit 0 at the end of your script.

Figure_2-Script_which_uses_exit_0_to_ensure_an_exit_status_of_zero_is_returned_to_Installer

Installer Script Variables

When building a payload-free package, it’s helpful to know that the Installer application can automatically pass along information to the script using variables. The table below shows the variables that are available for use with shell scripts.

Variable

What’s Referenced

$0

=

Returns the path to the script

$1

=

Returns the path to the installer package

$2

=

Returns the target location (for example: /Applications)

$3

=

Returns the target volume (for example: /Volumes/Macintosh HD)

Here’s an example of using the $3 variable in a payload-free package script. In this case, we can take advantage of the Installer process telling us which drive the package is being installed on by using the $3 variable as the target of our script’s actions.


#!/bin/bash
# Detects if /Users is present
# If /Users is present, the
# chflags command will unhide it
if [[ -d "$3/Users" ]]; then
chflags nohidden "$3/Users"
fi
# Detects if /Users/Shared is present
# If /Users/Shared is present, the
# chflags command will unhide it
if [[ -d "$3/Users/Shared" ]]; then
chflags nohidden "$3/Users/Shared"
fi
# Runs a permissions repair to fix
# the world-writable permission on
# /Users
diskutil repairPermissions "$3"
exit 0

view raw

gistfile1.sh

hosted with ❤ by GitHub

Creating payload-free packages

To assist with the task of creating payload-free packages, I’ve written a tool named Payload-Free Package Creator to help create payload-free installer packages. It leverages Apple’s pkgbuild tool to create payload-free packages from existing scripts. All Payload-Free Package Creator components and scripts are available at my GitHub repo:

https://github.com/rtrouton/Payload-Free-Package-Creator

If you want to know more about the process that Payload-Free Package Creator uses, I have a post on how how to use pkgbuild to create payload-free packages.

Payload-free Packages and Receipts

One thing to be aware of when using payload-free installer packages to run commands is that payload-free flat packages may not leave an installer receipt behind. When installing a payload-free package built with Apple’s pkgbuild tool using the —nopayload flag, no receipt is created as part of the installation process. When asked about this behavior, Apple’s response was that this is an intended behavior for payload-free packages built using pkgbuild as the principal purpose of receipts is to track upgrade behavior. Apple further stated in their response that payload-free packages are intended to be a convenient container for scripts.

Using payload-free packages to deploy scripts has been a vital part of my toolkit for many years. Understanding the functionality that payload-free packages can offer, and knowing how to quickly create them to meet your needs, will hopefully add them to yours as well.

  1. marquette rogers
    June 2, 2014 at 12:40 pm

    Excellent write up. Particularly since it can be confusing the first time around, understanding the terminology for preflight and preinstall. Don’t recall seeing the usual “see below the jump”.

  2. June 3, 2014 at 9:45 am

    Great write up! Love how it is all laid out! Thanks!

  3. Nic
    July 30, 2019 at 11:52 pm

    Appreciated! Thanks

  1. No trackbacks yet.

Leave a comment