env只能查看已导出的环境变量,因为其输出源自进程的“环境块”,未执行export的变量仅限当前shell作用域,子进程无法继承;set或declare -p才能显示全部变量(含未导出变量、函数等),其中declare -p格式更规范、可区分导出状态。

env 只能看到已导出的环境变量,set 才能真正看到“所有系统变量”——包括未导出的 shell 变量、函数、内置配置项。但直接跑 set 会混入大量噪音,必须过滤。
为什么 env 不等于“所有变量”
env 输出的是当前进程的「环境块」(environment block),只含 export 过的变量。你写 MYVAR=123 没加 export,它就根本不会出现在 env 里,子进程也收不到。这不是命令缺陷,是 POSIX 环境模型本身的设计:未导出 = 仅限当前 shell 作用域。
set 怎么用才不被函数刷屏
set 默认输出变量 + 函数 + shell 选项,函数体动辄几十行。安全过滤方式是:
- 只取合法变量赋值行:
set | grep '^[a-zA-Z_][a-zA-Z0-9_]*=' - 排除函数定义(函数名后跟
()):set | grep -v '^[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]*()' - 想看带引号包裹的原始值(防换行/空格截断):
set | grep '^[a-zA-Z_][a-zA-Z0-9_]*=' | sed "s/=/='/; s/$/';/" | while IFS="=" read -r k v; do echo "$k=$v"; done(慎用,仅调试时)
declare -p 是更干净的替代方案
declare -p 是 bash 内置命令,输出格式统一为 declare -x VAR="value" 或 declare -- VAR="value",能一眼区分是否已导出:
- 查所有变量(含未导出):
declare -p - 只查已导出的:
declare -px - 只查未导出的:
declare -p | grep -v '^declare -x ' - 查某个变量是否只读:
declare -p MYVAR—— 若输出含-r,说明不能unset或重赋值
别信终端里跑的 env,要看进程真实环境
你改了 PATH 后 env | grep PATH 显示正常,但启动的程序却没生效?可能它不是从当前 shell 继承的。真正权威的是 /proc/$$/environ:
- 当前 shell 的原始环境:
cat /proc/$$/environ | tr '\0' '\n' - 某子进程(如
nginx)的真实环境:cat /proc/$(pgrep nginx)/environ | tr '\0' '\n' - 注意:
$$是当前 shell 的 PID,tr '\0' '\n'必须加,否则全是乱码
这个文件内容和 env 输出一致,但绕过了 shell 层解析 —— 如果两者不一致,说明你在 shell 启动后手动修改过变量,而该进程没继承这些改动。











