10

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?

1
  • Launchd is very aggressive about staring things up in parallel. So I have observed cases, during startup, where this LaunchAgent fired later than I'd like. For example after my editor launched. I'm of the impression this is more common if I'm rebooting and I took the kind offer to restart my current applications after the reboot.
    – Ben Hyde
    Jun 4, 2020 at 17:11

1 Answer 1

7
  • 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.

12
  • 1
    This doesn't work. I launched Terminal; typed echo $FOO; saw foo; and exited Terminal. Then I unloaded environment.plist with your launchctl unload ... command above, changed the command in that file to launchctl setenv FOO bar, saved the file, and loaded the file with your launchctl load ... command. Finally I launched Terminal again, typed echo $FOO, and still saw the output foo. ...Ah, if I kill and restart the dock with killall Dock, then launch Terminal again, I finally see the updated value of FOO. Bloody hell, what a pain.
    – Sean
    Jul 7, 2017 at 18:18
  • @Sean Now tested in Sierra and it also works. No need to reboot, or kill an app (except Terminal which has to be relaunched). I'll try to add a work-around or a better solution...
    – klanomath
    Jul 7, 2017 at 18:36
  • I am getting Invalid or missing service identifier on running launchctl load .MacOSX/environment.plist Jan 27, 2020 at 2:37
  • @klanomath I still couldn't understand. Jan 27, 2020 at 16:28
  • I added lines as per your recommendations in a file bitbucket.org/snippets/kuldeepiitg/8nRq5G#file-Users/kuldeep/… but still not working. Can you please help with me the file? Jan 27, 2020 at 18:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .