launchd.plist is not a file, but rather a type of file. It is an XML document that holds parameters which can be loaded into launchd. Here we’ll see how to use it to set environment variables.

Setting a Variable

For our first example, we’ll set the variable FOO to the value of BAR. Let’s look at an example and we’ll break it down:

/Library/LaunchDaemons/setenv.FOO.plist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  <plist version="1.0">
  <dict>
  <key>Label</key>
  <string>setenv.FOO</string>
  <key>ProgramArguments</key>
  <array>
    <string>/bin/launchctl</string>
    <string>setenv</string>
    <string>FOO</string>
    <string>BAR</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>ServiceIPC</key>
  <false/>
</dict>
</plist>

Breakdown

We will save in /Library/LaunchDaemons as that is where system-wide daemons provided by the administrator are set up. Other options include:

  • /Library/LaunchAgents - which is where per-user agents provided by the administrator are setup.
  • ~/Library/LaunchAgents - which is where per-user agents provided by the user are setup.

We’ll name the file setenv.FOO.plist, as the convention is to name the file Label.plist and the label here is setenv.FOO.

Label

The label can be anything, but needs to uniquely identify the job. We’ll use a convention of setenv.VARIABLE_NAME.

ProgramArguments

Next is the program arguments of the daemon. launchctl is used to set environment variables; it can be used in the terminal to set environment variables. This is what it would look like using the terminal:

Terminal - hostname:~ user$

1
/bin/launchctl setenv FOO BAR

Quit the terminal and reopen it

Terminal - hostname:~ user$

1
echo $FOO

Output

1
BAR

The issue however is if you reboot, you’ll lose the environment variable; fortunately we can put this command into ProgramArguments. ProgramArguments is just an array that lists the arguments for running the program.

RunAtLoad

This tells launchd whether or not to run the job once it is read.

ServiceIPC

This was required in Mac OS X 10.4, but is inferred in Mac OS X 10.5 and later.

Creating the File

We can run the following command in the terminal to create the file.

Terminal - hostname:~ user$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cat << EOF | sudo tee /Library/LaunchDaemons/setenv.FOO.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  <plist version="1.0">
  <dict>
  <key>Label</key>
  <string>setenv.FOO</string>
  <key>ProgramArguments</key>
  <array>
    <string>/bin/launchctl</string>
    <string>setenv</string>
    <string>FOO</string>
    <string>BAR</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>ServiceIPC</key>
  <false/>
</dict>
</plist>
EOF

Load the file

And if we don’t want to log out and back in, we can just run this command in the terminal to set the variable.

Terminal - hostname:~ user$

1
launchctl load -w /Library/LaunchDaemons/setenv.FOO.plist

Setting Another Variable

When setting variables with /etc/launchd.conf we couldn’t have spaces in the value, here we can. We’ll set the environment variable BAR to the value TEST SPACES:

/Library/LaunchDaemons/setenv.BAR.plist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  <plist version="1.0">
  <dict>
  <key>Label</key>
  <string>setenv.BAR</string>
  <key>ProgramArguments</key>
  <array>
    <string>/bin/launchctl</string>
    <string>setenv</string>
    <string>BAR</string>
    <string>TEST SPACES</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>ServiceIPC</key>
  <false/>
</dict>
</plist>

Create the File

Terminal - hostname:~ user$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cat << EOF | sudo tee /Library/LaunchDaemons/setenv.BAR.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  <plist version="1.0">
  <dict>
  <key>Label</key>
  <string>setenv.BAR</string>
  <key>ProgramArguments</key>
  <array>
    <string>/bin/launchctl</string>
    <string>setenv</string>
    <string>BAR</string>
    <string>TEST SPACES</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>ServiceIPC</key>
  <false/>
</dict>
</plist>
EOF

Load the File

Terminal - hostname:~ user$

1
launchctl load -w /Library/LaunchDaemons/setenv.BAR.plist

Issues

launchd does not have ordering for loading services, so setting the environment variables will be run concurrently with any programs automatically opening on login. So can either close and reopen those apps that need the variables; login, then logout, then login again; or do not use “Reopen windows when logging back”.

References

Parts of this series