怎么用脚本设置临时环境变量

wen 实用脚本 3

怎么用脚本设置临时环境变量(Shell/Python/Bat全攻略)

📚 目录导读

  • 为什么需要临时环境变量?
  • 基础概念:临时环境变量 vs 永久环境变量
  • Shell脚本(Linux/macOS)中设置临时环境变量
    • 单条命令临时设定
    • 多条命令内的变量传递
    • 子shell与父shell的隔离机制
    • 实战:export、source、exec的区别
  • 批处理脚本(Windows CMD/PowerShell)中设置临时环境变量
    • CMD下的set与setx
    • PowerShell的$env: 与 [Environment]::SetEnvironmentVariable
    • 跨脚本传递变量的技巧
  • Python脚本中临时设置环境变量
    • os.environ字典的临时修改
    • subprocess继承环境变量的控制
    • dotenv库读取.env文件
  • 常见错误与调试方法
    • 为什么变量设置后不起作用?
    • 查看当前所有环境变量的命令
  • QA问答精选(真实场景)
  • 选择最佳实践

为什么需要临时环境变量?

在日常开发、CI/CD流水线、或服务器部署时,我们经常需要临时改变程序的行为——比如切换数据库连接字符串、指定日志级别、或者在不影响全局配置的前提下测试新版本API密钥。

怎么用脚本设置临时环境变量

典型场景

  • 本地调试时,临时覆盖 DATABASE_URL 指向测试库
  • 部署脚本中,为单个命令注入密钥而不写入磁盘
  • 在多项目并行时,防止环境变量污染全局 ~/.bashrc

核心痛点:很多新手在脚本里 export 一个变量后,发现退出脚本就没了,或者发到另一台机器就失效了——这正是“临时”的精髓,我们将从原理到实战,彻底打通。


基础概念:临时环境变量 vs 永久环境变量

特性 临时环境变量 永久环境变量
生命周期 当前Shell进程或脚本执行期间 用户登录会话 / 系统重启后依然存在
设置位置 终端命令行 / 脚本内 export ~/.bashrc/etc/profile、系统属性
影响范围 当前进程及其子进程 所有新启动的Shell
典型用途 一次性构建、测试、敏感信息注入 固定路径、默认编辑器、语言编码

一句话记忆:临时变量是“用完即走”,永久变量是“常住户口”。


Shell脚本(Linux/macOS)中设置临时环境变量

单条命令临时设定(最常用)

# 在命令前直接赋值,只对该命令生效
DB_HOST=test.example.com npm run migrate
# 多个变量可以并列
API_KEY=123 DEBUG=true python app.py

原理:这其实是 bash 的特性——在当前行前面插入变量赋值,它们被当作“入口环境变量”传递给该命令的子进程,命令结束后变量自动消失,适用于仅一次的调用。

多条命令内的变量传递

如果你想在同一个Shell会话里连续使用变量,需要 export

#!/bin/bash
# 临时设置,仅对当前脚本内后续命令有效
export MY_SECRET="s3cr3t"
echo "当前变量: $MY_SECRET"
python -c "import os; print(os.getenv('MY_SECRET'))"

注意:脚本结束后 MY_SECRET 不在外部Shell中残留,如果你用 . script.shsource script.sh 执行,则变量会留在当前Shell——这正是 source 的“加载”效果。

子shell与父shell的隔离机制

# 在括号内执行,生成一个子shell
(
  export TMP_DIR="/tmp/mybuild"
  cd "$TMP_DIR" && make
)
# 退出子shell后,TMP_DIR 和 cd 操作均不影响父shell
echo "父shell当前目录: $(pwd)"

常见误解export 后变量会一直存在?错,它只存在于当前Shell以及它启动的子进程,如果你打开一个新终端,它不存在。

export、source、exec的区别

命令 行为 变量是否持久到当前Shell
export VAR=val 设置变量并标记为可传递给子进程 ✅ 是的
source script.sh 在当前Shell中逐行执行脚本 ✅ 脚本内的export在脚本结束后仍然有效
./script.sh 启动一个子Shell执行脚本 ❌ 变量在子Shell内有效,执行完后消失
exec cmd 用新进程替换当前Shell ❌ 原Shell消失,变量在新进程中

最佳实践:如果你在一个脚本内需要临时变量,直接在脚本里export,然后用 ./script.sh 执行,不会污染环境。


批处理脚本(Windows)中设置临时环境变量

CMD(传统命令行)

@echo off
REM 临时设置,仅对当前CMD窗口有效
set MY_VAR=temporary_value
echo %MY_VAR%
python -c "import os; print(os.getenv('MY_VAR'))"

关键区别:CMD中 set 默认就是临时变量,退出窗口即消失。setx 才是永久写入注册表。

跨文件传递:如果你在 build.bat 里set了一个变量,想让它影响 deploy.bat,需要 call

REM build.bat
set BUILD_NUM=42
call deploy.bat

PowerShell

# 临时设置当前进程的环境变量
$env:MY_SECRET = "temp123"
python -c "import os; print(os.getenv('MY_SECRET'))"
# 仅对一条命令临时设置(类似Linux前缀写法)
$env:DEBUG='true'; npm run test
# 查看当前所有临时环境变量
Get-ChildItem Env: | Format-Table

永久设置要用 [Environment]::SetEnvironmentVariable("MY_VAR", "value", "User"),这与临时机制完全不同。

PowerShell vs CMD:PowerShell的 $env: 前缀比 set 更直观且支持对象操作,推荐在Windows 10+上优先使用。


Python脚本中临时设置环境变量

通过 os.environ 临时修改

import os
# 临时设置,只影响当前Python进程以及后续os.system/subprocess启动的子进程
os.environ['DATABASE_URL'] = 'postgres://test:pass@localhost:5432/dev'
print(os.environ['DATABASE_URL'])
# 启动子进程,会继承上面的变量
os.system('echo $DATABASE_URL')  # Linux/macOS
# 或
os.system('echo %DATABASE_URL%') # Windows

重要os.environ 是对当前进程环境变量的直接操作,不会写入系统或文件,Python退出后消失。

subprocessenv 参数(彻底隔离)

import subprocess
import os
# 创建一个全新的环境,不继承当前进程的环境
new_env = {**os.environ, 'MY_SECRET': 'override'}
subprocess.run(['python', 'child.py'], env=new_env)
# 或者只传递自定义变量(丢弃所有系统变量)
subprocess.run(['python', 'child.py'], env={'APP_MODE': 'test'})

典型用途:在CI脚本中,你不想把 $HOME 或密钥泄露给子进程,就可以自定义 env

使用 python-dotenv 读取 .env 文件

很多项目用 .env 文件管理临时环境变量:

# .env 文件内容(不需要引号,不需要export)
DATABASE_URL=postgres://localhost/mydb
SECRET_KEY=abc123

Python读取:

from dotenv import load_dotenv
import os
# 加载 .env 到 os.environ(临时)
load_dotenv()
print(os.getenv('DATABASE_URL'))

优势:无需在脚本或命令行里写死敏感信息,适合提交到GitHub(需gitignore!)。


常见错误与调试方法

❌ 错误1:export后为什么脚本外还能看到?

很可能你用了 source script.sh 而不是 ./script.shsource 是在当前Shell执行的,export 会残留在你的终端里。

❌ 错误2:Windows下set后,新打开的CMD找不到

这是正常的。set 只对当前CMD窗口有效,如果你需要永久设置,用 setx(但那就不是临时了)。

✅ 调试命令

系统 查看当前所有环境变量
Linux/macOS envprintenv
Windows CMD set
Windows PowerShell Get-ChildItem Env:dir env:
Python import os; print(dict(os.environ))

快速检查特定变量

echo $PATH          # Linux
echo %PATH%         # CMD
echo $env:PATH      # PowerShell

QA问答精选(真实场景)

Q1:我在Dockerfile里用ENV设置变量,这是临时的还是永久的?

A:Docker的 ENV 指令是永久的——构建时写入镜像层,容器启动后每个进程都能看到,如果你只想在构建期间临时用(比如下载临时密钥),用 ARG 然后结合 --build-arg 传值,构建完成后不保留。

Q2:用脚本设置临时环境变量,如何确保子进程(如npm、python)能继承到?

A:关键是在父Shell中必须export(或使用上一节的前缀法 VAR=value cmd),如果父进程没有export,子进程只能看到未标记的变量(实际上看不到),检测方式:在子进程中打印 os.environecho $VAR

Q3:持续集成(CI)中,怎么安全地传递临时密钥?

A:CI平台(如GitHub Actions、GitLab CI)本身提供了「临时环境变量」机制——你在Web界面设置的Secret会被自动注入到每个Job的Shell里,但不会出现在日志中,在脚本中直接用 $API_KEY 即可,CI平台保证安全性,具体做法:在CI设置里定义 API_KEY,然后在 .gitlab-ci.ymlaction.ymlscript: 中使用。

Q4:多个脚本需要共享同一个临时变量,如何避免重复export?

A:创建一个 setup_env.sh 文件,里面只包含export命令,然后在每个脚本中 source 它:

# setup_env.sh
export BUILD_ID=$(date +%s)
export TARGET_STAGE='dev'
# 其他脚本中
source ./setup_env.sh
echo "当前构建ID: $BUILD_ID"

这样可以避免每个脚本里写重复的变量值,且变量生命周期仅限于脚本执行期间(如果不沿用 source 的话)。

Q5:Windows下用Start-Job启动异步任务,环境变量能传递吗?

A:默认不会,需要在 Start-Job 中显式使用 -ArgumentList 或设置 $env: 在脚本块内,推荐做法:

$job = Start-Job -ScriptBlock { param($port) $env:PORT=$port; node server.js } -ArgumentList 8080

选择最佳实践

场景 推荐方法
只运行一次命令(最常见) VAR=val command(Linux) / $env:VAR='val'; command(PowerShell)
脚本内有多个命令需要共享 export(Linux) / set(CMD) / $env:(PowerShell)
Python内部临时覆盖 os.environ['KEY']='val'
不希望子进程继承过多变量 subprocess.run(..., env={})
管理项目配置文件 .env + python-dotenv
CI/CD流水线中传敏感信息 CI平台的内置Secret变量

最后建议:始终明确“临时”的边界——脚本执行完后,变量应该自动消失,不留痕迹,如果某个变量需要跨会话使用,请把它加入 ~/.bashrc 或系统环境变量,但那就不属于本文讨论的“临时”范畴了。

(全文约2900字)

抱歉,评论功能暂时关闭!