验证配置文件和环境变量,以防止运行时错误和缺失设置。
何时使用
- 处理环境变量或配置文件
- 部署或配置问题
- 用户提及“.env”,“config”,“环境变量”或“设置”
指令
1. 查找配置文件
搜索:
.env,.env.example,.env.localconfig/,config.js,config.jsonsettings.py,application.ymlappsettings.json,.env.production
2. 检测缺失变量
比较 .env.example vs .env:
# 变量在示例中但不在 .env 中
comm -23 <(grep -o '^[A-Z_]*' .env.example | sort) <(grep -o '^[A-Z_]*' .env | sort)
常见必需变量:
DATABASE_URL
API_KEY
SECRET_KEY
NODE_ENV
PORT
3. 验证变量格式
检查常见问题:
// 带有空格的值缺少引号
DATABASE_URL=postgres://localhost/db name // 错误
DATABASE_URL="postgres://localhost/db name" // 正确
// 缺少协议
API_URL=example.com // 错误
API_URL=https://example.com // 正确
// 布尔值作为字符串
DEBUG=true // 可能被解释为字符串
DEBUG=1 // 更明确
4. 在运行时验证必需变量
Node.js 示例:
const requiredEnvVars = [
'DATABASE_URL',
'API_KEY',
'JWT_SECRET'
];
const missing = requiredEnvVars.filter(v => !process.env[v]);
if (missing.length > 0) {
throw new Error(`Missing required env vars: ${missing.join(', ')}`);
}
Python 示例:
import os
REQUIRED_ENV_VARS = [
'DATABASE_URL',
'SECRET_KEY',
'ALLOWED_HOSTS'
]
missing = [var for var in REQUIRED_ENV_VARS if not os.getenv(var)]
if missing:
raise EnvironmentError(f"Missing env vars: {', '.join(missing)}")
5. 类型验证
验证类型:
const config = {
port: parseInt(process.env.PORT || '3000', 10),
debug: process.env.DEBUG === 'true',
apiUrl: new URL(process.env.API_URL), // 如果无效则抛出
maxConnections: Number(process.env.MAX_CONNECTIONS),
};
// 验证
if (isNaN(config.port) || config.port < 1 || config.port > 65535) {
throw new Error('PORT must be a valid port number');
}
6. 生成 .env.example
从实际的 .env 创建模板:
# 移除值,保留键
sed 's/=.*/=/' .env > .env.example
或带有占位符:
DATABASE_URL=postgres://user:password@localhost:5432/dbname
API_KEY=your_api_key_here
SECRET_KEY=generate_random_secret
PORT=3000
NODE_ENV=development
7. 配置模式
定义模式(使用 Joi 示例):
const Joi = require('joi');
const envSchema = Joi.object({
NODE_ENV: Joi.string()
.valid('development', 'production', 'test')
.required(),
PORT: Joi.number()
.port()
.default(3000),
DATABASE_URL: Joi.string()
.uri()
.required(),
API_KEY: Joi.string()
.min(32)
.required(),
DEBUG: Joi.boolean()
.default(false),
}).unknown();
const { error, value } = envSchema.validate(process.env);
if (error) {
throw new Error(`Config validation error: ${error.message}`);
}
module.exports = value;
8. 安全检查
不要提交秘密:
# 检查 .env 是否被 gitignore
if ! grep -q "^\.env$" .gitignore; then
echo "Warning: .env not in .gitignore"
fi
# 检查代码中硬编码的秘密
grep -r "api_key.*=.*['\"]" --exclude-dir=node_modules
常见安全问题:
- 硬编码密码/密钥
- 生产中的默认秘密
- 暴露的敏感配置
- 未加密的秘密
9. 环境特定配置
按环境组织:
.env.development
.env.staging
.env.production
.env.test
适当加载:
require('dotenv').config({
path: `.env.${process.env.NODE_ENV || 'development'}`
});
10. 文档化所有变量
创建 CONFIG.md:
# 配置
## 环境变量
### 必需
- `DATABASE_URL`: PostgreSQL 连接字符串
- 格式:`postgres://user:pass@host:port/db`
- 示例:`postgres://app:secret@localhost:5432/myapp`
- `API_KEY`: 第三方 API 密钥
- 从获取:https://dashboard.example.com
- 必需范围:读,写
### 可选
- `PORT`: 服务器端口(默认:3000)
- `DEBUG`: 启用调试日志(默认:false)
- `MAX_CONNECTIONS`: 数据库池大小(默认:10)
## 设置
1. 复制 `.env.example` 到 `.env`
2. 填写所有必需值
3. 运行 `npm run validate-config` 进行验证
11. 验证脚本
创建 scripts/validate-config.js:
const fs = require('fs');
function validateConfig() {
const required = ['DATABASE_URL', 'API_KEY'];
const missing = required.filter(v => !process.env[v]);
if (missing.length > 0) {
console.error(`❌ 缺失:${missing.join(', ')}`);
process.exit(1);
}
console.log('✓ 所有必需的配置变量都存在');
}
validateConfig();
12. 最佳实践
- 永不提交 .env: 始终 gitignore
- 维护 .env.example: 保持更新
- 启动时验证: 如果配置错误则快速失败
- 使用强默认值: 合理的回退
- 文档化一切: 解释每个变量
- 轮换秘密: 定期更新密钥
- 使用秘密管理器: Vault, AWS Secrets Manager 用于生产
- 类型检查: 验证类型,而不仅仅是存在
支持文件
templates/config-validator.jstemplates/.env.examplescripts/generate-env-example.sh