是什么
环境变量(Environment Variables):操作系统提供给进程的键值对,进程可以在运行时读取。
特点:
- 由父进程传给子进程(继承);
- 进程可以读取,通常不应修改(修改只影响自身和后续子进程);
- 在 Unix/Linux/macOS 和 Windows 上都支持。
常见用途
- PATH:可执行文件搜索路径;
- HOME / USERPROFILE:用户主目录;
- LANG / LC_ALL:语言和区域设置(影响字符编码默认值的推断);
- JAVA_HOME / GOPATH 等:工具链路径;
- 应用程序的自定义配置。
为什么配置喜欢用它
一、与代码分离
十二要素应用(The Twelve-Factor App)方法论建议:把配置存储在环境中。
理由:
- 同一份代码可以在不同环境(开发、测试、生产)用不同配置运行;
- 不需要为不同环境打不同的包;
- 配置变更无需重新构建。
二、与部署环境天然契合
容器(Docker)和云原生平台(Kubernetes)都原生支持环境变量:
docker run -e DATABASE_URL=... myappenv:
- name: DATABASE_URL
valueFrom:
secretKeyRef: ...这比挂载配置文件更轻量、更容易在编排层面管理。
三、语言无关
所有编程语言都能读取环境变量——不需要统一的配置文件格式。
局限与风险
一、只适合小段文本
环境变量适合简单的键值对。复杂的嵌套配置(YAML/JSON 结构)不适合塞进环境变量。
二、不是"隐藏"的安全措施
一个常见误解:把密钥放在环境变量里就安全了。
实际上:
- 环境变量对进程可见(在 Linux 上可以通过
/proc/<pid>/environ读取,如果权限允许); - 子进程会继承环境变量——如果你的应用启动了子进程,密钥就传递过去了;
- 很多错误上报工具、日志框架会在崩溃时转储环境变量——导致密钥泄露;
- 在容器环境中,
docker inspect可以看到环境变量。
结论:环境变量是"方便",不是"安全"。
敏感配置的正确做法:使用专门的密钥管理服务(Vault、云厂商的 KMS/Secrets Manager、Kubernetes Secrets 配合加密),并在运行时注入。
三、类型都是字符串
环境变量的值都是字符串。需要自己做类型转换和校验。
四、修改需要重启
进程在启动时读取环境变量,运行中修改通常不生效(除非应用主动重新读取)。
五、优先级容易混乱
配置来源可能有:默认值、配置文件、环境变量、命令行参数、远程配置中心。
优先级必须明确并在文档中说明,否则排查"这个配置到底从哪来的"会很痛苦。
实践建议
- 明确优先级:通常
命令行参数 > 环境变量 > 配置文件 > 默认值; - 所有环境变量都要有校验——缺失时给出清晰的错误信息,而不是运行时崩溃;
- 提供
.env.example,列出所有必需和可选项(但不要提交包含真实密钥的.env); -
.env文件要加入.gitignore; - 不要在日志或错误信息中打印环境变量的值;
- 敏感信息用密钥管理服务,环境变量只作为传递通道。
一个实用模式
# .env.example(提交到仓库)
DATABASE_URL=postgres://user:password@localhost:5432/dbname
REDIS_URL=redis://localhost:6379
LOG_LEVEL=info开发者复制为 .env 并填入自己的值。.env 不提交。
说明:本文为配置管理的知识整理。