Setting variables in environment.plist

environment-variableslaunchd

I've been trying to come to terms with how to set environment variables needed by launched applications in Sierra, but I'm puzzled.

Following various bits of advice found online, I created a file ~/Library/LaunchAgents/environment.plist. It looks like this:

<?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>my.startup</string>
  <key>ProgramArguments</key>
  <array>
    <string>sh</string>
    <string>-c</string>
    <string>
      launchctl setenv FOO foo
      launchctl setenv BAR bar
      <!-- ... -->
      launchctl setenv PATH /usr/local/opt/scala210/bin:/usr/local/bin:$PATH
    </string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

From my experimenting, it appears that nothing less than a system reboot will make changes to this file take effect. I did find mentions of this command that will supposedly do the trick:

$ launchctl load ~/Library/LaunchAgents/environment.plist

…but when I run it I get this response:

[my home dir]/Library/LaunchAgents/environment.plist: service already loaded

In the documentation for launchctl I see mention of a -F flag that seems relevant:

Force the loading or unloading of the plist. Ignore the Disabled key.

However, it makes no difference if I include this switch; I get the same output and the file is ignored.

So anyway, rebooting does make the changes take effect (maybe logging out and back in also would? I didn't check), but with one exception: the PATH variable. That variable just stayed the same no matter how I changed it, and across reboots. Eventually I stumbled across a Stack Exchange answer that offhandedly warned that changing PATH in this way would be ignored until the Dock was restarted with the killall Dock command. So I did that, and rebooted, and finally I had my PATH set correctly.

So, anyway, I suppose my main question would be: Is there any more hassle-free way to update environment variables than the way I outline above? And a subsidiary question might be: Does the special handling of PATH make any sense at all?

Best Answer

  • Unload the launch agent:

    launchctl unload ~/Library/LaunchAgents/environment.plist
    
  • Modify the plist/env settings
  • Load the launch agent again:

    launchctl load ~/Library/LaunchAgents/environment.plist
    

You have to quit and relaunch Terminal to get the new value of the variable in the shell.

With the example of Kuldeep Yadav's comment the usr.aws.plist in ~/Library/LaunchAgent/ would look like this then:

<?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>usr.aws</string>
        <key>ProgramArguments</key>
        <array>
                <string>/bin/launchctl</string>
                <string>setenv</string>
                <string>AWS_SECRET_ACCESS_KEY</string>
                <string>loremipsum</string>
                <string>/bin/launchctl</string>
                <string>setenv</string>
                <string>AWS_ACCESS_KEY_ID</string>
                <string>loremipsum2</string>
                <string>/bin/launchctl</string>
                <string>setenv</string>
                <string>AWS_ACCESS_KEY</string>
                <string>loremipsum3</string>
                <string>/bin/launchctl</string>
                <string>setenv</string>
                <string>AWS_SECRET_KEY</string>
                <string>loremipsum4</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
</dict>
</plist>

This is only tested (& working) with bash & zsh.