直接运行env即可查看当前shell中所有已导出且真实传给子进程的环境变量,输出为纯KEY=VALUE格式,不包含未export的局部变量、函数或shell内置变量,是验证变量是否生效的最准确起点。

直接运行 env 就能看到当前 shell 进程中所有「正在使用的环境变量」——也就是已导出(exported)、且实际传给子进程的那批变量。这不是“理论上定义过”的变量,而是内核当前给这个进程分配的、真实生效的环境快照。
为什么 env 是最准的起点
它只输出 export 过的变量,不混杂函数、shell 内置变量(如 BASH_VERSION)或未导出的局部变量。你在脚本里写了 MYVAR=123 却没 export MYVAR,env 就不会显示它——这恰恰是你要的结果:看「哪些变量真能被 curl、python、make 这类子进程读到」。
-
env输出是纯KEY=VALUE格式,方便grep、awk处理,比如env | grep -i path - 输出顺序按声明先后(GNU 版本默认字母序,可用
env -0 | sort -z | tr '\0' '\n'强制排序) - 不依赖 bash 特性,在
/bin/sh(如 dash)下也完全可用
printenv 和 env 选哪个?
查单个变量必须用 printenv VARNAME;查全部时两者等价,但行为有关键差异:
-
env VARNAME会被 shell 当作「启动一个叫VARNAME的程序」,大概率报错:bash: env: VARNAME: No such file or directory -
printenv VARNAME明确语义,返回值或空行(变量为空或未设置),适合脚本判断:if [ -z "$(printenv DEBUG)" ]; then ... - Alpine 等精简系统预装
printenv(busybox 提供),但可能没 GNUenv
想看到未导出的变量?别用 env,改用 declare -p
env 故意不显示它们——因为这些变量根本不会传给子进程。但调试时你可能需要确认:PATH 是不是被某个地方悄悄设空了?PS1 是不是被覆盖成乱码?这时:
-
declare -p PATH会输出类似declare -x PATH="/usr/bin:/bin",其中-x表示已导出;declare -- PATH=""表示显式设为空字符串 -
declare -p | grep '^declare -x '等价于env,但格式更结构化 -
declare -p | grep -v '^declare -x '才是未导出的自定义变量(排除函数和内部状态需额外过滤)
排查程序实际收到的环境,得绕过 shell 层
你在终端里敲 env 看到的,是当前 shell 进程的环境;但某个正在跑的 nginx 或 java 进程,它启动时继承的是那一刻的快照,之后你再 export 新变量,它也收不到。要验证它到底拿到什么:
- 查当前 shell 自己的原始环境:
cat /proc/$$/environ | tr '\0' '\n' - 查某进程(如 PID 1234):
cat /proc/1234/environ | tr '\0' '\n' - 注意:
/proc/*/environ用\0分隔,直接cat会乱码,tr这步不能省
真正容易被忽略的是:变量作用域和 shell 类型混在一起时,export 在不同上下文里根本不是同一个东西——#!/bin/sh 脚本里的 export FOO=bar 可能被忽略,而 bash -c 'export FOO=bar; env' 中的 export 又只在子 shell 生效。看变量前,先确认你在哪个 shell 里、以什么方式执行的。











