Home > Apple Remote Desktop, Casper, Mac administration, Mac OS X, Scripting, Unix > PATH environment variables and Casper 9.8

PATH environment variables and Casper 9.8

In the wake of the release of Casper 9.8, where the Casper agent’s jamf and jamfAgent binaries have made their planned move from /usr/sbin to /usr/local/jamf/bin, a number of Casper-using folks who were used to running commands that referenced the jamf and jamfAgent binaries from Apple Remote Desktop (ARD) or other tools began to see errors that indicated that the jamf and jamfAgent binaries could not be found.

Screen Shot 2015 09 23 at 8 23 05 PM

Screen Shot 2015 09 23 at 8 11 28 PM

Conversely, opening a Terminal session and running the exact same command works fine.

Screen Shot 2015 09 23 at 8 21 14 PM

Why are different tools acting differently? The root cause is that they each have different PATH environmental variables, usually referred to as $PATH. For more details, see below the jump.

PATH environmental variables define which directories in the OS are searched for commands. When a command name is specified, the OS searches through the directories defined in the PATH environmental variables, examining each directory and looking for an program which matches the command name. Once the OS finds it, that command is executed.

However, if a command is not found as a result of this search, an error results instead of the command being executed.

By default, a Terminal session in OS X will have the following PATH environmental variables:

/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

The jamf and jamfAgent binaries are located in /usr/local/jamf/bin, but JAMF also added symlinks to /usr/local/bin for both of these binaries. Because /usr/local/bin is included in the OS’s search, /usr/local/bin/jamf and /usr/local/bin/jamfAgent can be run in Terminal using just the commands jamf and jamfAgent.

In contrast, Apple Remote Desktop has different PATH environmental variables:

/bin:/sbin:/usr/bin:/usr/sbin:/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support

As /usr/local/bin is not referenced in ARD’s $PATH, the OS does not know to search that directory. As a consequence, /usr/local/bin/jamf and /usr/local/bin/jamfAgent are not located and an error results.

A similar situation applies to LaunchD items, like LaunchAgents and LaunchDaemons. LaunchD items have the following PATH environmental variables:

/usr/bin:/bin:/usr/sbin:/sbin

As with ARD,  /usr/local/bin is not referenced in LaunchD items’ $PATH and the OS does not know to search that directory.

A commonality between all three (Terminal, ARD and LaunchD) is that they all include /usr/sbin as part of their $PATH, so the /usr/sbin/jamf and /usr/sbin/jamfAgent binaries are always found when Terminal, ARD and LaunchD items search for those commands.

This condition does not apply to /usr/local/bin, as only Terminal sessions include /usr/local/bin as part of $PATH.

Now that the root cause of the issue has been identified, what can be done about it? A common solution is to refer to the complete directory path to the command, starting from the root level. In the case of the jamf binary, one way to address this is to use /usr/local/bin/jamf in scripts and commands. That way, the OS doesn’t have to search for the command; it’s being told exactly where the command is.

However, a complication in the case of the Casper agent is that the location of the jamf and jamfAgent binaries depends on the operating system version, as JAMF made the decision to move the binaries only if the Mac in question is running 10.7.x or later.

Screen Shot 2015 09 23 at 8 23 06 PM

To help address the issue of the jamf binary being in one of two possible locations, I’ve added a task template for running commands using Casper’s jamf binary to ARD’s Send Unix function:


#!/bin/bash
CheckBinary (){
# Identify location of jamf binary.
jamf_binary=`/usr/bin/which jamf`
if [[ "$jamf_binary" == "" ]] && [[ -e "/usr/sbin/jamf" ]] && [[ ! -e "/usr/local/bin/jamf" ]]; then
jamf_binary="/usr/sbin/jamf"
elif [[ "$jamf_binary" == "" ]] && [[ ! -e "/usr/sbin/jamf" ]] && [[ -e "/usr/local/bin/jamf" ]]; then
jamf_binary="/usr/local/bin/jamf"
elif [[ "$jamf_binary" == "" ]] && [[ -e "/usr/sbin/jamf" ]] && [[ -e "/usr/local/bin/jamf" ]]; then
jamf_binary="/usr/local/bin/jamf"
fi
}
# Run the CheckBinary function to identify the location
# of the jamf binary for the jamf_binary variable.
CheckBinary
$jamf_binary command_goes_here

view raw

gistfile1.txt

hosted with ❤ by GitHub

The script above contains a function called CheckBinary, which populates a variable named $jamf_binary. The script calls the CheckBinary function before running commands which reference $jamf_binary, in place having to hardcode /usr/sbin/jamf or /usr/local/bin/jamf in the script.

Screen Shot 2015 09 23 at 6 07 15 PM

The CheckBinary function can also be added to scripts which are being triggered by LaunchD items, allowing the jamf binary to be located correctly by the OS before running commands using the jamf binary.

  1. Brian Lankford
    September 24, 2015 at 2:58 pm

    Rich is there a reason you wouldn’t add the /usr/sbin/jamf and /usr/local/bin/jamf to the paths of launchd or ARD?

  1. No trackbacks yet.

Leave a comment