1 基本概念
环境变量是操作系统中,用来指定系统运行环境的参数,通常具有全局特性,在系统中全局生效,供所有进程 / 程序使用。
环境变量 = 系统全局的 "快捷方式 + 配置信息"
你在终端输入ls pwd cd 系统怎么知道这些命令在哪?
靠的就是环境变量 PATH。
PATH 里存的是一堆目录路径 ,用冒号 : 隔开。系统执行命令时,会挨个去这些目录里找同名程序
- 环境变量 (environment variables) 一般是指在操作系统中用来指定操作系统运行环境的一些参数
- 如:我们在编写 C/C++ 代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
- 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性
常用环境变量有哪些?
PATH:命令搜索路径HOME:当前用户家目录PWD:当前所在目录USER:当前用户名SHELL:当前使用的 shellLANG:语言编码PS1:命令行提示符长啥样
2 环境变量的来源与传递
1. 环境变量的源头
bash 进程的环境变量,从 Linux 系统的配置文件中来 (如~/.bashrc、/etc/profile等),配置文件中定义的export语句,会在 bash 启动时被加载,写入 bash 的环境变量表。
2. 存储与传递逻辑
- 存储位置 :环境变量本质是存储在内存中的临时表(环境变量表),属于内存级数据,仅在进程运行期间有效。
- 传递关系 :
- 我们运行的程序、命令,都是 bash 进程的子进程;
- 子进程会继承父进程(bash)的环境变量表,因此子进程可以共享父进程的环境变量;
- 这就是环境变量全局特性的本质:父进程(bash)将环境变量传递给所有子进程,实现全局生效。
- 传递方式:本质是把环境变量表,传递给子进程,由子进程继承使用。
3 环境变量与C/C++代码、进程的关系
1. 代码中获取环境变量的 3 种方式
(1)main 函数的第三个参数
C 语言main函数有 3 个参数,第三个参数char *env[](也可写作char **envp),直接接收完整的环境变量表:
int main(int argc, char *argv[], char *env[])
env[]是一个字符指针数组,每个指针指向一个"变量名=值"格式的字符串(如HOME=/home/akaedu);- 数组以
NULL作为结束标志,遍历数组即可打印所有环境变量。
(2)全局变量char **environ
Linux 系统提供全局变量environ,直接指向环境变量表,和main函数的env[]作用完全一致,可直接遍历使用。
(3)库函数getenv(name)
C 标准库提供getenv(const char *name)函数,传入环境变量名(如"PATH"),直接返回对应的值,是精准获取单个环境变量的常用方式。
2. 实际运行效果示例
执行自定义程序./mycommand时,会打印出完整的环境变量表,示例如下:
[ ]$ ./mycommand
env[0]: XDG_SESSION_ID=36981
env[1]: HOSTNAME=alicloud
env[2]: TERM=xterm
env[3]: SHELL=/bin/bash
env[4]: HISTSIZE=1000
env[5]: SSH_CLIENT=113.132.215.158 17705 22
...
3. 核心结论
- 环境变量是父进程(bash)给你的 ,子进程通过
fork创建时,会继承父进程的环境变量; - 因此环境变量具有全局属性,所有 bash 的子进程都能访问到。
4 补充延伸
1. 环境变量的作用
- 帮助编译器查找依赖:编写 C/C++ 代码时,链接动态 / 静态库时,编译器能自动找到库文件,就是依赖相关环境变量的帮助;
- 软件全局配置:Java、Python 等软件,配置
PATH后,可在任意目录直接调用对应命令; - 系统运行参数:指定用户目录、终端类型、语言编码等系统运行的基础参数。
2. 临时 vs 永久环境变量
- 临时环境变量:通过
export 变量名=值在终端设置,仅在当前 bash 进程有效,关闭终端即失效; - 永久环境变量:写入系统配置文件(如
~/.bashrc),bash 启动时自动加载,永久生效。
5 环境变量、本地变量、内建命令知识梳理
1. 本地变量
- 定义 :仅在当前 bash 进程内部生效的变量,无法被子进程继承,不具备全局属性。
- 定义方式 :直接赋值,无需
export,如TEST_ENV="helloworld"、local_value=100 - 特性验证 :
- 直接
echo $变量名可正常读取; env | grep 变量名无法查到(env 仅显示环境变量);- 运行子进程(如
./mybash)时,变量值为null,无法继承。
- 直接
- 存储位置:仅存在于当前 bash 进程的内存中,不写入环境变量表。
2. 环境变量
- 定义 :可被子进程继承的全局变量,是环境变量全局特性的本质:环境变量可以被子进程继承。
- 定义方式 :通过
export将本地变量升级为环境变量,如export TEST_ENV=123456789 - 特性验证 :
echo $变量名可读取,env | grep 变量名可查到;- 子进程可继承该变量,全局生效。
- 存储位置:写入 bash 进程的环境变量表,随进程传递给子进程。
3. 内建命令 vs 普通命令
| 特性 | 普通命令 | 内建命令(shell 内置命令) |
|---|---|---|
| 本质 | 独立的二进制可执行文件,存放在PATH指定的目录中 |
在 shell(bash)内部自定义的函数,不依赖外部二进制文件 |
| 执行方式 | 系统 fork 子进程执行,依赖PATH查找 |
由 bash 直接调用,无需 fork 子进程,不依赖PATH |
| 示例 | ls、top、/usr/bin/echo |
cd、pwd、echo(bash 内置版)、export、unset |
PATH清空后的表现 |
无法执行(系统找不到二进制文件) | 正常执行(不依赖PATH) |
结论:
- 普通命令依赖
PATH查找二进制文件,PATH清空后失效; - 内建命令由 bash 直接实现,不依赖
PATH,始终可用。
4、核心知识点总结
- 全局属性本质 :环境变量的全局特性,核心是子进程可以继承父进程的环境变量,本地变量无此特性。
- 操作级别 :所有
export、unset等操作都是内存级,仅对当前 bash 进程有效,不会修改系统配置文件,重启终端 / 系统后失效。 - 命令分类 :区分普通命令(二进制文件)和内建命令(shell 内置),是理解
PATH作用、命令执行逻辑的关键。 - 变量生命周期:本地变量仅存活于当前 bash,环境变量随 bash 进程传递给子进程,进程终止则变量销毁。
