目录
[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
这里我们可以看到,图片中有很多**":"符号 ,这是用来分割路径的,有4个":"**证明有五个路径。linux的指令都在这些路径下,因此就可以直接运行。
二、添加PATH环境变量
我们自己写的代码如果想不指定路径,也需要将他放到PATH路径下才可以直接运行。如下这段代码。
我们想要执行需要再可执行程序前面加上指定路径。否则系统找不到会执行失败
这里我们可以直接给PATH赋值为我们的路径。
这样就可以直接运行了,但是又会让我们之前的环境变量消失,因此最好使用如下代码
PATH=$PATH:/home/kky/centos_test/109/240207_envir
/home以及后面的内容是我自己的路径,你需要设置为你自己的。
我们也可以将可执行程序拷贝到已经存在PATH路径下,这个过程叫做程序安装,这也是可以的。
需要注意更改环境变量,只限于本次登录,重新登录,环境变量会自动恢复。
三、HOME环境变量
在我们登录linux的时候可以看到,进入时默认都是root身份,root身份的家目录为/root,而切换普通用户家目录为/home/用户id
这是因为登录的时候会形成环境变量,不同的用户环境变量可能会不同
四、查看所有环境变量
1.指令获取
输入指令env可以只看所有环境变量
bash
env
这里面有很多信息,比如HOSTNAME主机名字,SHELL外壳,HISISIZE历史命令条数,USER使用者等等
不同的用户环境变量也可能不一样
系统会存在大量的环境变量,每一个环境变量都有他自己的特殊用途,用来完成特定的系统功能。
2.代码获取
2.1 getenv
我们也可以使用C语言的getenv参数来获取环境变量,如下就是一种例子,判断必须是root用户才可以继续执行,否则就报错非法用户并退出。
运行结果如下
2.2main函数的第三个参数
在之前学的命令行参数,我们了解到main函数前两个参数int argc 和 char* argv[],今天重点学习第三个参数char* env[],其实这第三个参数本质就是环境变量,他将环境变量当做字符串放入这里。
我们可以将env里面的字符串打印出来看一下。
我们可以看到打印出的内容就是输入env指令看到的那些内容,main函数是如何获取到系统的环境变量的呢?
命令行启动的进程都是shell/bash的子进程,这是我们之前将进程和进程fork中提到过的,子进程的命令行参数和环境变量,是父进程bash给我们传递的。
2.3 全局变量environ
在头文件unistd.h中,有一个外置的二级指针environ变量,他指向着bash的环境变量表。
可以通过environ获取到系统环境变量,代码如下
make后运行
五、环境变量存放地点
在之前,我们还更改过环境变量,但是你可以发现,你更改环境变量后会立即生效,但是当你重启bash环境变量又会自动恢复,这是因为你修改的是内存中的环境变量,而环境变量是写到了磁盘的,每一次重新登录,都会给我形成新的bash解释器并且新的bash解释器会自动从磁盘中读取形成自己的环境变量表信息。
当我们进入家目录,输入ls-al指令,可以看到由一个文件叫做.bash_profile,这是bash配置文件,bash在启动的时候会自动读取该文件里面的内容并执行。
打开该文件里的内容可以看到PATH路径,同时在前面他还会执行~/.bashrc
我们再打开~/.bashrc,这也是在上面图片中的文件。同时他也包含了另一个文件,就这样一直读取这些文件里面的内容,bash就可以将环境变量给配置好。
现在我们应该理解了每一次登录,bash都会读取.bash_profile配置文件中的内容,为bash形成一张环境变量表信息。只要我们没有改过该配置文件,在命令行中修改一些环境变量,重启后都会恢复原样。
六、添加自命名环境变量
在命令行中,我们可以直接定义变量,如下,就定义了一个MYENV_TEST变量,内容为hellolinux。
bash
MYENV_TEST=hellolinux
但此时环境变量里是没有该变量的,我们需要通过export进行导入。
我们重新启动shell后,我们之前设置的环境变量依然不存在,要想使他重启后仍然存在,需要将该命令写到对应的文件去,shell启动会自动读取文件里的内容进行配置。
依然是.bash_profile文件里,添加如下红线代码,这样重启后就存在该环境变量了。
七、系统环境变量具有全局属性
在之前,我们通过指令env获取了环境变量,我们还通过代码利用进程的方式获取到了环境变量,我们知道该进程的父进程是bash,因此该进程可以继承bash的环境变量表,并打印出来,那么该进程fork的子进程呢?是否也能打印出来环境变量。
代码如下
依然能运行。
这个结果证明系统环境变量具有全局属性。进程都可以继承系统环境变量。
八、环境变量与本地变量
bash中也可以赋值,在命令行中随意输入变量名赋值给某个值或者变量,这些变量统称为本地变量。
但本地变量只在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变量和环境变量