目录
[2.1 getenv](#2.1 getenv)
[2.3 全局变量environ](#2.3 全局变量environ)
前言
在前面我们学习了进程与命令行参数,了解到了指令的本质就是可执行程序,选项就是通过main函数参数argv来获取并处理的。但是系统的一些mkdir/ls/rm/pwd等指令,是不需要添加 ./ 来执行的,而我们自己写的程序需要添加 ./ 来指定路径执行(系统找不到)。
其实这都跟环境变量有关系,./ 的目的是从当前文件夹中去寻找程序。设置了环境变量后,系统就知道了程序的路径,会去你设置的路径里面寻找,如果存在,就开始运行了。
一、环境变量
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但 是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找
想要执行一个程序,需要先找到这个程序的路径,系统的 ls/rm 等指令,可以不带路径直接执行,系统一定是有自己的默认搜索路径去找到这些可执行程序。环境变量会记录这些搜索路径,方便系统查找,包含搜索路径的环境变量我们称作 PATH。
我们可以通过如下指令查询系统的PATH环境变量
bash
echo $PATH
![](https://file.jishuzhan.net/article/1759914723769323522/adb09f5b53e6a7073b152c8190c93b4b.webp)
这里我们可以看到,图片中有很多**":"符号 ,这是用来分割路径的,有4个":"**证明有五个路径。linux的指令都在这些路径下,因此就可以直接运行。
二、添加PATH环境变量
我们自己写的代码如果想不指定路径,也需要将他放到PATH路径下才可以直接运行。如下这段代码。
![](https://file.jishuzhan.net/article/1759914723769323522/930bc85db264b09b13766af5293c58ae.webp)
我们想要执行需要再可执行程序前面加上指定路径。否则系统找不到会执行失败
![](https://file.jishuzhan.net/article/1759914723769323522/20d97218c09da0592e5c0f791dfcad80.webp)
这里我们可以直接给PATH赋值为我们的路径。
![](https://file.jishuzhan.net/article/1759914723769323522/17154758d329180b93095f0a3c574d38.webp)
这样就可以直接运行了,但是又会让我们之前的环境变量消失,因此最好使用如下代码
PATH=$PATH:/home/kky/centos_test/109/240207_envir
/home以及后面的内容是我自己的路径,你需要设置为你自己的。
![](https://file.jishuzhan.net/article/1759914723769323522/f337aa60a8a0d796748378450f1a9e85.webp)
我们也可以将可执行程序拷贝到已经存在PATH路径下,这个过程叫做程序安装,这也是可以的。
![](https://file.jishuzhan.net/article/1759914723769323522/aeb895be155aedda37f157804c9d0914.webp)
需要注意更改环境变量,只限于本次登录,重新登录,环境变量会自动恢复。
三、HOME环境变量
在我们登录linux的时候可以看到,进入时默认都是root身份,root身份的家目录为/root,而切换普通用户家目录为/home/用户id
![](https://file.jishuzhan.net/article/1759914723769323522/c1712b0ae54533725c572f41c59990d1.webp)
这是因为登录的时候会形成环境变量,不同的用户环境变量可能会不同
![](https://file.jishuzhan.net/article/1759914723769323522/d9387e31aff27088b70b4ef2d7eb18a3.webp)
四、查看所有环境变量
1.指令获取
输入指令env可以只看所有环境变量
bash
env
这里面有很多信息,比如HOSTNAME主机名字,SHELL外壳,HISISIZE历史命令条数,USER使用者等等
![](https://file.jishuzhan.net/article/1759914723769323522/bd4cc7eede746320ce283a7752cec1fc.webp)
不同的用户环境变量也可能不一样
系统会存在大量的环境变量,每一个环境变量都有他自己的特殊用途,用来完成特定的系统功能。
2.代码获取
2.1 getenv
我们也可以使用C语言的getenv参数来获取环境变量,如下就是一种例子,判断必须是root用户才可以继续执行,否则就报错非法用户并退出。
![](https://file.jishuzhan.net/article/1759914723769323522/865b3772936040bd63941921036a0ded.webp)
运行结果如下
![](https://file.jishuzhan.net/article/1759914723769323522/ffb2ece61c6aedf60e1eef7cca608a55.webp)
2.2main函数的第三个参数
在之前学的命令行参数,我们了解到main函数前两个参数int argc 和 char* argv[],今天重点学习第三个参数char* env[],其实这第三个参数本质就是环境变量,他将环境变量当做字符串放入这里。
![](https://file.jishuzhan.net/article/1759914723769323522/a1a365ee67c7a3c75d53b92d69eb613b.webp)
我们可以将env里面的字符串打印出来看一下。
![](https://file.jishuzhan.net/article/1759914723769323522/5ad3105c6ca08086043d53e0f0061910.webp)
我们可以看到打印出的内容就是输入env指令看到的那些内容,main函数是如何获取到系统的环境变量的呢?
命令行启动的进程都是shell/bash的子进程,这是我们之前将进程和进程fork中提到过的,子进程的命令行参数和环境变量,是父进程bash给我们传递的。
2.3 全局变量environ
在头文件unistd.h中,有一个外置的二级指针environ变量,他指向着bash的环境变量表。
![](https://file.jishuzhan.net/article/1759914723769323522/56276cf0bbd0d84b38629215c116e571.webp)
可以通过environ获取到系统环境变量,代码如下
![](https://file.jishuzhan.net/article/1759914723769323522/ef8614fe58a36e955c2bf220ba9583ff.webp)
make后运行
![](https://file.jishuzhan.net/article/1759914723769323522/9b7adb9f594b3810d51abc7d858b94a5.webp)
五、环境变量存放地点
在之前,我们还更改过环境变量,但是你可以发现,你更改环境变量后会立即生效,但是当你重启bash环境变量又会自动恢复,这是因为你修改的是内存中的环境变量,而环境变量是写到了磁盘的,每一次重新登录,都会给我形成新的bash解释器并且新的bash解释器会自动从磁盘中读取形成自己的环境变量表信息。
当我们进入家目录,输入ls-al指令,可以看到由一个文件叫做.bash_profile,这是bash配置文件,bash在启动的时候会自动读取该文件里面的内容并执行。
![](https://file.jishuzhan.net/article/1759914723769323522/cbfce8cb018fbd6ad81762d83655dac3.webp)
打开该文件里的内容可以看到PATH路径,同时在前面他还会执行~/.bashrc
![](https://file.jishuzhan.net/article/1759914723769323522/6e0f0fb16884bf6a30643d1404a437be.webp)
我们再打开~/.bashrc,这也是在上面图片中的文件。同时他也包含了另一个文件,就这样一直读取这些文件里面的内容,bash就可以将环境变量给配置好。
![](https://file.jishuzhan.net/article/1759914723769323522/32178330a29dbb5a1ad42b84d3a6a68d.webp)
现在我们应该理解了每一次登录,bash都会读取.bash_profile配置文件中的内容,为bash形成一张环境变量表信息。只要我们没有改过该配置文件,在命令行中修改一些环境变量,重启后都会恢复原样。
六、添加自命名环境变量
在命令行中,我们可以直接定义变量,如下,就定义了一个MYENV_TEST变量,内容为hellolinux。
bash
MYENV_TEST=hellolinux
但此时环境变量里是没有该变量的,我们需要通过export进行导入。
![](https://file.jishuzhan.net/article/1759914723769323522/92fb31bb4b5eb46a26f171688ae78673.webp)
我们重新启动shell后,我们之前设置的环境变量依然不存在,要想使他重启后仍然存在,需要将该命令写到对应的文件去,shell启动会自动读取文件里的内容进行配置。
依然是.bash_profile文件里,添加如下红线代码,这样重启后就存在该环境变量了。
![](https://file.jishuzhan.net/article/1759914723769323522/a73c6febf9973bcaf1b70922d0581a17.webp)
七、系统环境变量具有全局属性
在之前,我们通过指令env获取了环境变量,我们还通过代码利用进程的方式获取到了环境变量,我们知道该进程的父进程是bash,因此该进程可以继承bash的环境变量表,并打印出来,那么该进程fork的子进程呢?是否也能打印出来环境变量。
代码如下
![](https://file.jishuzhan.net/article/1759914723769323522/1c7094e32a48e06cad9ff9d3b45e6422.webp)
依然能运行。
![](https://file.jishuzhan.net/article/1759914723769323522/e33f8b3a81a7c7c933962c7b8a8564d6.webp)
这个结果证明系统环境变量具有全局属性。进程都可以继承系统环境变量。
八、环境变量与本地变量
bash中也可以赋值,在命令行中随意输入变量名赋值给某个值或者变量,这些变量统称为本地变量。
![](https://file.jishuzhan.net/article/1759914723769323522/3b08f6650f33555c43fa99a5060f7052.webp)
但本地变量只在bash进程内部有效,不会被子进程继承下去,而环境变量通过让所有的子进程继承的方式,实现环境变量的全局属性。
那么现在问题来了,echo不算进程吗,我们定义的abc本地变量,说好的不会被子进程继承,怎么echo可以打印呢?
这是因为linux大部分命令是在磁盘中真正存在的,需要由bash fork出子进程来执行的,比如ls top mkdir touch env等等。
但是有小部分命令为内建命令,比如echo export等,他们是内建命令,他是bash命令行的一个函数,当然可以直接读取bash内部定义的本地变量。
九、环境变量相关的命令
- echo: 显示某个环境变量值
2.export: 设置一个新的环境变量
3.env: 显示所有环境变量
4.unset: 清除环境变量
5.set: 显示本地定义的shell变量和环境变量