基本理解
环境变量一般是指在操作系统中用来指定运行环境的某些参数。可以将它们视为“系统或程序运行时使用的隐藏小助手”,如同标签一样附着在系统或程序的背后,提供关键信息以确保程序能够正常运行。
例如,当你刚搬到一个新城市,需要快速适应新的生活环境,你可能会在手机里保存一些重要信息:
- 超市地址(相当于PATH):方便随时找到最近的超市购买日用品。
- 默认快递地址(相当于HOME):别人寄送物品时可以直接填写这个地址,无需每次重复输入。
环境变量就是这类“系统级快捷信息”,程序或系统需要这些信息时可以直接调用,不需要每次都手动输入。
环境变量的应用实例
-
当你在终端输入c++命令,但系统不知道c++安装在哪个目录时,会报错“命令未找到”。通过PATH环境变量告诉系统:“C++位于/usr/bin/cpp这个目录下”,这样就可以直接执行该命令,而无需指定路径。
-
程序需要保存文件时,但不知道存放到哪里,可能会随意存储到系统目录。HOME环境变量指向你的用户目录(如/home/yourname),程序会自动将文件存储在你的“家目录”里。就像你快递寄存的地址设置为“XX小区X栋X室”,设置默认地址后,就不需要每次都告诉快递员具体地址。
命令行参数
在之前的学习中我们了解到main是程序的入口点,但实际上main函数并非第一个被执行的函数。_start才是程序真正的入口点,main通常由_start间接调用,但具体实现与操作系统和编译器相关。
因此,main函数内部也可以有参数,尽管这些参数是可写可不写的。命令行参数并非所有程序都需要,如果程序不需要参数,强制要求会增加代码复杂度。
main函数中的命令行参数
main函数的第一个参数argc是一个int类型的变量,第二个参数argv是一个char*类型的指针数组。如果我们打印argc的内容,可以看到输出的是我们的程序名(例如./code)。
如果我们在打印时像指令一样带参数的话,对应的参数也会被打印出来。
命令行输入的参数以空格分隔,将输入的内容划分为多个部分,分别放入argv这个char*指针数组中。argc统计的是argv数组中的元素个数,在argv数组中需要以NULL结尾。
环境变量PATH与程序执行
当我们使用自己编写的code程序时,需要通过./code的方式执行(通过路径方式找到当前目录下的code程序)。而当我们执行指令(如ls、pwd)时,无论在哪个目录下都可以直接使用,无需带上它们的路径。
如果将我们自己的程序复制到/usr/bin路径下(需要root权限),我们会发现自己的程序也可以像命令一样直接执行,并且可以在任何目录下直接调用!
为什么会有这样的区别?
这是因为系统中存在环境变量的原因。自带的指令位于/usr/bin路径下,通过环境变量PATH可以直接找到这些命令。因此,将我们自己的程序放到这个路径下也可以不带路径直接执行。
查看环境变量
可以使用env命令查看所有环境变量。环境变量的显示方式是等号左边是名字,右边是内容。例如,通过echo $PATH可以查看PATH环境变量的内容,可以看到多个路径以冒号分隔。
环境变量的工作原理
当执行一个命令时,如果没有手动指定路径,则会优先在PATH环境变量中的第一条路径下查找。如果未找到,则继续查找下一个路径,直到所有路径都找完为止。如果仍未找到,则会报错“not found”。因此,这解释了为什么code不在/usr/bin路径下直接使用会报not found错误,而将其放到/usr/bin路径下则可以正常执行。
测试将程序路径添加到PATH环境变量中
既然将code程序放在/usr/bin路径下可以直接使用是因为该路径在PATH环境变量中,那么如果直接将code所在的路径添加到这个PATH环境变量中,code是否也能直接执行?答案是肯定的。接下来可以进行测试。

给PASH环境变量添加新路径的方法及理解环境变量的存储和来源
如何向PATH环境变量中添加新路径
若需将新的目录添加至PATH环境变量,可采用以下格式:
PATH=$PATH:新添加的路径
这里,$PATH代表原有的路径集合。如果不使用$PATH而直接设置PAT=新添加的路径,将会覆盖原有的PATH值,导致如ls等依赖环境变量中路径的命令失效(但pwd、cd这类内建命令仍可正常工作)。重启Xshell后,PATH会恢复至其初始状态。
深入理解环境变量
环境变量是操作系统提供给用户的一种机制,用于存储各种配置信息。当一个用户登录系统时,操作系统会自动启动一个bash进程,并从系统配置文件中读取所有的环境变量设置,形成一张环境变量表。
在执行如code -a这样的命令时(假设未手动指定路径),命令解析过程如下:
- 以空格分割输入的命令为多个部分(例如:将
code -a分为code和-a)。 - 查找
argv[0](即程序名称)在环境变量PATH所定义的路径中是否存在。若存在,则创建子进程执行该命令;反之,显示“not found”错误信息。
环境变量的来源及存储位置
环境变量最初来源于系统的配置文件,在用户登录时由bash进程加载到内存中。具体来说,每个用户的主目录下都有隐藏的配置文件(如.bash_profile和.bashrc),这些文件会调用系统级配置文件/etc/bashrc来设置环境变量。
命令执行过程中的关键表格
当一个用户登录时,操作系统为其分配了一个bash进程。每个bash进程中包含两张重要表格:命令行参数表和环境变量表。命令行参数表用于解析用户输入的指令及其参数;而环境变量表在bash启动时从系统配置文件中加载。
常见的环境变量
除了PATH,还有其他常用的环境变量,比如:
- HOME: 当前用户的主目录路径。例如,执行
cd ~实际上是通过环境变量HOME来确定目标位置的。 - SHELL: 显示当前用户默认使用的Shell程序路径。
- USER: 当前登录用户名。
- LOGNAME: 与USER类似,用于标识当前登录用户。
- HISTSIZE: 历史命令的存储条数,默认通常是1000条。
- HOSTNAME: 当前主机名。
- LS_COLORS: 定义了文件和目录在列表显示时的颜色样式。
- PWD: 显示当前工作目录的完整路径。
- OLDPWD: 记录上一个访问过的目录,使用
cd -命令可返回该目录。
获取和管理环境变量的方法
可以通过以下命令查看或修改环境变量:
env: 显示所有当前的环境变量。echo $环境变量名称: 查看特定环境变量的具体值。export 环境变量名=新值: 设置或修改环境变量,使其对当前会话及其子进程可见。unset 环境变量名: 移除指定的环境变量。
通过编程方式访问环境变量
在程序中,可以通过main函数的第三个参数char* env[]来获取环境变量表。此数组由父进程bash在创建子进程时传递给子进程。例如,在C语言中:
int main(int argc, char *argv[], char *env[]) {
// 代码逻辑
}
通过这种方式,程序可以直接访问运行环境中的所有环境变量。
子进程创建时会获得一个与父进程完全相同的环境变量副本,这意味着如果子进程再生成自己的子进程(即孙进程),这个孙进程同样会继承其直接父进程的环境变量。因此,环境变量具备全局特性。
在C语言中,main函数可以接受不同数量的参数以适应不同的应用场景。虽然我们在命令行调用程序时通常不直接看到这一点,但在Linux系统下,实际执行的第一个函数是_start。_start负责初始化环境,并根据传入参数的数量调用相应的main函数版本。
getenv是一个用于获取特定环境变量值的C库函数。通过给定的环境变量名称作为参数,该函数能够返回与之关联的具体字符串内容;若指定的环境变量不存在,则函数返回NULL。
利用这一特性,我们可以编写一个只有特定用户才能运行的程序。例如,如果希望仅当当前用户的用户名为yx时才允许执行某段代码(即便是root用户也不行),可以通过在子进程中检查继承自父进程的USER环境变量来实现。
environ是一个全局数组,其中包含了所有可用的环境变量。每个元素都是指向一个字符串的指针,该字符串的形式是“NAME=VALUE”。因此,environ实际上是指向这些指针的指针(即二级指针),方便程序访问各个环境变量。
为了高效地操作特定环境变量,建议使用getenv函数直接获取所需值。相比之下,遍历整个environ数组查找目标环境变量可能效率较低且代码较为复杂。
理解环境变量与本地变量
1. 环境变量的全局性:如前所述,每个新创建的进程都会继承其父进程的所有环境变量。这一特性保证了程序在不同上下文中的行为一致性。
2. 本地变量的特点:当我们在命令行中定义一个未导出的变量(例如i=10),它被视为本地变量,仅限于当前shell会话使用,并不会被传递给子进程。要查看这些本地变量,可以使用set命令。
两个常见的本地变量是PS1和PS2,它们分别控制着命令行提示符的格式以及多行输入时的续行符样式。
环境变量与本地变量的主要区别在于继承性:前者会被传递给子进程,而后者仅在当前shell内部有效。若要将一个本地变量提升至环境变量级别,可使用export命令;反之,取消环境变量则可通过unset实现。
值得注意的是,尽管通常认为子进程不能修改父进程的环境变量(因为各自拥有独立的内存空间),但通过执行如export这样的内置命令时,实际上是由shell自身完成操作而非真正创建了一个新的子进程。因此,在这种特殊情况下,“子进程”能够更新其“父进程”的环境变量。



雷达卡


京公网安备 11010802022788号







