dotenv 用法速查表 - .env 环境变量配置与多环境加载顺序
几乎每个 Node/Python/前端项目都要写 .env,但最容易栽的坑是等号两侧留空格、值里的 # 被当注释、密钥误提交进仓库。这份速查覆盖 5 组:变量定义、在 Shell/Node/Python 里如何读取、dotenv 的加载写法、多环境文件(.env/.env.local/.env.production)的组织,以及一组安全陷阱提醒。写完对照检查格式,部署前确认密钥没有被提交。读完后你能规范组织环境变量,并规避最常见的数据泄漏问题。
典型使用场景
面向需要把配置与密钥从代码里分离出来的开发者:本地开发用 .env,生产用真实环境变量,团队间用 .env.example 对齐字段名。本表覆盖变量定义与读取、各语言/Shell 的访问方式、dotenv 加载、多环境文件约定与四类安全陷阱。核心判断标准只有一条——真实密钥永远不进版本库。
变量定义 Definition 6
KEY=valueKEY="value with space"KEY='literal $NOT_EXPANDED'KEY=${OTHER}_suffix# commentexport KEY=value引用与读取 Reading 5
echo $KEYecho %KEY%$env:KEYprocess.env.KEYos.getenv("KEY")dotenv 用法 4
require('dotenv').config()import 'dotenv/config'dotenv.config({ path: '.env.local' })python-dotenv load_dotenv()多环境文件 Multi-env 5
.env.env.local.env.development.env.production.env.example安全陷阱 Security FAQ 4
不要提交密钥区分大小写类型转换换行需转义参数矩阵
| 参数 | 作用 | 示例 |
|---|---|---|
KEY=value | 定义变量,等号两侧不可有空格 | KEY=value |
KEY="a b" | 含空格或特殊字符需加引号 | KEY="value with space" |
KEY='$RAW' | 单引号内不做变量展开 | KEY='literal $NOT_EXPANDED' |
export KEY=value | 设置并导出为环境变量,供子进程读取 | export DATABASE_URL=postgres://... |
$KEY / %KEY% / $env:KEY | 三平台读取语法:Shell / cmd / PowerShell | echo $KEY |
dotenv.config() | Node 把 .env 载入 process.env | require('dotenv').config() |
import 'dotenv/config' | ESM 写法加载 .env | import 'dotenv/config' |
.env.local | 本地覆盖,优先级高于 .env | dotenv.config({ path: '.env.local' }) |
.env.<mode> | 按环境分文件:development / production | .env.production |
.env.example | 示例模板,可提交,不含真实密钥 | cp .env .env.example |
os.getenv("KEY") | Python 读取;未设置时返回 None | os.getenv("DATABASE_URL") |
process.env.KEY | Node 读取;未设置时为 undefined | process.env.PORT |
易错点与避坑指南
现象变量明明在文件里写了,读取却是空值。
原因等号两侧加了空格(KEY = value 被解析为执行命令 KEY),或用了未导出的普通变量。
处置写成 KEY=value 不带空格,并加 export 让子进程可见。
现象密钥提交进了 Git,历史里还能查到,即使现在删除文件也不安全。
原因.env 未加入 .gitignore,或已追踪后补的忽略规则不生效。
处置立即轮换密钥(改 ignore 无法撤回已泄露内容);git rm --cached .env 移出索引,并补 .gitignore。
现象跨平台脚本在 Windows 上运行失败,Linux 正常。
原因Shell 用 $KEY 读取,而 cmd 需要 %KEY%。
处置跨平台脚本避免直接读环境变量,或分别处理两套语法。
现象读出来的是字符串 "8080" 而不是数字,直接比较大小报类型错误。
原因环境变量的值一律是字符串,没有类型。
处置显式转换:Number(process.env.PORT) 或 parseInt(..., 10)。
现象多行值(如私钥)写入 .env 后只能读到第一行。
原因换行符未转义,解析在第一行就截断。
处置用引号包裹并把真实换行写成 \n,或改用 base64 / 密钥管理服务。
现象本地改了 .env.local 但应用读到的还是旧值。
原因dotenv 默认不覆盖已存在的 process.env 值。
处置用 dotenv.config({ override: true }),或确认加载顺序符合预期。
排障路径
1确认变量确实存在于当前 shell
echo $KEY没输出说明没 export 或没加载 .env;用 set | grep KEY 也可。
2从文件临时加载到当前会话
set -a && source .env && set +aset -a 让 source 定义的变量自动导出,+a 恢复;仅当前 shell 有效。
3确认 Node 侧是否真的读到了
node -e "console.log(process.env.KEY)"绕过应用直接问运行时,能区分是加载失败还是代码没读对字段。
4生成不含密钥的提交模板
sed -E "s/=.*/=/" .env > .env.example保留 KEY 名清空值;确认 .env 已在 .gitignore 中。
5排查密钥是否已泄露进版本库
git log -S "SECRET_VALUE" --oneline能命中就说明历史里存在,必须轮换密钥,改 .gitignore 只防未来。
命令示例
定义变量并导出给子进程
export DATABASE_URL=postgres://localhost:5432/app等号两侧不能有空格;只 set 不 export 的话子进程读不到这个值。
从指定路径加载 .env 文件
dotenv.config({ path: '.env.local' })不传 path 时默认读项目根目录的 .env;传了就只读指定文件,不会自动合并。
三个平台各自的读取语法
echo $KEY
# Linux/macOS
echo %KEY%
# Windows cmd
$env:KEY
# PowerShell同一份配置要在不同平台跑时,读取语法本身就不同,脚本不能假定只有一种。
Python 中加载并读取变量
from dotenv import load_dotenv
load_dotenv()
os.getenv("API_HOST")变量不存在时返回 None,判断配置是否加载成功要先处理这个 None 分支。
常见坑与注意事项
- 把 .env 加入 .gitignore,真实密钥永远不进版本库,提交 .env.example 作为字段模板。
- 等号两侧不要留空格,KEY = value 不会完成赋值,变量名保持全大写下划线风格最不易出错。
- 所有值都是字符串,数字和布尔必须自行转换,"false" 在 JavaScript 里是 truthy,直接判断会得到相反结果。
- 变量名区分大小写,KEY 与 key 在 Linux/macOS 上是两个变量,排查空值时先确认大小写完全一致。
- 多行内容(私钥、证书)必须用引号整体包裹或写成显式换行转义,否则只能读到第一行。
提示
- 等号两侧不要留空格(KEY=value 正确,KEY = value 错误)。
- 把 .env 加入 .gitignore,密钥改用 .env.example 模板提交。
- 所有值都是字符串,数字需用 Number()/parseInt() 转换。
- 多行值用引号包裹或 \n 表示换行。
常见问题
变量明明写在 .env 里,读出来却是空的?
按顺序排三种最常见原因:一是等号两侧留了空格,KEY = value 会被当成一个整体而不是赋值;二是只定义了但没有 export,子进程读不到;三是变量名大小写不一致,KEY 和 key 是两个完全不同的变量,Linux 上是区分大小写的。
为什么端口号读出来是字符串,比较大小时报类型错误?
.env 里的值一律按字符串处理,不存在类型标注,PORT=8080 拿到的就是 "8080" 这段文本。直接拿它和数字比较或做算术就会在运行时报错,必须自己转换:Node 里用 Number(process.env.PORT),Python 里用 int(os.getenv("PORT"))。布尔值同理,"false" 这个字符串在 JavaScript 里是 truthy。
私钥那种多行值写进 .env 后只读到第一行?
.env 按行解析,裸换行会把一行内容截断成两行,第二行会被当成新的变量或直接忽略。多行值要用引号整体包裹,或者用显式的换行转义序列表示,保证整个值仍处在同一行里。
.env 和 .env.local 同时存在时哪个生效?
.env.local 优先级更高,它扮演本地覆盖的角色,适合放只有你本机需要的值,比如指向本地数据库的连接串。基础配置放 .env,需要分环境的用 .env.development 和 .env.production,给团队对齐字段名的是不含真实密钥的 .env.example。
Node 和 Python 分别怎么从 .env 里取值?
Node 先 require('dotenv').config() 把文件载入 process.env,之后用 process.env.KEY 读;ESM 环境改用 import 'dotenv/config' 这一行侧效应写法。Python 用 python-dotenv 的 load_dotenv() 载入,读取走 os.getenv("KEY"),变量不存在时返回 None。两者都需要在读取之前完成加载。
由 巧匠 维护
公开更新于 2026年8月2日,内容持续校对官方文档。