怎么用脚本获取环境变量值?详解 Shell、Python、PowerShell 与 Node.js 实战
目录导读
- 环境变量基础:什么是环境变量?为什么脚本需要读取它?
- Shell 脚本获取环境变量(Bash/Zsh):
$VAR与${VAR:-default}用法 - Python 脚本获取环境变量:
os.environ与python-dotenv库 - Node.js 脚本获取环境变量:
process.env与.env文件加载 - PowerShell 脚本获取环境变量:
$env:VAR与[Environment]::GetEnvironmentVariable - 常见问题与问答:脚本获取不到变量?权限问题?作用域问题?
环境变量基础
环境变量是操作系统级别存储的键值对,用于配置程序运行时的行为。PATH 指定可执行文件搜索路径,HOME 指定用户家目录,DB_HOST 指定数据库地址,脚本获取环境变量可以避免硬编码敏感信息(如密码、API密钥),支持不同环境(开发/测试/生产)灵活切换。

问答环节
Q:为什么要用脚本获取环境变量,而不是直接写在代码里?
A:直接写入代码会导致:① 密码泄露风险(代码提交到 Git 仓库);② 环境切换困难(每换环境需改代码);③ 不符合 12-Factor App 规范,用环境变量实现“配置与代码分离”。
Shell 脚本获取环境变量
Shell(Bash/Zsh)是最直接获取环境变量的方式。
1 基本用法:$变量名
#!/bin/bash echo "当前用户是:$USER" echo "家目录:$HOME"
2 带默认值:${变量名:-默认值}
若变量未设置,使用默认值;若已设置,使用原值。
#!/bin/bash
DB_HOST="${DB_HOST:-localhost}"
DB_PORT="${DB_PORT:-3306}"
echo "连接数据库:$DB_HOST:$DB_PORT"
3 判断变量是否存在
#!/bin/bash
if [ -z "$API_KEY" ]; then
echo "错误:API_KEY 环境变量未设置!"
exit 1
fi
问答环节
Q:用 $VAR 和 ${VAR} 有区别吗?
A:在多数情况下等效,但 ${VAR} 更安全,尤其在字符串拼接或带默认值时(如 echo "${VAR}_suffix" 避免歧义)。
Python 脚本获取环境变量
Python 通过 os.environ 字典读取所有环境变量。
1 基础读取
import os
user = os.environ.get('USER', 'default_user')
db_url = os.environ.get('DATABASE_URL')
if db_url is None:
raise EnvironmentError("DATABASE_URL 未设置")
2 使用 python-dotenv 加载 .env 文件
# .env 文件内容
DB_HOST=myhost.com
DB_PASS=secret123
from dotenv import load_dotenv
load_dotenv() # 加载 .env 到环境变量
import os
host = os.getenv('DB_HOST')
password = os.getenv('DB_PASS')
问答环节
Q:os.environ 和 os.getenv 有什么区别?
A:os.environ 是字典,访问时若 key 不存在会抛 KeyError;os.getenv(key, default) 更安全,可提供默认值,推荐使用 os.getenv。
Node.js 脚本获取环境变量
Node.js 通过 process.env 对象访问。
1 基础用法
const user = process.env.USER || 'guest';
const dbPort = process.env.DB_PORT || 5432;
console.log(`用户: ${user}, 端口: ${dbPort}`);
2 使用 dotenv 模块加载 .env 文件
# .env 文件
APP_SECRET=my-secret-key
NODE_ENV=development
require('dotenv').config(); // 加载 .env
const secret = process.env.APP_SECRET;
if (!secret) {
console.error('缺少 APP_SECRET 环境变量');
process.exit(1);
}
问答环节
Q:process.env 中的变量可以修改吗?
A:可以临时修改当前进程的变量,process.env.MY_VAR = 'new',但不会影响父进程或其他进程,修改后仅对当前 Node.js 进程生效。
PowerShell 脚本获取环境变量
Windows 环境下,PowerShell 提供多种读取方式。
1 使用 $env: 前缀
$user = $env:USERNAME $path = $env:PATH Write-Host "用户名: $user"
2 使用 [Environment]::GetEnvironmentVariable (支持用户/系统级别)
# 获取系统级别变量
$javaHome = [Environment]::GetEnvironmentVariable('JAVA_HOME', 'Machine')
# 获取用户级别变量
$myVar = [Environment]::GetEnvironmentVariable('MY_VAR', 'User')
# 获取当前进程变量(默认)
$tempVar = [Environment]::GetEnvironmentVariable('TEMP')
3 带默认值
$logLevel = if ($env:LOG_LEVEL) { $env:LOG_LEVEL } else { 'INFO' }
# 或者使用 PowerShell 7+ 的 ?? 运算符
$logLevel = $env:LOG_LEVEL ?? 'INFO'
问答环节
Q:PowerShell 中 $env:VAR 和 [Environment]::GetEnvironmentVariable 有何区别?
A:$env:VAR 读取当前进程环境变量(可能被脚本修改过),[Environment]::GetEnvironmentVariable 可指定读取系统或用户级别的原始值(且可指定作用域)。
常见问题与问答
Q1:脚本获取环境变量时,返回空值或 None?
A:可能原因:① 变量拼写不一致(大小写敏感,Linux 下需区分),② 变量未在当前会话 export(使用 export VAR=value 而非 VAR=value),③ 脚本运行在子 shell 中,子 shell 默认继承父 shell 环境(除非用 unset 或子 shell 内修改)。
Q2:如何将 .env 文件中的变量加载为系统环境变量?
A:不建议全局加载,推荐在脚本内使用第三方库(如 python-dotenv、dotenv)加载,仅对当前进程生效,Linux 可用 export $(grep -v '^#' .env | xargs) 临时加载。
Q3:跨平台脚本如何统一获取环境变量?
A:推荐用 Python 或 Node.js 编写跨平台脚本,Shell 脚本在 Windows(Git Bash)下兼容性较差;PowerShell 只在 Windows 原生可用,Python 的 os.environ 和 Node.js 的 process.env 在三个平台表现一致。
Q4:环境变量中密码包含特殊字符(如 、&)怎么办?
A:在 Shell 中,直接设为 export PASS='abc!def&'(用单引号),在 .env 文件中,不需转义(.env 解析库会自动处理),在 Python 中直接读取,无需额外处理。
Q5:脚本获取环境变量时,安全性需要注意什么?
A:① 不要将敏感变量硬编码到脚本或 .env 文件(特别是 .env 应加入 .gitignore),② 生产环境使用密钥管理服务(如 AWS Secrets Manager、HashiCorp Vault),③ 避免在日志、错误输出中打印敏感变量。
通过 Shell、Python、Node.js 和 PowerShell 获取环境变量,是构建可靠、可配置脚本的关键技能,核心原则:配置与代码分离,默认值防御,敏感信息不硬编码,实际开发中,建议使用 Python 或 Node.js 编写跨平台脚本,并配合 .env 文件管理本地开发配置,Linux 服务器推荐直接使用 Shell 结合 export 语句,Windows 则优先 PowerShell。
(完)