【LINUX】环境变量

1.💡环境变量概念

2.💡一个例子,一个环境变量

3.💡认识更多的环境变量

4.💡获取环境变量的方法

5.💡理解环境变量的特性


1.环境变量概念

环境变量一般指的是操作系统运行环境的一些参数

比如说,我们C/C++编译完要链接各种库的话,尽管我们并不知道这些库的位置,我们依然可以完成库的链接,这就是环境变量给你完成的

2.一个例子,一个环境变量

开始之前,我们先理解一个东西

深得理解一下命令行参数

在我们的main函数其实是有两个参数的

一个是int argc,一个是char* argv[]

比如我们的code是编译完的可执行程序的话,我们./code就是执行这个命令,如果我们后面加了-a -b -c这样的选项的话,就能完成各种子功能

./code -a/-b/-c

比如上面这行命令,bash会把它分成两个字符串,形成一个表,传递给可执行函数的main函数里

我们可以写代码示范一下

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc,char* argv[])
{
  for(int i = 0;i<argc;i++)
   {
      printf("argv=%s\n",argv[i]);

   }

   return 0;
}

证明完毕

我们再写一个代码,要求必须带-a 或者 -b -c的选项,如果没带就提示要带选项,如果带了就表明是功能几

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
int main(int argc,char* argv[])
{
   if(argc !=2)
   {
     printf("Usage %s : [-a/-b/-c]\n",argv[0]);
     return 1;
   }
  const char* arg = argv[1];
  if(strcmp(arg,"-a")==0)
    {
     printf("这是功能1\n");
    }
   else if(strcmp(arg,"-b")==0)
    {
     printf("这是功能2\n");
    }
   else if(strcmp(arg,"-c")==0)
    {
      printf("这是功能3\n");
    }
   else
   {
     printf("Usage %s :  [-a/-b/-c]",argv[0]);
   }


   return 0;
}

main主函数的两个参数,是实现程序不同子功能的方法

下面就来说环境变量,

我们说到,linux的命令都是C语言写的,都在/usr/bin里

我们的二进制程序一般都是在当前目录下./code这样执行,那我们常用的ls cat 之类的bash命令为什么就能不加路径直接执行呢?

这就是环境变量了,系统里有环境变量来帮助bash找到对应的命令的位置

如果我们把我们自己的程序也拷贝到/usr/bin里,那我们也不需要路径直接就能运行了

如图所示,果然如此

/usr/bin是在环境变量里的,这个环境变量就叫PATH 存放着系统中搜索指令的默认搜索路径

我们env可以查看所有环境变量

可以找到这就是PATH路径

我们也可以直接

echo $PATH

那我们直接把我们自己二进制程序的路径加到PATH里,是不是也可以直接执行我们的二进制程序了

PATH=你的二进制程序路径

但是这样的话

我们其他命令就没法执行了,坏了,这是因为啥呢

我们这种PATH=路径,是直接覆盖上去了

我们怎么恢复呢?我们可以找到之前的PATH路径,重新PATH=,覆盖回去

我们也可以重启bash,bash会自动从配置文件里重新加载环境变量

我们正确不覆盖的方法是

 PATH=$PATH:要添加的路径

那,我们从存储的角度理解一下环境变量吧

我们启动bash的时候,bash会用一个表(char*数组)来存储每个环境变量和它的所有路径

同时当我们在bash输入命令的时候,也会形成一个命令行的表

当我们输入命令的时候,比如ls,我们的bash会从PATH所有路径里找这个叫ls的二进制程序,找到了就执行,找不到就command not found

环境变量最开始是从配置文件里来的

,bash_profile从.bashrc里找PATH,.bashrc从/etc/.bashrc里找PATH

如下图就是.bashrc

如果我们对PATH加路径的话,只是这一次,下次重新登录还会恢复到之前的,如果我们想永久更改PATH路径,就要改配置文件

我们在bash_profile这个配置文件里添加路径,下次bash再登录的时候就会把这个路径也加载上,就能找到我们该路径的二进制程序了

如果有十个用户登录,那就有十个bash进程,每个bash进程都会加载一份环境变量

我们windows上也有PATH环境变量

在.bash_profile里把要添加的路径加上去

然后

source ~/.bash_profile

然后就能执行该路径的可执行程序了,并且重新登录也不会变

3.认识更多的环境变量

1°HOME

该环境变量存储的就是当前用户的家目录

然后介绍俩命令

who是查看登录的用户是谁

whoami是查看当前使用终端的用户

我们cd ~ 这个~就是从HOME环境变量里找的家目录路径

2°SHELL

SHELL变量记录的是启动终端的默认SHELL路径

3°USER & LOGNAME

LOGNAME和USER大部分情况下都是一致的,登录的时候自动就会填上登录的用户名

假如我们用自己的用户登录,然后su转成超级用户的时候

只是切换了使用终端的用户,并没有重新登录,USER和LOGNAME是不变的

如图所示,而当我们su -的话就表示重新登录

退出登录的时候则会切换回去

3°HISTSIZE

该环境变量表示bash里存储的之前用过的命令最多的条数

我们上下键找历史命令就和它有关

我们bash里应该会把历史命令用队列存起来

4°HOSTNAME

标识主机的名字

5°PWD & OLDPWD

该环境变量是存储的是当前路径

OLDPWD是存储上一个路径

有了oldpwd,我们就可以快速回到上一个目录

这个命令叫

cd -

4.获取环境变量的方法

1°操作

我们先谈操作

我们前面已经学了

env

查看所有环境变量

echo $XXXX

查找某一个环境变量的内容

export MYENV=112233444

这个表示增加一个MYENV的环境变量

unset XXX

取消某个环境变量

ok操作我们学了,我们接下来再在代码里学一下怎么获取环境变量

首先,我们要知道 main函数有参数吗?如果有,最多有几个?

答案是有,最多有三个

分别是 int argc,char*argv,char* env

也就是说第三个参数就是bash的环境变量的表

我们试着用一下这个env(这三个参数都是父进程bash传给子进程的)

#include <stdio.h>
#include <stdio.h>

int main(int argc,char *argv[],char* env[])
{
  for(int i = 0;env[i];i++)
  {
    printf("env[%d]-> %s\n",i,env[i]);
  }
}

这样果然就能打印出我们的环境变量列表了

那我们的代码编译的时候,是怎么知道main函数的参数的呢

实际上啊,我们代码编译的时候,不是直接就调用main函数了的

而是操作系统会把一些变量加载到_start,_start是真正的入口

_start再进行调用main函数的操作

大概就是这样

_start
{
   int ret = 0;
   int arg_count = 0;
   arg_count = 3;
   if(arg_count == 0)
    ret = main();
   else if(arg_count == 1)
    ret = main(argc);
   else if(arg_count ==2)
    ret = main(argc,argv[]);
   else
    ret = main(argc,argv[],env[]);


}

至此,我们第一个用代码获取环境变量的方法有了

即(1).main函数的env参数 ,即父进程bash的env列表

当然。父进程的环境变量是可以被子进程继承的,如果bash环境变量进行了修改,子进程的环境变量会和bash的环境变量列表一样

我们试一下

再执行我们程序

环境变量为什么能被继承呢?因为环境变量是有全局性的呀

那么接下来我们再学一个系统调用接口吧

它叫做getenv()

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     int main(int argc,char* argv[],char *env[])
     {
       char *value = getenv("PATH");
       if(value == NULL) return 1;
       printf("PATH->%s\n",value) ;                                                               
    }
  

我们可以用getenv来得到user,这样就能让一个程序只能我这个用户来执行,其他人执行不算数了

2 #include <stdlib.h>
    3 #include <string.h>
    4 
W>  5 int main(int argc,char* argv[],char *env[])
    6 {
    7   const char *who = getenv("USER");
    8   if(who==NULL) return 1;
    9   if(strcmp(who,"lbl")==0)
   10   {
   11     printf("这是程序的正确执行逻辑\n");
   12   }
   13   else
   14   {
   15     printf("ONLY LBL\n");
   }                                                                                          
    }

如上面代码,这样的话就能用环境变量确定登录的用户了,如果用户不是我,就不能执行

ok下面介绍第三种方法

environ

它就是一个全局指针,我们那个环境变量不是会在bash形成一个指针数组吗?

我们char** environ指向的就是指针数组的第一个指针

enviorn[i]就表示指针数组第i个元素,可以用百分号s打印

我们用代码实现一下

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char** environ;
int main(int argc,char* argv[])
{
   for(int i = 0;environ[i];i++)
    {
        printf("env[%d]->%s\n",i,environ[i]);
    }
}

5.理解环境变量的特性

上面三个获取环境变量的方式,都充分体现了环境变量的全局性

我们尤其再说一下第三个方法

extern char** environ;

就算是我们再开一个子进程,照样能用这个environ

不信我们就试试,充分说明了environ的全局性

   1 #include <stdio.h>
    2 #include <stdio.h>
    3 #include <unistd.h>                                                                          
W>  4 int main(int argc,char *argv[],char* env[])
    5 {
    6   if(fork()==0)
    7   {
    8   for(int i = 0;env[i];i++)
    9   {
   10     printf("env[%d]-> %s\n",i,env[i]);
   11   }
   12   }
   13 }

子进程照样可以用

补充概念

除了环境变量,我们还有本地变量

我们env是只能看环境变量而不能看本地变量的

想看到本地变量,我们必须用set

set既能查看到环境变量,也能查看到本地变量

bash会记录两套变量 1.环境变量 2.本地变量

本地变量只在bash内部用,不会继承给子进程

我们本地变量可以用作shell脚本

PS1就是我们显示在开头的

PS2就是shell显示我们续行

删除本地变量命令

unset i

同样我们也可以把本地变量直接导入到环境变量,export i即可

我们环境变量一般都在bash里,那么问题来了,如果我们export是子进程,那子进程凭什么能修改我们父进程呢?

不是说进程之间是独立的吗,其实呀,export是一个内建命令,是我们bash自己调用系统调用,而不需要创建子进程的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无敌大饺子 dot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值