暗色模式

Linux 环境变量:从 printenv 到 export 与持久化配置

技术教程
2026-08-19
42
0

Linux 环境变量:从 printenv 到 export 与持久化配置

本文要点
  • 环境变量是键值对形式的全局配置,影响程序行为,可用 printenvenvecho $VAR 查看
  • 临时变量只对单条命令生效,export 让子进程继承,unset 删除变量
  • 引用变量用双引号保持展开,用 ${VAR} 做变量名拼接,用 ${VAR:-默认值} 给缺省兜底
  • 持久化配置分系统级 /etc/environment/etc/profile.d/ 与用户级 ~/.bashrc~/.profile
  • 常见坑sudo 默认清空环境变量、非交互 shell 不读 ~/.bashrc、PATH 被覆盖找不到命令

环境变量是什么

环境变量(Environment Variable)是操作系统为进程提供的键值对配置,可以理解成一组"全局设置项"。程序运行时通过读取这些变量来决定行为,比如去哪个目录找可执行文件、用哪种语言输出提示、把临时文件放哪里。

# 形如 KEY=VALUE 的键值对
HOME=/root
LANG=C.UTF-8
PATH=/usr/local/sbin:/usr/bin:/bin

与普通 shell 变量不同,环境变量有两个特点:

  1. 全局可见:一旦设置,当前 shell 和它启动的所有子进程都能读到;
  2. 跨程序生效:任何语言写的程序(C、Python、Go…)都可以通过系统接口读环境变量,这是 Linux 程序间传递配置最基础的方式之一。

查看环境变量

printenv 查看指定变量

printenv 可以一次查看多个指定变量的值:

printenv HOME SHELL LANG USER

查看环境变量

图中的输出告诉我们:主目录是 /root、默认 shell 是 /bin/bash、语言环境是 C.UTF-8、当前用户是 root

env 列出全部变量

不带参数执行 env 会列出当前 shell 的全部环境变量:

env | head -5

echo 快速读取

在 shell 中更常用的是直接用 $ 前缀展开变量:

echo "当前用户: $USER, 主目录: $HOME"
注意:$ 展开发生在双引号内,所以上面的输出是"当前用户: root, 主目录: /root",而不是字面 $USER

临时变量:只对单条命令生效

命令前缀方式

如果只想让一条命令临时带个配置,直接在命令前加 KEY=VALUE 即可,不污染当前 shell

VAR=hello bash -c 'echo $VAR'

这条命令临时为 bash 设置了 VAR=hello,输出 hello,但当前 shell 里并不存在 VAR

变量赋值 vs 环境变量

在 shell 里直接写 VAR=hello 只是定义了一个 shell 变量,子进程读不到;只有 export 之后才变成环境变量,能被子进程继承:

export VAR=world   # 导出为环境变量,子进程可见
echo $VAR          # world
unset VAR          # 删除该变量
echo $VAR          # 空

临时变量、export 与 unset

图中演示了完整生命周期:

  1. 第一条命令 VAR=hello bash -c 'echo $VAR' 输出 hello,变量只对子进程生效;
  2. export VAR=worldecho $VAR 输出 world
  3. unset VAR 删除变量,最后的 echo $VAR 输出为空。

变量引用与拼接

双引号与单引号的区别

双引号内的 $VAR 会展开,单引号内的会原样保留:

NAME=Linux
echo "双引号: $NAME"    # 输出: 双引号: Linux
echo '单引号: $NAME'    # 输出: 单引号: $NAME

${VAR} 变量名拼接

当变量名后面紧跟其他字符时,必须用 ${VAR} 明确边界,否则 shell 会把整段当成变量名:

APP_NAME=nginx
echo "版本号: ${APP_NAME}-1.24"   # 输出: 版本号: nginx-1.24
# echo "版本号: $APP_NAME-1.24"   # 错误:shell 会去找变量 APP_NAME-1.24

${VAR:-默认值} 缺省兜底

变量没定义时,${VAR:-default} 会展开为默认值,常用于脚本里给配置项兜底:

echo "${NOTSET:-默认值}"   # 输出: 默认值
echo "${HOME:-/root}"      # 输出: /root

子进程继承:export 的作用

环境变量是"从父进程继承给子进程"的。用 export 导出后,任何子进程都能读到:

export INHERITED=yes
bash -c "echo 子进程看到: $INHERITED"   # 输出: 子进程看到: yes

但要注意两点:

  • 反向不传递:子进程里修改的变量不会影响父进程;
  • 有例外sudo 默认会清空大部分环境变量(见下文常见坑)。

持久化配置:让环境变量每次登录都生效

临时设置的变量重启终端就没了。要永久生效,需要写入配置文件。Linux 按"系统级 → 用户级"两级组织:

系统级配置

文件作用加载时机
/etc/environment所有用户共用的基础环境变量登录时由 PAM 读取
/etc/profile全局登录脚本,定义 PATH 等登录 shell 启动时
/etc/profile.d/*.sh全局环境变量扩展脚本(更推荐)/etc/profile 自动 source

查看系统级配置:

cat /etc/environment
ls /etc/profile.d/ | head -6

环境变量配置文件

图中可以看到 /etc/environment 里通过 PATH="..." 形式定义了系统默认搜索路径,而 /etc/profile.d/ 下则放了一堆按功能拆分的脚本(bash_completion.shapps-bin-path.sh 等),由 /etc/profile 自动加载。

用户级配置

文件作用加载时机
~/.bashrc用户交互式 shell 配置每次打开交互式终端
~/.profile用户登录配置登录 shell 启动时

把环境变量写进 ~/.bashrc,以后每次开终端都自动生效:

echo "export MY_APP_CFG=demo-value" >> ~/.bashrc
source ~/.bashrc
echo $MY_APP_CFG   # demo-value
source(等价 .)会立刻在当前 shell 执行文件内容,不必重新登录。

常见坑与注意事项

坑 1:sudo 默认清空环境变量

sudo 出于安全默认重置环境变量,你自己 export 的变量在 sudo 内是读不到的:

export MY_SECRET=abc123
sudo bash -c "echo sudo内: $MY_SECRET"   # 输出为空

若确实需要保留,用 sudo -E(保留现有环境)或 sudo VAR=value command(指定传递)。

坑 2:非交互 shell 不读 ~/.bashrc

很多脚本在开头有这段保护:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

所以通过 ssh host "source ~/.bashrc; echo $VAR" 这类非交互方式执行时,~/.bashrc 会被直接跳过,变量读不到。要么改用交互式 bash -i,要么把通用变量放到 ~/.profile

坑 3:PATH 被覆盖后找不到命令

PATH 决定命令查找顺序。一旦被错误覆盖(比如 PATH=/tmp),lsvim 等命令全部失效:

echo $PATH | tr : "\n"   # 分行查看 PATH 里的每个目录
which -a ls              # 查看 ls 实际在哪些目录

排查思路:先确认 which -a 找得到命令,再检查 PATH 是否丢了目录;恢复用 export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

坑 4:env -i 会完全清空

env -i command 让命令在空环境中运行(测试脚本健壮性常用):

env -i bash -c "echo 清空后 HOME=$HOME"   # HOME 为空

小结

环境变量是 Linux 下最基础的配置机制,掌握后能少踩很多坑。核心记忆点:

  • 查看printenv / env / echo $VAR
  • 临时用在命令前加 KEY=VALUE持久用写配置文件并 source
  • export 让子进程继承,unset 删除,${VAR} 拼接,${VAR:-def} 兜底;
  • 系统级写 /etc/profile.d/,用户级写 ~/.bashrc~/.profile

日常排障时,遇到"明明设置了却不生效",先按「变量有没有 export → 文件有没有被加载 → 是不是 sudo/非交互环境」三步排查,很快就能定位。

发表评论

暂无评论,快来抢沙发吧!