环境变量
1、基本概念
环境变量是操作系统用来存储和传递关于系统环境信息的一种机制 ,它相当于一种全局变量,可供系统中的各个程序、进程在运行时访问和使用,这些信息包括系统的配置参数、文件路径、用户设置等,程序可以根据这些环境变量的值来确定如何运行,例如在哪里查找文件、使用什么语言设置、分配多少内存等
2、常见环境变量
PATH:指定命令的搜索路径
HOME:指定用户的主工作目录
SHELL:当前使用的shell名称
通过echo $NAME
指令可以查看当前系统环境变量,NAME是环境变量的名称
![](https://i-blog.csdnimg.cn/direct/2a2e1daf95d145c4b0ac51fc182b0ffd.png)
3、相关指令
指令 | 作用 |
---|---|
echo | 显示某个环境变量值 |
export | 设置一个新的环境变量 |
env | 显示所有环境变量 |
unset | 清除环境变量 |
set | 显示本地定义的shell变量和环境变量 |
4、PATH的相关概念
创建一个hello world的c文档,生成可执行文件,我们输入两条指令,分别是直接写process和./process,我们发现./process能执行文件
我们在《打破Linux神秘的面纱》一文中提到过,process的写法是指令写法,而指令就是存储在bin目录下的可执行程序,我们可以通过root账户将可执行程序移动到bin目录下,就可以形成人造指令,在《从软件到硬件了解进程》一文中提到过./是定位目录,因为进程属性有一条就是current work dir 当前工作目录(cwd),那么我们可以得出一个结论,指令的进程属性中的cwd指向的就是bin目录,而我在这里又会提供一个结论:环境变量PATH中的分隔符是: ,分隔符两边的是目录,而且都是bin目录,PATH当中的文件不需要定位目录就可以执行
那么我们通过指令export PATH=$PATH:程序所在目录
对环境变量进行增加,我们就可以直接process执行程序了,这个是一个临时的改变,在我们重启Shell软件后就恢复如初了,要想永久改变,我们可以做以下步骤:
第一种:编辑/etc/profile文件(对所有用户生效):
①打开终端,使用文本编辑器(如vim或nano)编辑/etc/profile文件,以vim为例,在终端输入sudo vi /etc/profile
②在文件末尾添加export PATH=$PATH:新路径
,例如export PATH=$PATH:/home/user/mybin
,保存并退出编辑器
③在终端执行source /etc/profile使设置立即生效
第二种:编辑用户主目录下的.bashrc文件(仅对当前用户生效):
①打开终端,使用文本编辑器编辑.bashrc文件,如vi ~/.bashrc
②在文件末尾添加export PATH=$PATH:新路径
,保存并退出编辑器
③执行source ~/.bashrc使设置立即生效
5、环境变量的组织方式
环境表:每个程序运行时都会收到一张环境表,它是一个字符指针数组,数组中的每个指针都指向一个以'\0'结尾的环境字符串
environ 变量:environ是一个char**类型的全局外部变量,指向环境变量表,它没有包含在任何头文件中,在代码中使用时需要用extern声明,如extern char **environ;
,通过它可以第三方形式获取所有环境变量
getenv 函数:char *getenv(const char *name)函数可通过指定的环境变量名称来获取其对应的值,该函数包含在头文件<stdlib.h>中,比如获取PATH环境变量的值就用char*s = getenv("PATH");
6、通过代码获取环境变量
(一)命令行第三个参数
我们要学习通过命令行第三个参数获取环境变量就要先了解main函数的三个参数,我们在之前使用main函数的时候一般都是如下所示
c
int main(void)
{
//...
return 0;
}
其实main函数一共最多是有三个参数的,如下所示
c
int main(int argc, char *argv[], char *envp[])
{
//...
return 0;
}
其中argc是命令行参数的数量 ,argv是一个指向命令行参数字符串的指针数组,用于存储命令行参数 ,envp是一个指向环境变量字符串的指针数组 ,用于传递程序运行时的环境信息
在我们程序当中,我们可以通过strcmp的方式来进行选项的应用,如果我们想要-a选项的效果是打印hello world,-b选项的效果是打印hello linux,我们可以这样写
c
for(int i = 0; i < argc; i++)
{
if(strcmp(argc[i],"-a") == 0)
{
printf("hello world");
}
if(strcmp(argc[i],"-b") == 0)
{
printf("hello linux");
}
//...
else
{
printf("wrong!!!");
}
}
通过envp打印环境变量
(二)第三方变量environ
environ是一个库中定义的全局变量,指向环境变量表,没有包含在任何头文件中,所以在使用的时候要用extern声明
7、环境变量全局性的验证
c
int setenv(const char *name, const char *value, int overwrite);
//name:这是一个指向字符串的指针,代表你要设置的环境变量的名称
//value:同样是一个指向字符串的指针,表示你要赋给环境变量的值
//overwrite:这是一个整数类型的参数,用于控制是否覆盖已存在的同名环境变量
//若为0,当环境变量已经存在时,不会对其进行修改,不存在时创建并设置它
//若为非0,无论该环境变量是否已经存在,都要将其值更新为value
![](https://i-blog.csdnimg.cn/direct/958f0f82a1524613a8b560b302a25646.png)
这个程序如果父子进程都打印出TEST_VARIABLE: test_value那么就说明子进程可以继承父进程的环境变量
以上我们所运行的进程,都是bash的子进程(bash就是命令行解释器,所有我们所创建的进程的父进程或祖宗进程),bash本身在启动的时候,会从操作系统的配置文件中读取环境变量信息,子进程会继承父进程交给我们的环境变量
8、本地变量
和环境变量不同,本地变量只在本bash内部有效,不会被继承,通过MYENV="内容"
定义本地变量名和内容,在子进程中不可被访问
我们知道我们在命令行(bash)中所创建的进程都是命令行(bash)的子进程,所以我们的本地变量是没办法在这种进程中显示的,只有将它export进环境变量,才可以被命令行子进程访问
9、内建命令
Linux中命令分为普通命令和内建命令,普通命令是要通过bash创建子进程完成的,而内建命令bash自己亲自执行,bash不创建子进程,相当于bash调用自己内部的函数
常见的内建命令有echo,cd等
若echo是外部命令,那么在输出本地变量SUPER值的时候是访问不到的,因为echo会产生一个子进程,命令行子进程访问不到本地变量,不符合用户使用需求
若 cd 是外部命令,在执行时,Shell 会创建一个子进程来运行它,子进程拥有独立的环境和工作目录,当子进程修改工作目录时,这种修改仅局限于子进程自身,并不会对父进程(即当前的 Shell 进程)的工作目录产生影响,也就是说,执行完外部的 cd 命令后,当前 Shell 的工作目录不会发生改变,这显然不符合用户的使用需求,所以我们有了内建命令这样的进程执行命令,专门处理这类问题
今日分享就到这里了~