Linux环境变量

文章目录

        • Linux环境变量
          • 基本概念
          • 常见环境变量
          • 查看环境变量的方法
          • 测试PATH
          • 测试Home
          • 测试SHELL
          • 与环境变量相关的命令
          • 环境变量的组织方式
          • 通过代码获取环境变量
          • 通过系统调用获取环境变量
          • 环境变量通常是具有全局属性的

Linux环境变量

基本概念

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。

比如说:

  • 我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序, 原因就是有相关环境变量帮助编译器进行查找。
  • 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性
常见环境变量
  • PATH:指定命令的搜索路径
  • HOME:指定用户的祝工作目录(即用户登录到Linux系统中时,默认的目录)
  • SHELL:当前Shell,它的值通常是/bin/bash
查看环境变量的方法

我们可以使用echo命令来查看环境变量,方法如下:

echo $NAME //NAME:你的环境变量名称

下面我们使用echo命令来试一下吧

查看PATH环境变量:

[root@izuf65cq8kmghsipojlfvpz ~]# echo $PATH

Linux环境变量_第1张图片

测试PATH

我们之前说过在Linux下一切皆文件,因此Linux下的这些命令、程序、工具本质都是一个可以执行的文件。

Linux环境变量_第2张图片

那么问题来了:

为什么我们这里执行我们自己生成的proc这个可执行文件的时候必须在前面要加上./才能够跑,但是执行ls、pwd这些系统指令的时候不带./却可以跑呢?

这个问题其实很好回答:

我们想要执行一个可执行程序,那么我们第一步就必须得找到它在哪里,然后再去执行它。因为系统不知道proc这个文件在哪,加上./是为了帮助系统找到proc这个可执行程序的。

那么问题又来了:

既然你说要执行一个可执行程序必须得先找到它,我们这里加上./是为了帮助系统找到proc,那么为何系统的命令不用带路径呢?

其实系统的命令也带了路径的,系统它是通过环境变量PATH去找到pwd、ls这些系统命令的,我们通过echo命令来查看一下环境变量PATH一起看一下吧:

Linux环境变量_第3张图片

我们可以看到环境变量PATH中有多条路径,这些路径以冒号作为分隔符隔开,当我们使用pwd或者ls命令的时候,系统就会依次在环境变量PATH的这些路径中进行查找。

如果某条系统命令在这些路径中找到了就会停止查找,然后执行这条命令。

我们可以通过which指令查看一下ls命令是在哪里的:

Linux环境变量_第4张图片

可以看到ls命令其实是在环境变量PATH的其中一条路径下的。

明白了上面的那些问题之后,我现在又有了一个小问题,那既然系统指令可以不用加./就可以执行,那我们自己生成的可执行程序可不可以这样呢?

答案是可以的,下面我教大家两种方法。

方法一:将你自己生成的可执行程序拷贝到环境变量PATH的某一路径下。

我们知道在未指定路径的情况下操作系统会根据环境变量PATH里面的路径去查找,那么我们可以将我们可执行程序拷贝到PATH里面的其中一条路径下,后面我们执行该可执行程序的时候就不用再带./了

[root@izuf65cq8kmghsipojlfvpz ~]# cp proc /usr/bin

在这里插入图片描述

方法二:将可执行程序所在的目录导入到环境变量PATH中

[root@izuf65cq8kmghsipojlfvpz ~]# export PATH=$PATH:/root

先给大家看一个错误示范:

Linux环境变量_第5张图片

我们将可执行程序所在目录导入环境变量PATH的时候,最好不要这样去导入,这样去导入的话覆盖掉环境变量PATH里面的路径,导致你执行不了系统指令,但是遇到这种情况也不要慌张。因为我们并不是改了环境变量的配置,因此我们只需要重新启动一下Xshell,环境变量就会恢复到原来的样子。

正确做法:

Linux环境变量_第6张图片

我们将可执行程序的所在目录导入到环境变量PATH后,我们再去执行这个可执行程序的时候就可以像执行系统命令那样直接去执行而不用带./了。

Linux环境变量_第7张图片

测试Home

在之前讲Linux指令的时候,我们说过cd~命令可以进入到当前用户的工作目录,并且每个用户的工作目录是不一样的。那么问题来了操作系统它是怎么知道每个用户的工作目录是在哪的呢?

因为每个用户的环境变量HOME是不同的,操作系统通过环境变量HOME来保存该用户的工作目录

普通用户:

Linux环境变量_第8张图片

超级用户:

Linux环境变量_第9张图片

测试SHELL

我们平常使用的时候可能会用到各种Shell,我们可以通过查看环境变量SHELL来知道当前所用的命令行解释器的种类。

Linux环境变量_第10张图片

我们上面说了一些环境变量,那么问题来了:

我们应该如何去理解环境变量呢?

在语言上面定义变量的本质是在内存中开辟空间(有名字),我们不要去质疑OS开辟空间的能力!!!

环境变量的本质是OS在内存/磁盘文件中开辟的空间,用来保存系统相关的数据,环境变量是具有全局属性的。

系统上还存在着一种变量,它是与本次登录(session)有关的变量,只在本次登录有效(本地变量)

与环境变量相关的命令
  1. echo:显示某个环境变量的值

Linux环境变量_第11张图片

  1. export:设置一个新的环境变量

Linux环境变量_第12张图片

  1. env:显示所有环境变量

Linux环境变量_第13张图片

  1. unset:清除环境变量

Linux环境变量_第14张图片

  1. set:显示本地定义的shell变量和环境变量

Linux环境变量_第15张图片

Linux环境变量_第16张图片

环境变量的组织方式

在操作系统当中,环境变量的组织方式是这样的:

Linux环境变量_第17张图片

系统下的每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串。

通过代码获取环境变量

你觉得main函数可以带参数吗?如果可以带参数的话那能带几个呢?

我想大部分人可能都会觉得main是可以带参数的,并且只可以带一个,因为大家可能只见过这个:main(void)

其实我们的main函数是可以带参数,并且它是有三个参数的,因为我们平时基本上都不怎么用他们,所以我们并没有将这三个参数给写出来。

main函数是有这三个参数的:

main(argc,argv,envp);

main函数的前两个参数我们通常称之为命令行参数

我们先来看一下main函数的前两个参数

我们在Linux系统下,编写以下代码,生成可执行程序并执行它。

Linux环境变量_第18张图片

执行结果:

Linux环境变量_第19张图片

看到了执行结果之后我们来讲一下前两个参数吧

第二个参数argv我们上面说过它是一个字符指针数组,我们将可执行程序以及它后面的选项都看作是字符串,argv的第一个字符指针存放的是可执行程序,后面几个字符指针存放的是可执行程序后面的选项,最后一个字符指针存放的是NULL。

第一个参数argc它决定了字符指针数组里面有几个有效的命令行字符串。

Linux环境变量_第20张图片

我们知道我们可以通过调用系统指令+不同的选项实现不同的子功能,那么这里我们同样可以通过main函数的几个参数来根据你所给的选项不同,从而打印不同的结果或者实现不同的功能。

下面我们来看一段代码:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4 
  5 int main(int argc,char* argv[])
  6 {
  7   if(argc!=2)
  8   {
  9     printf("Usage: ./proc -[a|b]\n");                                                                               
 10     return 1;
 11   }
 12 
 13   if(strcmp(argv[1],"-a")==0)
 14   {
 15     printf("hello mlf\n");
 16   }
 17   else if(strcmp(argv[1],"-b")==0)
 18   {
 19     printf("hello nihao\n");
 20   }
 21   else
 22   {
 23     printf("hello world\n");
 24   }
 25 
 26   return 0;
 27 }

运行结果:

Linux环境变量_第21张图片

总结:

指令有很多选项,用来完成同一个命令的不同子功能,选项的底层使用的就是我们的命令行参数!!!

main函数除了可以传递命令行参数它还可以传递env,main函数的第三个参数接收的就是我们上面说的环境变量表,我们可以通过main函数的第三个参数来获得系统的环境变量。

下面我们来看一段代码:

Linux环境变量_第22张图片

运行结果:

Linux环境变量_第23张图片

大家对于这个运行结果是不是有点眼熟呢?

没错,这里的运行结果其实就是输入env指令打印出来的各个环境变量的值。

我们这里除了使用main函数的第三个参数获取环境变量外,我们还可以通过第三方变量environ来获取

Linux环境变量_第24张图片

我们来运行一下可执行程序,查看一下运行结果:

Linux环境变量_第25张图片

注意: libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明。

通过系统调用获取环境变量

除了上面两种获取环境变量的方式外,我们还可以通过调用getenv函数来获取环境变量,这也是我们最常用的一种方式。

getenv函数可以根据所给的环境变量名,在环境变量表中进行搜索,从而找到对应的环境变量拿出后面的内容。

下面我们来看一段代码:

Linux环境变量_第26张图片

运行结果:

Linux环境变量_第27张图片

环境变量通常是具有全局属性的
  • 环境变量通常是具有全局属性的,可以被子进程继承下去

下面我们来看一段代码:

Linux环境变量_第28张图片

Linux环境变量_第29张图片

运行结果:

Linux环境变量_第30张图片

可以看到我们执行这个可执行程序之后,什么都没有打印,这是因为我们的MYString还只是一个本地变量,并不是一个环境变量,它只能够父进程自己去用。

下面我们让父进程bash通过export指令,将MYString变成环境变量再来看一下吧

Linux环境变量_第31张图片

可以看到再次运行刚刚的可执行程序后,会打印出我们想要的结果,这是为什么呢?

这是因为子进程继承了父进程bash的环境变量。

总结:环境变量具有全局属性,本质是环境变量可以被子进程继承下去。环境变量影响了整个用户系统。

你可能感兴趣的:(Linux,linux)