【Linux庖丁解牛】—环境变量!

目录

1. 环境变量

1.1 概念介绍

1.2 命令行参数 

1.3  一个例子,一个环境变量

1.4 认识更多的环境变量

1.5 获取环境变量的方法

a. 指令操作

b. 代码操作

1.6 理解环境变量的特性

a.环境变量具有全局特性

b.补充两个概念(为后面埋一个伏笔)


1. 环境变量

1.1 概念介绍

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

• 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪 里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。

• 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性

1.2 命令行参数 

下面我们先来做一个实验,我们都知道在C/C++中,main函数其实是有两个参数的(int argc,char* argv[ ]),字符指针在C语言中要么存有一个字符的地址,要么表示一个字符串的首地址,argv表示数组中存有字符串,而argc表示字符串的个数。

下面的代码表示将数组中的所有字符串打印下来:

下面是实验结果: 

根据结果我们可以发现有某种东西将我们命令行上面的命令(包含空格的字符串)以空格为分隔符分离成多个字符串,并保存在argv数组中。

下面我们再来写一个代码:

#include <stdio.h>
int main(int argc,char *argv[])
{if(argc!=2){printf("usage:%s [-a|-b|-c]\n",argv[0]);}return 0;
}

 以上代码是在用户没有正确使用该命令时告诉用户使用该命令的时候需要带上【-a -b -c】其中的一个选项。

 所以我们就可以用main函数的命令行参数来实现程序的各种不同子功能【这也是指令选项的实现原理】。

总结:每个进程都有一张argv表,用来实现选项功能,以往我们没有关心main函数的命令行参数是因为我们写的程序不需要这些需求。 

小问题:我们在命令行中写的长字符串是被谁切分了呢?

这里直接说结果:用户每次登入系统时都会自动创建一个bash进程,该进程会帮组我们解析命令行中的长字符串。【具体bash是如何做到的我暂时还不知道呢!以后再告诉你们】

1.3  一个例子,一个环境变量

系统预装指令【ls、mkdir】VS 自己写的程序

我们在使用系统级指令时,直接用它们的名称即可。但是当我们要执行自己写的程序时,必须要指明该指令的路径【相对路径或绝对路径】。我们都知道,要执行一个程序,必须先找到它。但是这里有一个问题,系统级指令是如何根据指令名称找到该指令的呢?

先说结论:系统中存在环境变量,来帮助系统找到目标二进制文件!

系统级指令在usr/bin/目录下,如果我们的指令也在该目录下也就可以和系统级指令一样不用指明路径了。

自己写的程序有很多未知性,所以我们还是不要把他放到该目录下! 

 好,接下来我们来认识一下第一个环境变量PATH

PATH是系统中默认搜索指令的路径。 

其中的冒号将每一个默认搜索路径分隔开来,当我们命令行中执行一个命令时,系统会根据PATH环境变量中的默认路径【从第一个路径开始】来查找是否存在该命令。 如果存在,则执行,否则输出该命令未被找到。

既然如此,那如果我们将自己的路径添加到PATH环境变量中,那我们的指令是不是也可以和系统级指令那般直接使用呢?

当然可以,我们直接修改PATH=路径

但是这样系统级指令就找不到了,不过我们关掉xshell重新登入PATH就恢复了

如果我们希望只添加路径的话,如下操作可以办到,当重新登入也会恢复原样:

 至于为什么会回复原样,我们需要对环境变量有更加深刻的理解!

接下来,我们从存储的角度理解环境变量。

先说结论,在用户登入系统时,bash进程会形成一张表->【环境变量表】,这张表的结构和命令行参数表完全相同【都是字符指针数组】。

env命令可以查看系统当中的所有环境变量,而环境变量表中存储着这些内容!

所以,环境变量就是bash进程内部malloc的一段空间,而这段空间存储的内容就是一个一个的字符串【环境变量】 。

至此,我们就可以理解当我们在命令行当中敲下ls -al命令时,ls -al的基本执行流程了:bash进程首先拿到“ls -al”字符串,然后切分形成命令行参数表,接着根据解析完成后的字符串到环境变量表当中找到PATH环境变量,根据PATH默认的路径下找该命令,找到即执行,没找到则报错。

那环境变量最开始从哪里来的呢?->[如果不登入就没有bash进程]

先说结论:从系统相关的配置文件中来的!

bash进程创建时就会从配置文件中拿到所有的环境变量并创建一张表!这就是我们上面说到的修改PATH环境变量为什么在重新登入时就会恢复原样的原因。

好,那我们就来看一下什么是配置文件!

在每个Linux用户的家目录下都有一个.bashrc的隐藏文件。

该文件下的100多行都是先关的配置信息。 

那如果我们将自己的路径添加到配置文件中的PATH值的时候,是不是每次登入时自己写的程序可以和系统级指令一样使用呢!当然如此!这里就不演示了。

1.4 认识更多的环境变量

。HOME环境变量

指定用户的家目录(即用于登入Linux系统时,默认的家目录)

。LOGNAME  |  USER 【登入用户 | 用户】

。HISTSIZE 

记录我们历史上敲的最新1000行命令

。PWD  |  OLDPWD [当前工作路径 | 上一次工作路径]

这也是我们使用cd -可以来回切换工作路径的原因,系统已经帮我们记录好了。

最后,我们在回到环境变量的概念:环境变量(environment variables)⼀般是指在操作系统中用来指定操作系统运行环境的⼀些参数

此时,我们就会对这个概念有更加深刻的理解了,我们会发现每一种环境变量都有其特定的功能,有的是记录当前用户的,有的是记录历史指令的,有的是帮我们找指令的默认路径的,还有的是记录主机名,记录当前工作路径……而这些环境变量都是系统提供的,并且这些环境变量本质上是给bash进程使用,这也是间接的给用户使用了!

1.5 获取环境变量的方法

a. 指令操作

上面我们使用过了env【查看所有环境变量】,echo +环境变量名【查看某个环境变量】就不多说了。

export【向环境变量表中导入自己写的环境变量】

 unset【取消某个环境变量】

b. 代码操作

1.main函数的第三个命令行参数char *env

我们之前说main函数有两个参数,其实还有第三个参数env,这个参数继承了父进程bash的环境变量表,所以我们也可以通过这个参数拿到所有的环境变量。

 因为子进程会继承父进程bash的环境变量表,所以如果我们修改bash的环境变量,那么子进程的环境变量也会随之修改。

bash进程环境变量表修改后:

 子进程的环境变量表:

既然如此,bash的孙子进程,曾孙进程等等都会基础bash的环境变量表。

所以说:环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性

2.getenv【系统调用】

给该函数传递环境变量名,该函数就会返回字符串地址【该环境变量的内容】。即可以获得指定环境变量的内容。

上面我们说过:子进程会继承父进程的环境变量,为什么要这样设计呢?

这是为了让我们的进程可以根据环境变量做个性化的操作!下面举一个栗子:

如果我们希望写一个只有我们自己才能运行的程序,该怎么写呢?

我们都知道,系统当中只有bash进程认识当前用户是谁【在环境变量USER当中记录着】,所以我们可以通过获取该环境变量的方式来控制我们的程序逻辑进而实现只有自己登录系统时才能运行该程序的目的。

用户是user2时: 

用户是root时:      

3. environ 【全局的二级指针】

该指针指向环境变量表的首地址,所以是二级指针。所以我们也可以通过它来获取所有的环境变量。

1.6 理解环境变量的特性

a.环境变量具有全局特性

(前面已经说明过这个特性了,这里就不赘述了)

b.补充两个概念(为后面埋一个伏笔)

1.本地变量

我在命令行中直接定义变量i=10,发现echo命令也可以查看到该变量,但是该变量并不是环境变量,没有记录到环境变量表当中。

但是我们可以用set命令同时查看环境变量和本地变量。

本地变量与环境变量不同,并不会被子进程继承,而只是在bash内部被使用。

2.我们的环境变量是在谁里面?bash!

export是把自己写的环境变量导入到父进程bash里面。

而子进程怎么会导数据到父进程里面呢?这也太奇怪了!

原因就在于export是内建命令【built-in command】执行该指令时,不需要创建子进程,而是让bash自己亲自执行【bash自己调用函数或者系统调用完成】。

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

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

相关文章

LangChain4j +DeepSeek大模型应用开发——7 项目实战 创建硅谷小鹿

这部分我们实现硅谷小鹿的基本聊天功能&#xff0c;包含聊天记忆、聊天记忆持久化、提示词 1. 创建硅谷小鹿 创建XiaoLuAgent package com.ai.langchain4j.assistant;import dev.langchain4j.service.*; import dev.langchain4j.service.spring.AiService;import static dev…

普通 html 项目也可以支持 scss_sass

项目结构示例 下载vscode的插件Live Sass Compiler 自动监听编译scss 下载插件Live Server 用于 web 服务器&#xff0c;打开 html 文件到浏览器&#xff0c;也可以不用这个&#xff0c;自己用 nginx 或者宝塔其他 web 工具 新建一个 index.scss打开&#xff0c;点击 vscode 底…

网工_IP协议

2025.02.17&#xff1a;小猿网&网工老姜学习笔记 第19节 IP协议 9.1 IP数据包的格式&#xff08;首部数据部分&#xff09;9.1.1 IP协议的首部格式&#xff08;固定部分可变部分&#xff09; 9.2 IP数据包分片&#xff08;找题练&#xff09;9.3 TTL生存时间的应用9.4 常见…

SQL语句练习 自学SQL网 在查询中使用表达式 统计

目录 Day 9 在查询中使用表达式 Day 10 在查询中进行统计 聚合函数 Day 11 在查询中进行统计 HAVING关键字 Day12 查询执行顺序 Day 9 在查询中使用表达式 SELECT id , Title , (International_salesDomestic_sales)/1000000 AS International_sales FROM moviesLEFT JOIN …

基于机器学习的舆情分析算法研究

标题:基于机器学习的舆情分析算法研究 内容:1.摘要 随着互联网的飞速发展&#xff0c;舆情信息呈现爆炸式增长&#xff0c;如何快速准确地分析舆情成为重要课题。本文旨在研究基于机器学习的舆情分析算法&#xff0c;以提高舆情分析的效率和准确性。方法上&#xff0c;收集了近…

菲索旋转齿轮法:首次地面光速测量的科学魔术

一、当齿轮邂逅光束&#xff1a;19世纪的光速实验室 1849年&#xff0c;法国物理学家阿曼德菲索&#xff08;Armand Fizeau&#xff09;在巴黎郊外的一座庄园里&#xff0c;用一组旋转齿轮、一面镜子和一盏油灯&#xff0c;完成了人类首次地面光速测量。他的实验测得光速为315…

上位机知识篇---PSRAM和RAM

文章目录 前言一、RAM&#xff08;Random Access Memory&#xff09;1. 核心定义分类&#xff1a;SRAM&#xff08;静态RAM&#xff09;DRAM&#xff08;动态RAM&#xff09; 2. 关键特性SRAM优点缺点应用 DRAM优点缺点应用 3. 技术演进DDR SDRAMLPDDR&#xff08;低功耗DRAM&a…

Qt QComboBox 下拉复选多选(multicombobox)

Qt QComboBox 下拉复选多选&#xff08;multicombobox&#xff09;&#xff0c;备忘&#xff0c;待更多测试 【免费】QtQComboBox下拉复选多选&#xff08;multicombobox&#xff09;资源-CSDN文库

ElasticSearch深入解析(五):如何将一台电脑上的Elasticsearch服务迁移到另一台电脑上

文章目录 0.安装数据迁移工具1.导出数据2.导出mapping3.导出查询模板4.拷贝插件5.拷贝配置6.导入到目标电脑上 0.安装数据迁移工具 Elasticsearch dump是一个用于将Elasticsearch索引数据导出为JSON格式的工具。你可以使用Elasticsearch dump通过命令行或编程接口来导出数据。…

微服务中组件扫描(ComponentScan)的工作原理

微服务中组件扫描(ComponentScan)的工作原理 你的问题涉及到Spring框架中ComponentScan的工作原理以及Maven依赖管理的影响。我来解释为什么能够扫描到common模块的bean而扫描不到其他模块的bean。 根本原因 关键在于**类路径(Classpath)**的包含情况&#xff1a; Maven依赖…

Python镜像源配置:

1.用命令进行配置&#xff1a; 1. 使用命令行方式更改镜像源 可以直接通过 pip config 命令来设置全局或用户级别的镜像源地址。例如&#xff0c;使用清华大学开源软件镜像站作为新的索引 URL&#xff1a; pip config set global.index-url https://pypi.tuna.tsinghua.edu.…

【SpringBoot】Spring中事务的实现:声明式事务@Transactional、编程式事务

1. 准备工作 1.1 在MySQL数据库中创建相应的表 用户注册的例子进行演示事务操作&#xff0c;索引需要一个用户信息表 &#xff08;1&#xff09;创建数据库 -- 创建数据库 DROP DATABASE IF EXISTS trans_test; CREATE DATABASE trans_test DEFAULT CHARACTER SET utf8mb4;…

javascript 深拷贝和浅拷贝的区别及具体实现方案

一、核心区别 特性浅拷贝深拷贝复制层级仅复制对象的第一层属性递归复制对象的所有层级属性&#xff08;包括嵌套对象和数组&#xff09;引用关系嵌套对象/数组与原对象共享内存&#xff08;引用拷贝&#xff09;嵌套对象/数组与原对象完全独立&#xff08;值拷贝&#xff09;…

pytorch对应gpu版本是否可用判断逻辑

# gpu_is_ok.py import torchdef check_torch_gpu():# 打印PyTorch版本print(f"PyTorch version: {torch.__version__}")# 检查CUDA是否可用cuda_available torch.cuda.is_available()print(f"CUDA available: {cuda_available}")if cuda_available:# 打印…

国内无法访问GitHub官网的问题解决

作为一名程序员&#xff0c;在国内访问GitHub官网经常会遇到打开过慢或者访问失败的问题&#xff0c;但通过一些技巧可以改善访问体验。GitHub访问问题的根源在于GitHub官网访问不稳定的主要原因在于DNS解析过程。当我们直接访问github.com时&#xff0c;需要通过DNS服务器将域…

使用 MediaPipe 和 OpenCV 快速生成人脸掩膜(Face Mask)

在实际项目中&#xff0c;尤其是涉及人脸识别、换脸、图像修复等任务时&#xff0c;我们经常需要生成人脸区域的掩膜&#xff08;mask&#xff09;。这篇文章分享一个简单易用的小工具&#xff0c;利用 MediaPipe 和 OpenCV&#xff0c;快速提取人脸轮廓并生成二值掩膜图像。 …

【动态导通电阻】GaN功率器件中动态导通电阻退化的机制、表征及建模方法

2019年,浙江大学的Shu Yang等人在《IEEE Journal of Emerging and Selected Topics in Power Electronics》上发表了一篇关于GaN(氮化镓)功率器件动态导通电阻(Dynamic On-Resistance, RON)的研究论文。该文深入探讨了GaN功率器件中动态导通电阻退化的机制、表征方法、建模…

从括号匹配看栈:数据结构入门的实战与原理

在计算机科学的世界里&#xff0c;数据结构是程序员的 “瑞士军刀”&#xff0c;不同的数据结构适用于不同的场景&#xff0c;能高效解决各类问题。其中&#xff0c;栈作为一种简单却强大的数据结构&#xff0c;在很多实际应用中发挥着关键作用。今天&#xff0c;我们就通过一个…

Dubbo(89)如何设计一个支持多语言的Dubbo服务?

设计一个支持多语言的Dubbo服务需要考虑以下几个方面&#xff1a; 服务接口设计&#xff1a;确保服务接口的定义可以被不同语言实现。序列化协议&#xff1a;选择一个支持多语言的序列化协议&#xff0c;例如Protobuf、Thrift、gRPC等。服务注册与发现&#xff1a;确保服务注册…

力扣面试150题--分隔链表

day 39 题目描述 思路 遍历链表&#xff0c;每一个点与值比较&#xff0c;比值小就继续&#xff0c;比值大就放到链表尾部即可 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int…