在 macOS Zsh 中管理开发环境变量需分三层:全局变量写入 ~/.zshrc 并 export;GUI 应用需通过 launchctl 注入;项目级变量推荐用 direnv 自动切换。
在 macos 的 zsh 环境中区分和管理开发环境变量,核心是让变量既可靠生效,又能按需切换、不冲突、不污染全局。不是简单写个 export environment=dev 就完事,而是要结合加载时机、作用范围、gui 兼容性和脚本健壮性来设计。
明确环境变量用途,再决定存放位置
先问自己:这个变量是用来做什么的?不同用途对应不同配置策略:
-
控制命令行工具行为(如
npm run dev自动设NODE_ENV、go build加调试标志)→ 写入~/.zshrc,用export导出 -
影响 GUI 应用内运行的脚本(如 VS Code 中终端/调试器启动的 Node 进程)→ 单靠
.zshrc不够,需用launchctl注入到系统级会话 -
项目级临时覆盖(比如某个 Git 仓库里必须用
production)→ 不写死在全局配置里,改用.env文件 + 工具(如direnv)自动加载
在 ~/.zshrc 中设置并安全导出
这是最常用也最推荐的起点。打开终端执行:
nano ~/.zshrc
在文件末尾添加类似内容(注意顺序和引号):
export ENVIRONMENT="development"export NODE_ENV="${ENVIRONMENT}"export API_BASE_URL="${API_BASE_URL:-https://api.dev.example.com}"
保存后立即生效:source ~/.zshrc。这样所有新开终端、以及从中启动的子进程(python script.py、node server.js)都能读取这些变量。
⚠️ 关键细节:
– 必须用 export,否则变量只在当前 shell 有效,子进程看不到;
– 使用 ${VAR:-default} 语法提供默认值,避免脚本因变量为空崩溃;
– 避免在 .zshrc 里写条件判断切换环境(如 if [ "$HOST" = "prod-server" ]; then ...),容易导致新终端行为不一致。
让图形界面应用也能识别环境
VS Code、IntelliJ、TablePlus 等 GUI 软件启动时不读 .zshrc,所以它们内部终端或调试器可能拿不到你的 ENVIRONMENT。解决方法是通过 macOS 的 launchd 注入:
创建文件:~/Library/LaunchAgents/com.user.env.plist
内容示例(设为 development):
<?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.env</string><key>ProgramArguments</key><array><string>sh</string><string>-c</string><string>launchctl setenv ENVIRONMENT development</string></array><key>RunAtLoad</key><true/></dict></plist>
然后运行:launchctl load ~/Library/LaunchAgents/com.user.env.plist
重启 VS Code 或其他 GUI 应用即可生效。如需切 production,改 plist 文件内容并 reload 即可。
进阶:按项目自动切换环境(推荐 direnv)
手动改 .zshrc 切换环境太麻烦,也容易误操作。更合理的方式是“进入目录自动生效”:
- 安装
direnv:brew install direnv && echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc && source ~/.zshrc - 在项目根目录新建
.envrc文件:export ENVIRONMENT=staging - 首次进入目录时运行
direnv allow授权
之后每次 cd 进该项目,ENVIRONMENT 自动设为 staging;离开后自动还原。比全局变量更安全、更符合实际开发流程。


















