Setting Environment Variables with Spaces in OS X 10.8 (Mountain Lion)…

For setting the PATH and other environment variables, see here, since it will explain the more appropriate place for them.

Unfortunately, the methods listed in the linked article above don’t work for environment variables with spaces, e.g. MAVEN_OPTS="-Djavax.net.ssl.trustStore=keystore -Djavax.net.ssl.trustStorePassword=password".

To set these, the variables have to be configured as launch daemon arguments.  Here is an example of a file I have:

$ cat /Library/LaunchDaemons/mavenopts.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
	"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>MAVEN_OPTS</string>
	<key>ProgramArguments</key>
	<array>
		<string>launchctl</string>
		<string>setenv</string>
		<string>MAVEN_OPTS</string>
		<string>-Djavax.net.ssl.trustStore=keystore -Djavax.net.ssl.trustStorePassword=password</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>KeepAlive</key>
	<true/>
	<key>LaunchOnlyOnce</key>
	<true/>
</dict>
</plist>

This file can also go in /System/Library/LaunchDaemons instead of /Library/LaunchDaemons, but this is more a matter of philosophy; either location will work.

For more details, here is the Apple documentation: http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html#//apple_ref/doc/uid/10000172i-SW7-BCIEDDBJ

Setting Environment Variables in OS X 10.8 (Mountain Lion)

I was recently trying to install SQL Developer from Oracle and wanted the LDAP function to work, which would require the application to be aware of my ORACLE_HOME, but I could not get the application to become aware of the environment variable when I launched it from the Launcher or the Dock.

Shell Variables

For environment variables that are only going to be used in the terminal, setting them in the .bash_profile is sufficient.  I’m not totally sure how the OS X shell works, but it seems to only read the .bash_profile (doesn’t seem to read .bashrc etc.), and it reads it every time a new terminal is open.

Example

PATH=${PATH}:${HOME}/scripts; export PATH

The problem with using the .bash_profile is that applications in the GUI are not aware of the environment variables (e.g. in my case, launching SQL Developer from the command line activated the features I wanted, but clicking the icon from the Launcher did not activate the features).

Environment Variables

There used to be a mechanism for setting environment variables prior to Mountain Lion by setting them in the ${HOME}/.MacOSX/environment.plist file, but this doesn’t seem to work in Mountain Lion.  They have to be set via launchd in /etc/launchd.conf. Unfortunately, this can’t be done at a user level at the moment (${HOME}/.launchd.conf not currently supported), so it must be done at a global level (affects all users).

Example

setenv ORACLE_HOME /opt/oracle

Path Variables

There is one more way to set the PATH globally for all users. It can be done by adding directories that should be in the path into files under the /etc/paths.d directory.

Example

Here is an example of a file that might be called /etc/paths.d/oracle.

/opt/oracle/bin

Custom Bash Completion

Bash completion (pressing [TAB][TAB] after a certain command to get the possible options) is an awesome feature, as I’m sure many would agree.  Here’s how to set up a custom completion.

The Completion Function

Here is an example of a basic bash completion function.

# the bash completion function to execute
bash_completion_function() {
  # clear the COMPREPLY variable
  COMPREPLY=()

  # get the current argument on the command line
  CURRENT_ARG="${COMP_WORDS[COMP_CWORD]}"

  # the list of possible options
  OPTIONS="aaa a23 bbb b34 ccc c45 ddd d56 eee e67 fff f78"

  COMPREPLY=($(compgen -W "${OPTIONS}" -- "${CURRENT_ARG}"))
  return 0
}
  • COMPREPLY: this is the variable that will eventually hold the completion results (what is output after pressing [TAB][TAB])
  • COMP_WORDS: an array of words on the command line
  • COMP_CWORD: an index for the COMP_WORDS array; something like COMP_WORDS[COMP_CWORD - 1] can also be used to perform some logic based on words in different positions on the command line
  • compgen: this is where the magic happens; the argument to the -W flag holds the possible arguments, and the possibilities are chosen based on the CURRENT_ARG; to test the completion function, this can be run on the command line (e.g. compgen -W "aaa a32 bbb b34" a should output aaa a32)

Apply The Function To the Command

After the function is set up, it must be sourced. This can be done manually for testing or example purposes (e.g. . ./bash_completion_function) or can be put somewhere like ~/.bashrc so it is always available.

After the function is sourced, it must be linked to the command. This is done with the complete command. The command below is linking the bash_completion_function function to the test.sh script. Again, this can be done manually for testing or example purposes or can be put somewhere like ~/.bashrc so it is always available.

complete -F bash_completion_function test.sh

With this particular set up, executing ./test.sh a [TAB][TAB] should output aaa a32 as possible arguments.