How to Set System Environment Variables in macOS

How to Set System Environment Variables in macOS

Intro

Info

macOS 使用  launchd  进程来管理守护进程和代理,而你还可以用它来运行 shell 脚本。你不与  launchd  直接交互,而是使用  launchctl  命令来载入或卸载  launchd  守护进程和代理。

在系统启动期间,launchd  是内核在设置电脑时首先运行的进程。若你想要 shell 脚本作为守护进程运行,应由  launchd  来启动它。其他用于启动守护进程和代理的机制可能会被 Apple 酌情移除。

你可以通过在以下文件夹中查看配置文件来了解由  launchd  管理的各种守护进程和代理:

文件夹用途
/System/Library/LaunchDaemonsApple 提供的系统守护进程
/System/Library/LaunchAgentsApple 提供的基于每个用户且所有用户适用的代理
/Library/LaunchDaemons第三方系统守护进程
/Library/LaunchAgents基于每个用户且所有用户适用的第三方代理
~/Library/LaunchAgents仅适用于登录用户的第三方代理

许多教程在设置 macOS 环境变量时,建议在 ~/.bash_profile~/.zshrc 等位置设置环境变量。这只对 bash/zsh 会话生效。例如在 /etc/bashrc 写入 export NAME="GnixAij",但该变量在 zsh 会话中是不可见的,第三方 shell 基本也不会读取

Example Case

这里以设置 XDG_* 系列变量为例进行演示。关于 XDG 规范的介绍,可查阅 XDG Base Directory - ArchWiki

步骤 1:创建环境设置脚本

首先,在任意位置创建一个 Shell 脚本,例如 ~/.local/bin/sys_envs

1
touch ~/.local/bin/sys_envs

脚本内容如下,它使用 launchctlsetenv 子命令来设置环境变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#! /bin/bash

# 封装一个函数来设置环境变量,为了可扩展性
env() {
    os_name=$(uname -s)

    case "$os_name" in
        Darwin)
            # For macOS, use launchctl to set environment variables
            launchctl setenv "$1" "$2"
            ;;
        Linux)
            export "$1=$2"
            ;;
        *)
            echo "Unsupported OS: $os_name"
            exit 1
            ;;
    esac
}

env XDG_BIN_HOME "$HOME/.local/bin"
env XDG_CACHE_HOME "$HOME/Library/Caches"
env XDG_CONFIG_HOME "$HOME/.config"
env XDG_CONFIG_DIRS "/etc/xdg"
env XDG_DATA_HOME "$HOME/.local/share"
env XDG_DATA_DIRS "/usr/local/share/:/usr/share/"
env XDG_RUNTIME_DIR "$TMPDIR/runtime-$UID"
env XDG_STATE_HOME "$HOME/.local/state"

# https://wiki.archlinux.org/title/XDG_user_directories
env XDG_DESKTOP_DIR "$HOME/Desktop"
env XDG_DOCUMENTS_DIR "$HOME/Documents"
env XDG_DOWNLOAD_DIR "$HOME/Downloads"
env XDG_MUSIC_DIR "$HOME/Music"
env XDG_PICTURES_DIR "$HOME/Pictures"
env XDG_PUBLICSHARE_DIR "$HOME/Public"
env XDG_VIDEOS_DIR "$HOME/Movies"

# Make sure the XDG directories exist
mkdir -p "$XDG_CACHE_HOME" "$XDG_CONFIG_HOME" "$XDG_DATA_HOME" "$XDG_RUNTIME_DIR" "$XDG_STATE_HOME"

# Define paths for common programs with partial XDG support
# https://wiki.archlinux.org/title/XDG_Base_Directory#Partial
env CARGO_HOME "$XDG_DATA_HOME/cargo"
env FFMPEG_DATADIR "$XDG_CONFIG_HOME/ffmpeg"
env LESSHISTFILE "$XDG_STATE_HOME/less_history"
env MYPY_CACHE_DIR "$XDG_CACHE_HOME/mypy"
env NODE_REPL_HISTORY "$XDG_STATE_HOME/node_repl_history"
env PYENV_ROOT "$XDG_DATA_HOME/pyenv"
env PYTHONPYCACHEPREFIX "$XDG_CACHE_HOME/python"
env PYTHONUSERBASE "$XDG_DATA_HOME/python"
env PYTHON_HISTORY "$XDG_STATE_HOME/python_history"
env RIPGREP_CONFIG_PATH "$XDG_CONFIG_HOME/ripgrep/config"
env RUSTUP_HOME "$XDG_DATA_HOME/rustup"
env WORKON_HOME "$XDG_DATA_HOME/virtualenvs"
# docker
env DOCKER_CONFIG "$XDG_CONFIG_HOME/docker"
env MACHINE_STORAGE_PATH "$XDG_DATA_HOME/docker_machine"
# npm
env NPM_CONFIG_USERCONFIG "$XDG_CONFIG_HOME/npm/npmrc"
# zsh
env ZDOTDIR "$XDG_CONFIG_HOME/zsh"
env ZSH_PROFILE "$XDG_CONFIG_HOME/zsh/profile"
# yazi
env YAZI_CONFIG_HOME "$XDG_CONFIG_HOME/yazi"

Step 2. Load the script at Login/StartUp

  1. 如果 ~/Library/LaunchAgents 目录不存在,则创建它:mkdir -p ~/Library/LaunchAgents
  2. 创建并编辑 ~/Library/LaunchAgents/env.plist 文件,写入以下内容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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>com.user.environment-vars</string>
    <key>ProgramArguments</key>
    <array>
      <!-- 这里需要替换成你自己的脚本路径 -->
      <string>/Users/gjx/.local/bin/sys_envs</string>
    </array>
    <key>RunAtLoad</key>
    <true />
    <key>KeepAlive</key>
    <false />
  </dict>
</plist>

完成以上步骤后,下次登录时,launchd 就会自动执行该脚本,从而设置好所有环境变量。

Limitations

Apple 不保证 launchd 加载服务的确切顺序,也就是可能先重启了Terminal,而后env.plist 才被加载,这会导致 Terminal 无法获取到新的环境变量。

解决方法如下:

  • 重新登录:当前用户先Log Out(快捷键 ⌘ + ⇧ + Q),再重新Login
  • 手动重启应用:字面意思
  • 禁用会话恢复:在系统设置中,关闭“Reopen windows when logging back”的功能。

另外就是无法通过 launchctl 修改 PATH 环境变量,想在 System-Wide 层级设置 PATH,需要在 /etc/paths 中修改。

Ref

How to Set System Environment Variables in macOS

https://vluv.space/Mac环境变量/

作者

GnixAij

发布于

2025-07-27

更新于

2025-07-27

许可协议

评论