Shell 脚本中使用环境变量 新手超详细教程
这个简单写一下;
环境变量和 Shell 脚本结合的核心逻辑是「进程继承规则」:
- Linux 中每个程序都是一个进程,父进程的环境变量会自动传递给它启动的所有子进程。
- 脚本默认以「子 Shell 进程」的方式运行,因此它天然能继承当前终端的所有环境变量;但反过来,脚本内部定义的变量,默认不会影响外部的父终端,子进程结束变量就销毁了。
下面我们从「基础读取 → 传参方式 → 反向生效 → 实战场景 → 避坑指南」逐层讲解,每个知识点都配可运行的例子和逐行拆解,同时结合你嵌入式开发的场景给出实用案例。
一、基础用法:脚本中直接读取环境变量
这是最简单的用法:环境变量不需要在脚本里重新定义,直接用$变量名就能读取,不管是系统自带的,还是你在终端里提前导出的,都能直接用。
1. 读取系统内置的环境变量
系统预设的环境变量(HOME、USER、PATH、PWD等),所有脚本都能直接读取,不需要任何额外操作。
示例脚本read_env.sh
#!/bin/bash # 功能:读取并打印系统内置环境变量 echo "===== 系统环境信息 =====" echo "当前登录用户:$USER" echo "用户家目录:$HOME" echo "当前所在路径:$PWD" echo "默认Shell解释器:$SHELL" echo "系统主机名:$HOSTNAME" echo "系统语言编码:$LANG" echo "========================"运行与效果
chmod +x read_env.sh ./read_env.sh输出示例:
===== 系统环境信息 ===== 当前登录用户:linuxlearn 用户家目录:/home/linuxlearn 当前所在路径:/home/linuxlearn/script 默认Shell解释器:/bin/bash 系统主机名:ubuntu 系统语言编码:zh_CN.UTF-8 ========================原理说明
这些变量是启动终端时就存在的「全局环境变量」,脚本作为终端启动的子进程,自动继承了全部环境变量,所以直接用$变量名就能拿到值。
2. 读取用户自定义的环境变量
你在终端里用export导出的自定义环境变量,脚本也能直接读到。
完整操作步骤
先在终端定义并导出一个环境变量
# 导出自定义项目路径变量 export PROJECT_DIR=/home/linuxlearn/ok62xx_project export BOARD_MODEL="OK6254"写脚本
read_custom_env.sh直接读取#!/bin/bash echo "项目根目录:$PROJECT_DIR" echo "开发板型号:$BOARD_MODEL"运行脚本
./read_custom_env.sh输出:
项目根目录:/home/linuxlearn/ok62xx_project 开发板型号:OK6254
✅ 核心结论:只要是父终端里
export过的环境变量,子脚本里直接用、不用重定义。
二、三种方式:给脚本传递自定义环境变量
除了提前在终端 export,还有三种常用的传参方式,适用不同场景,新手都要掌握。
方式 1:运行脚本时「临时指定」(最灵活,调试常用)
可以在运行脚本的命令前,临时加上环境变量,只对本次脚本运行生效,不会影响当前终端的环境。
语法
变量1=值 变量2=值 ./脚本名.sh实战例子
写一个备份脚本backup.sh,备份路径和保留天数通过环境变量传入:
#!/bin/bash # 备份脚本,通过环境变量接收配置 echo "备份源目录:$BACKUP_SRC" echo "保留天数:$KEEP_DAYS" echo "开始执行备份..."运行时临时指定参数:
BACKUP_SRC=/data/project KEEP_DAYS=7 ./backup.sh输出:
备份源目录:/data/project 保留天数:7 开始执行备份...适用场景
- 临时调试脚本,想改参数又不想修改脚本内容
- 同一个脚本,不同场景传不同配置,不用写多份
- 不污染当前终端的全局环境,用完就消失
方式 2:终端先 export 全局导出(长期生效,多个脚本复用)
就是上面基础用法里的方式,先在终端export变量,后面运行的所有脚本都能读到,适合一段时间内都要用的变量。
# 终端里先导出一次 export CROSS_COMPILE=arm-linux-gnueabihf- export ARCH=arm # 后面运行的所有脚本都能直接用这两个变量 ./build.sh ./deploy.sh适用场景
- 同一会话里多个脚本都要用同一个变量
- 嵌入式开发里设置编译环境,一次设置,全程有效
方式 3:source运行脚本(双向互通,配置脚本专用)
默认运行脚本会开一个「子进程」,变量是单向继承的(父传子可以,子传父不行)。 如果用source(简写.)运行脚本,不会开子进程,直接在当前终端 Shell 里执行脚本代码,变量是双向互通的。
对比演示
写一个脚本
set_var.sh#!/bin/bash export TEST_VAR="我是脚本里的环境变量" echo "脚本内部打印:$TEST_VAR"普通方式运行(子进程)
./set_var.sh echo "脚本外打印:$TEST_VAR" # 输出空!子进程的变量传不出来source 方式运行(同进程)
source set_var.sh # 或者简写: . set_var.sh echo "脚本外打印:$TEST_VAR" # 能正常输出值!
适用场景
- 环境配置类脚本:比如设置交叉编译环境、加载项目环境变量,必须 source 才能让配置在当前终端生效
- 脚本里修改 PATH、LD_LIBRARY_PATH 等,需要对当前终端生效的场景
三、重点实战:嵌入式开发环境配置脚本
这是你日常开发最常用的场景:写一个环境配置脚本,一键设置好交叉编译工具链的 PATH、目标架构、编译器前缀,source 之后就能直接编译。
示例脚本ok62xx_env.sh
#!/bin/bash # OK62xx 交叉编译环境配置脚本 # 使用方法:source ok62xx_env.sh # 1. 交叉编译器安装路径 TOOLCHAIN_PATH=/opt/gcc-arm-10.3-2021.07-x86_64-arm-linux-gnueabihf/bin # 2. 把编译器目录加入 PATH export PATH=$TOOLCHAIN_PATH:$PATH # 3. 设置内核编译用的架构和交叉编译器前缀 export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabihf- # 4. 设置动态库搜索路径(可选) export LD_LIBRARY_PATH=/opt/ok62xx_lib:$LD_LIBRARY_PATH echo "✅ OK62xx 交叉编译环境已加载" echo "架构:$ARCH" echo "编译器前缀:$CROSS_COMPILE" echo "PATH 已更新"使用方法
# 必须用 source 运行,不然 PATH 不会在当前终端生效 source ok62xx_env.sh验证
# 查看编译器版本,能正常输出版本就是配置成功 arm-linux-gnueabihf-gcc -v💡 这是嵌入式开发的标准操作:每个项目一个环境脚本,需要的时候 source 一下,不会和其他项目的编译环境冲突。
四、进阶用法:环境变量做逻辑判断
环境变量还可以用来控制脚本的执行逻辑,实现「一个脚本,多种运行模式」。
示例:根据环境变量控制日志级别
#!/bin/bash # 通过 LOG_LEVEL 环境变量控制日志输出 # 如果没设置LOG_LEVEL,默认是info LOG_LEVEL=${LOG_LEVEL:-info} echo "当前日志级别:$LOG_LEVEL" if [ "$LOG_LEVEL" = "debug" ] then echo "[DEBUG] 调试信息:正在加载配置..." fi echo "[INFO] 程序启动中..." if [ "$LOG_LEVEL" = "debug" ] then echo "[DEBUG] 初始化完成,耗时0.2s" fi运行效果
- 默认运行:
./test_log.sh→ 只输出 info 级别的日志 - 调试模式运行:
LOG_LEVEL=debug ./test_log.sh→ 输出详细调试日志
好处:不用修改脚本代码,通过环境变量就能切换运行模式,非常灵活。
五、新手必踩坑与避坑指南
坑 1:脚本里 export 了变量,外面看不到
- 原因:脚本默认在子 Shell 进程里运行,子进程的环境变量不会反向传给父终端,脚本结束进程销毁,变量就没了。
- 解决:需要对当前终端生效的配置脚本,必须用
source/.运行。
坑 2:脚本里读不到我定义的变量
- 原因:你只定义了普通 Shell 变量,没有
export导出成环境变量,子进程继承不到。 - 对比:
# 普通变量,子脚本读不到 A="测试" # 环境变量,子脚本能读到 export B="测试"
坑 3:路径变量有空格,脚本报错
- 原因:环境变量的值包含空格时,直接用
$VAR会被拆成多个参数。 - 解决:引用变量时一定要加双引号
"$VAR"。# ❌ 错误,路径有空格就报错 cd $PROJECT_PATH # ✅ 正确,加双引号保证整体作为一个参数 cd "$PROJECT_PATH"
坑 4:环境变量名用小写
- 约定俗成:环境变量全大写(比如
PATH、HOME、PROJECT_DIR),脚本内的普通变量用小写,方便区分。 - 不是语法强制,但行业通用规范,建议遵守。
坑 5:修改 PATH 后不生效
- 脚本里修改了 PATH,关掉终端再打开就没了 → 要永久生效就写到
~/.bashrc里。 - 脚本里改了 PATH,当前终端没变化 → 子进程修改不影响父终端,source 运行脚本才行。