【Linux】理解Linux环境变量

news2024/11/25 23:15:16

🍎作者:阿润菜菜
📖专栏:Linux系统编程


初识环境变量

什么是环境变量

我们平常所用的Linux指令其实也是可执行程序,和我们自己写的二进制程序没什么两样,那么为什么我们在执行自己的程序的时候需要加上 ./,而在我们执行系统提供的指令时(可执行程序),为什么不需要加上./ 呢?

在这里插入图片描述
其实时我们要执行一个程序或者指令,必须先找到这个程序。
所以我们在执行自己写的程序时,要加上./(当前路径),其实就是为了找到我们所写的程序,而系统指令实际上是系统默认帮我们找到其程序的位置并且执行,如果想不带./的执行自己的程序,那就需要将程序安装(安装的本质就是拷贝)到/usr/bin目录下面,也就是系统安装指令的路径当中。但我们不建议这么做,因为未知的程序可能会有污染系统指令池的风险。

所以什么是环境变量?
概念: 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
就是说,比如我们在执行C/C++代码代码时,会调用语言的库就,那在链接的时候,我们从来不知道我们所需要链接的动静态库在哪里,OS照样可以链接成功,生成可执行程序,原因就是有 相关 环境变量帮助编译器去进行查找。

添加程序路径到PATH环境变量里(像指令一样运行程序)

像是ls这样的指令程序就是在/usr/bin目录下的,那为什么在/usr/bin路径下的程序,系统就可以找到呢?其实是因为系统里面存在环境变量PATH,操作系统在启动的时候,会在shell的上下文当中定义一个PATH变量,这个变量是全局有效的,如果想要查看内容,可以利用echo $PATH命令进行查看。

查看环境变量的方法: echo $NAME //NAME:你的环境变量名称

在这里插入图片描述

在执行系统指令的时候,系统会默认去PATH环境变量里面的路径,查找我们输入的指令程序,如果找到,系统就会执行这个程序,如果没有找到就会报错command not found,如果我们想要想要像:ls、pwd、tree等命令一样使用起来不带路径的话,我么只需要将我们的可执行程序添加到PTAH中任一一条目录下或者将我们的路径追加到PATH环境变量下面;
另外我们可以任意修改PATH的值,因为只要重新退出登录,PATH环境变量就又会恢复了

我们可以用export指令来将shell变量导入到环境变量PATH里面,导入的时候需要先将老的环境变量导入进去然后在加上新的路径(追加路径),否则会出现你的路径直接覆盖掉之前环境变量PATH里面的所有路径的情况,PATH里面的路径下的所有程序都被默认为是系统指令。

PATH=$PATH:路径

在这里插入图片描述
像这样,过后我们不仅可以不带路径的使用我们追加的路径下的可执行程序,同时也不会影响ls等命令的使用。
另外我们的环境变量是内存级的,所以在你将自己的路径导入到环境变量PATH之后也只是暂时的,等你退出xshell之后,你的环境变量就又会恢复到默认的样子了
下面我们来看一些常见的环境变量:

PATH : 指定命令的搜索路径;
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)

HOME环境变量记录当前用户的工作目录在具体的哪个路径
在这里插入图片描述
cd的本质其实就是shell在解析指令时,看到了波浪号,shell就会直接调用环境变量HOME的值
SHELL : 当前Shell,它的值通常是/bin/bash
在这里插入图片描述
当然这都是一些比较常见的环境变量,我们如果想要查看所有环境变量的话,我们可以使用 命令env
在这里插入图片描述

进一步理解环境变量

环境变量的作用

无论是我们自己写的程序还是操作系统提前给我们准备好的程序,想要运行都必须先加载到内存里面,因为CPU只能从内存中读取代码和数据,但是这里有一个潜在的问题,这些程序想要运行,都必须让操作系统先找到这些程序,找到这些程序才能把他们加载到内存里面.操作系统要找这些程序就必须去特定的路径下面去找这些程序,包括系统自带的指令程序和我们自己所写的程序,操作系统还有可能找头文件,找动态库静态库等等,但是为什么你说操作系统能找到这些东西,它就能一定找到呢?操作系统是如何找到这些东西的?

其实想要找到这些东西,操作系统需要做很多的准备工作,操作系统在启动的时候,他就已经默认从配置文件当中读取了他自己曾经把软件安装到了哪些路径下,他把安装到哪些路径下这些重要信息都记录在配置文件里面,等到OS启动的时候,把配置文件中的这些信息导入到内存里面,构建出一个内存级变量,这种变量就是环境变量,上面所讲的PATH环境变量就是操作系统在启动命令行解释器shell的时候,将PATH这样的变量导入到shell的上下文当中,当我们执行对应的指令的时候,我们就必须通过PATH环境变量里面指定的默认的搜索路径去查找对应的可执行程序,所以操作系统为了让我们找到可执行程序,其实做了很多的准备工作,帮我们定义了许许多多的环境变量,通过环境变量帮助我们做了很多本身我们看不见的工作,除PATH这个环境变量,其实还有很多很多的其他环境变量,操作系统需要完成其他很多我们忽略掉的工作,这就需要依靠这些它自己定义出来的环境变量,这些环境变量都有不同的用途,配色方案,当前路径,主机名,用户名,历史指令记录,默认的shell类型这些都要依靠OS他自己定义出来的环境变量去隐式的解决或处理我们看不到的问题和工作。

在不同的使用场景下,要求操作系统在启动shell之后,给我们做命令行解释的时候,必须预先设置好一批未来shell可能用到的变量,通过这些变量完成我们输入的命令的解释,所以 操作系统为了满足不同的应用场景,必须预先在自己的OS内设置一大批的全局变量,这些全局变量其实就是环境变量!

环境变量的组织方式

首先我们知道环境变量是存储的有内容的,那么这些环境变量里面的内容是从哪里来的?
答:环境变量的内容一般是由os从特定的配置文件中读取到的,当我们的os启动完毕过后,os就会读取相关配置文件里面的数据放到环境变量里面;在Linux下环境变量一般都在家目录下的.bashrc和.bash_profile;
这些环境变量也是数据,os也会对这些数据进行管理,os利用一个字符指针数组来维护这个环境变量表
在这里插入图片描述
每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串;这个环境变量表的最后一个元素是NULL,以此来表示环境表的长度

如何获取环境变量

通过代码环境变量主要有3种方式:
1.通过main函数的参数获取:
我们都知道main函数是可以带参数的,而且最多可以带3个参数,比如:

int main(int argc,char*argv[],char*envp[]);

其中envp就是指向这个环境表的首元素指针,通过envp我们可以获取到环境变量:

#include<stdio.h>


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


  return 0;
}

测试结果:
请添加图片描述2.我们也可以不用main的参数,C语言给我们提供了一个全局的字符指针,用来指向环境表,我们也可以通过这个全局的环境表来访问环境变量,这个全局的字符指针也就是:environ,我们只需要声明一下即可使用:

#include<stdio.h>

extern char** environ;

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

  return 0;
}
  1. 通过系统调用getenv函数来获取:
    上面的两种方法虽然可行,但是用起来实在是不方便,比如我向访问一下USER这个环境变量,还得我自己去写匹配算法去一个一个寻找,很是麻烦,而是用getenv函数则会省去我们自己写匹配算法查找的过程,我们只需要告诉getenv我们需要获取哪个环境变量即可,getenv就会返回对应环境变量的内容;如果没有找到对应环境变量则返回NULL
#include <stdio.h>
#include <stdlib.h>
int main()
{
	printf("%s\n", getenv("USER"));
	printf("%s\n", getenv("PATH"));
	return 0;
}

在这里插入图片描述
利用该函数我们可以搞一个只允许私人(如IKun)使用的pwd命令!

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<assert.h>
#define NAME "Ikun"
void Mypwd()
{
	char* pwd = getenv("PWD");
	assert(pwd);
	printf("%s\n", pwd);
}
int main()
{
	char* user = getenv("USER");
	assert(user);
	if (strcmp(NAME, user) == 0)
	{
		Mypwd();
	}
	else
	{
		printf("\n小黑子...\n");
	}

	return 0;
}

为了保持我们的pwd指令能像系统的pwd指令那样执行,我们需要将我们的代码所形成的可执行程序添加到PATH其中一个默认目录下:
在这里插入图片描述
测试:
请添加图片描述

环境变量和本地变量的关系(本地变量包含环境变量)

显示本地变量和环境变量的指令

  1. set指令可以显示shell中的环境变量和非环境变量(包括本地变量)
  2. env可以显示所有的环境变量

导入环境变量和取消环境变量

export MYVAL="youcanseeme"
unset MYVAL

在这里插入图片描述
由于自己定义的环境变量默认就是字符串,所以在定义的时候既可以带上双引号,也可以不带双引号,但如果出现定义的环境变量带空格的话,就必须带上双引号了,所以还是建议在定义的时候带上空格。

1.父进程shell定义的本地变量不会被子进程继承下去,但是父进程的环境变量是会被子进程继承下去的,继承的原因就是为了满足不同的应用场景,因为许多系统指令(ls、whoami、pwd、which、su - )都会涉及到使用环境变量,所以这些指令(子进程)必须继承父进程bash的环境变量,以满足不同的使用场景。
所以环境变量是具有全局性的,因为无论是父进程还是子进程都有环境变量,子进程的环境变量是从父进程继承得来的。

2.本地变量只会在当前进程bash内部有效,因为它不会被继承下去,具有局部性。

命令行参数

上面我们再介绍利用代码获取环境变量的时候,提到了可以利用main函数的参数来获取,其中我们介绍了envp参数,但是argc、argv参数是什么呢,现在我们就来理解一下这两个参数的意义:
从结构上我们可以看到argv与envp是同一个类型,于是我们可以大胆的猜测一下,argv也可能表示的是一张表!其中argc是这个表的长度!
打印出来看看:

#include <stdio.h>

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

1. main函数中的第一个参数是命令行中运行程序的时候字符串的个数,以空格为分隔符,比如上面运行时-a -b -c等,实际上是三个字符串,./mycmd也是一个字符串,所以argc代表的就是字符串的个数,argv指针数组中的指针,指向的就是这些字符串,通过程序运行结果和代码,可以证明这个结论,argv数组中打印出来的值实际上就是这些字符串,所以main函数中的第二个参数就是命令行参数表,表中的指针指向命令行中的所有字符串

2. 系统指令其实就是C语言写的程序,那么它在带指令运行的时候,也能实现不同的功能,这是怎么做到的呢?实际上在实现的代码中的main函数就是需要argc、argv这样的参数实现的

3.所以命令行参数最大的意义就是,通过不同的参数(也就是执行时携带的选项)使得进程拥有不同的功能

类似的在windows下的命令提示符当中,我们也可以通过不同的命令行参数,来使得进程实现不同的功能,例如下面的关机指令,可以设置关机时间,也可以取消关机,选择关机,通过-t、-a、-s等参数实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/393673.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于 OpenCV 与 Java 两个语言版本实现获取某一图片特定区域的颜色对比度

本文目录一、什么是对比度二、什么是颜色直方图三、如何通过RGB计算颜色对比度什么是HSV、Lab颜色空间四、OpenCV代码五、Java代码5.1 平滑处理5.2 完整代码一、什么是对比度 对比度是指图像中不同区域之间的明暗差异程度&#xff0c;它是图像质量中的重要指标之一。除了颜色对…

java的Map集合说明及方法demo示例

一、Map集合的特点&#xff1a;Map集合的特点&#xff1a;1.Map是一个双列集合&#xff0c;一个元素包含两个值&#xff08;一个key&#xff0c;一个value&#xff09;2.Map集合中的元素&#xff0c;key和value的数据类型可以相同&#xff0c;也可以不同3.Map中的元素&#xff…

概率论小课堂:泊松分布(完善你对随机性的认识,特别是对风险防范的认识)

文章目录 引言I 泊松分布1.1 概率计算公式1.2 应对随机性,需要的冗余比平均值要大1.3 池子越大,越能抵消随机性带来的误差引言 伯努利试验:解释了随机事件的发生概率在理论和现实中的差距泊松分布:进一步完善你对随机性的认识,特别是对风险防范的认识。另一类特殊的伯努利…

11.Maxwell 部署

Maxwell 部署 一、环境准备 1、确保服务器上已经安装好了zookeeper、kafka、MySQL软件&#xff1b; &#xff08;1&#xff09;启动zookeeper: /usr/app/zookeeper3.4/bin/zkServer.sh start&#xff08;2&#xff09;启动三台主题的kafka 启动&#xff1a;bin/kafka-serv…

js求解《初级算法》141. 环形链表

一、题目描述 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置…

Apollo控制部分2-- ControllerAgent 控制器管理

Apollo控制部分2-- ControllerAgent 控制器管理摘要一、预备知识1、控制模块预备知识2、多态二、控制器管理解析1、初始化函数&#xff08;配置文件参数决定控制器&#xff09;1&#xff09;配置文件&#xff1a;"/apollo/modules/control/conf/control_conf.pb.txt"…

借助Spire.PDF,这家企业低成本实现在线文档签名和量打印

“公司主要是做跨国运输业务的&#xff0c;我们的客户在邮寄过程中需要提交和下载的确认材料非常多&#xff0c;这些材料大多需要客户分别下载后再手写签字确认上传&#xff0c;这导致我们订单操作效率非常低&#xff0c;还容易导致系统卡顿&#xff0c;我们一直在寻找合性能稳…

【C++】BloomFilter——布隆过滤器

文章目录一、布隆过滤器概念二、布隆过滤器应用三、布隆过滤器实现1.插入2.查找3.删除四、布隆过滤器优缺五、结语一、布隆过滤器概念 布隆过滤器是由布隆&#xff08;Burton Howard Bloom&#xff09;在1970年提出的 一种紧凑型的、比较巧妙的概率型数据结构&#xff0c;特点是…

从互联网科技到手机厂商,谁能扮演好孩子们的“辅导老师”?

【潮汐商业评论/ 原创】“ 没想到现在小孩子的学习机花样这么多&#xff0c;从配置到内容&#xff0c;挑得我是眼花缭乱&#xff0c;跟咱们那会儿一台复读机就能搞定学习完全不一样&#xff01;”80后的Gavin最近苦于为自己要上小学的孩子选购一台合适的学习机。本想是一件很容…

Process Monitor工具使用实验(23)

实验目的 学习Process Monitor实用小工具的使用&#xff0c;学会利用Process Monitor工具观察程序进程/线程、文件系统、注册表、网络连接等的活动。预备知识 Process Monitor是一个Windows系统下先进的监视工具&#xff0c;它可以显示文件系统、注册表、网络连接、进程…

操作系统基础知识介绍之Mixed CriticalitySystems——混合关键系统

一、发展背景 在嵌入式场景中&#xff0c;虽然Linux已经得到了广泛应用&#xff0c;但并不能覆盖所有需求&#xff0c;例如高实时、高可靠、高安全的场合。这些场合往往是实时操作系统 的用武之地。有些应用场景既需要Linux的管理能力、丰富的生态又需要实时操作系统的高实时、…

spring加载bean流程解析

spring作为目前我们开发的基础框架,每天的开发工作基本和他形影不离,作为管理bean的最经典、优秀的框架&#xff0c;它的复杂程度往往令人望而却步。不过作为朝夕相处的框架&#xff0c;我们必须得明白一个问题就是spring是如何加载bean的&#xff0c;我们常在开发中使用的注解…

机器人工程专业师生的第二张名片

课堂上多次提及第二张名片。什么是CatGPT-使用效果如何-专业感性非理性总结如下&#xff1a;机器人工程的工作与考研之困惑→汇总篇←其中包括&#xff1a;☞ 机器人工程的工作与考研之困惑“卷”☞ 机器人工程的工作与考研之困惑“歧视”☞ 机器人工程的工作与考研之困惑“取舍…

62-63-64 - 进程互斥锁Mutex的初步实现

---- 整理自狄泰软件唐佐林老师课程 文章目录1. 问题2. 系统调用重设计2.1 互斥锁系统调用功能设计2.2 整体调用流程2.3 编程实验&#xff1a;互斥锁模块的创建2.4 思考3. 在内核态实现互斥锁功能的考虑3.1 互斥锁内核数据结构及接口实现3.1.1 创建互斥锁3.1.2 销毁互斥锁3.1.3…

Java 字符串String 在堆,栈,常量池中

一、Java程序的运行会涉及以下的内存区域: 寄存器&#xff1a;JVM内部虚拟寄存器&#xff0c;存取速度非常快&#xff0c;程序不可控制。 栈&#xff1a;存放基本类型的数据和对象的引用&#xff0c;但对象本身不存放在栈中&#xff0c;而是存放在堆中。 堆&#xff1a;存放n…

全同态加密:FHEW

参考资料&#xff1a; Micciancio D, Peikert C. Trapdoors for Lattices: Simpler, Tighter, Faster, Smaller[C]//Eurocrypt. 2012, 7237: 700-718.Alperin-Sheriff J, Peikert C. Faster bootstrapping with polynomial error[C]//Advances in Cryptology–CRYPTO 2014: 34…

css盒模型详解

一、引言 盒模型是网页开发中的一个基本概念&#xff0c;它描述了网页元素的外观和大小。盒模型由内容区域、内边距、边框和外边距四个部分组成&#xff0c;这些部分的大小和位置都可以通过CSS进行控制。在本文中&#xff0c;我们将介绍盒模型的概念和作用&#xff0c;并提出本…

一、SpringMVC概述

1.什么是SpringMVC 基于MVC开发模式的框架,用来优化控制器.它是Spring家族的一员.它也具备IOC和AOP. 什么是MVC?   一种开发模式,模型视图控制器的简称.所有的web应用都是基于MVC开发.   M:模型层,包含实体类,业务逻辑层,数据访问层   V:视图层,html,javaScript,vue等都…

MySQL安装和配置

下载官网下载mysql解压版本&#xff1a;配置环境变量下载完成后直接解压到需要放的文件夹&#xff0c;根据文件夹来配置环境变量&#xff1b;新建系统变量&#xff0c;变量名自取&#xff0c;值是MySQL的目录编辑path环境变量&#xff0c;加上MySQL的bin目录 %MYSQL_HOME%\bin配…

【python】序列(列表、元组)、字典、集合的初步认识

一、序列 序列类型(sequence)&#xff1a;一组有序的数据集&#xff0c;特点是数据之间存在先后关系&#xff0c;通过序号访问 序列包含以下三种类型&#xff1a; 1.字符串&#xff08;str&#xff09;不可修改 2.列表&#xff08;list&#xff09;可修改 3.元组&#xff08;t…