linux进程——解析命令行参数——环境变量详解

news2024/11/14 2:45:30

        前言:本节内容还是linux进程, 主要讲解里面的环境变量——我们首先要知道的就是环境变量其实就是操作系统维护的一组kv值, 环境变量是系统提供的一组 变量名=变量值 形式的变量。不同的环境变量之间具有不同的用途, 并且具有全局属性。 本篇内容主要分为两个大板块——第一个大板块主要是具体举几个环境变量的例子、第二个大板块主要是讲解环境变量的概念与知识点。

        ps:本节内容适合了解进程PCB的友友进行观看

        

目录

PATH

HOME

SHELL

getnev

什么是环境变量

命令行参数

命令行参数里的环境变量

本地变量与内建命令


PATH

        我们以前说过, 指令的本质就是一个进程。 而且, 我们以前也说过, 我们自己写的程序必须加上./, 而指令不需要./——请问这是为什么呢?

        这是因为, 系统当中, 针对我们指令的搜索, 我们的系统会为它提供一个环境变量——PATH, 我们可以使用echo $PATH打印。 (注意, 这里的$符号不能去掉, 因为不加$就意味着echo会将PATH当作一个字符串进行打印。这个时候, 打印的内容里面包含一串串路径, 并且这些路径用“:”进行分割, 这里面的每一条路径都对应着我们的指令进行搜索的路径。如下图;

        也就是说, 我们的系统怎么知道我们都是用的指令在哪里寻找呢? 就是因为PATH, 当我们调用某个指令的时候, 系统会进入PATH显示的每一个路径里面一个一个进行查找。 没找到就继续下一个, 没找到就继续下一个。 而如果某个程序被放到这些路径下面, 那么系统默认就会找到(就比如我们使用的指令 就是放到这里面的), 而如果某个程序没有被放到这些路径下面, 系统默认就找不到, 就会返回commend no found。 而如果想要运行这个程序就要输入这个程序的相对路径(就比如我们运行我们自己写的程序, 就是使用./程序, 这就是相对路径)

        想要在环境变量的路径中添加路径怎么做呢?

        就是使用PATH=$PATH:新添路径——其实这里的等号后面的路径就相当于PATH的新路径, 如果等号后面的PATH不要了, 只要添加新的路径, 那么新路径就不是现在这样既有PATH原本的路径, 又有新添路径了, 而是只有一个新路径。 

        注意:此时所修改的环境变量是内存级的环境变量, 想要变回来只需要重新启动一下xshell。

        综上:PATH:linux系统指令的搜索路径。

        windows下面的同样有环境变量, 事实上, 当我们使用python、java这些解释型语言的时候, 都需要配置环境变量, 而windows下面的环境变量的修改方法如下:

HOME

如图我们登陆了普通用户, 并且可以使用pwd查看当前当前目录, 同时我们使用echo $HOME;

也可以看到当前的目录。 

一个用户默认登录的进入的是用户的家目录, 那么为什么会这样呢?

因为一个用户在登录时, 系统默认识别$HOME命令, 查看当前用户的家目录在哪里, 当我们登录的时候, 就默认执行了cd $HOME指令进入了用户的家目录下。

SHELL

$SHELL可以查看当前命令行用的是什么, 即, 当前shell用的是哪一个可执行程序。

其他的, 还有很多的环境变量, env指令可以查看当前自己的进程和bash进程从系统继承下来的所有环境变量


 

getnev

通过c语言, c++我们也可以通过getenv函数获取某个环境变量。 

那么环境变量在权限中的应用?

如何就是通过getnev获取当前用户, 获取用户后和root账户做对比, 根据if else语句判断是不是root账户, 并在if或者else代码块里面执行对应的动作。 通过这个, 我们就能更好的理解权限问题——对于一个文件或者某个指令的权限判断, 是拥有者, 还是所属组, 亦或者是其他人。

什么是环境变量

        关于什么是环境变量, 在前言中博主已经提到。 但是这里还要补充一点:环境变量其实是有一定的用途的, 比如当前用户的家目录在哪, 当前的用户是谁,指令的搜索路径是哪里, shell的可执行程序是哪个等等。 

        而要具体的理解环境变量, 需要先理解命令行参数。 下面我们先来理解一下命令行参数的概念

命令行参数

      对于main函数来说, 其实它是可以有参数的, 如下:

int main(int argc, char* argv[]){}

        这里面的argv是一个指针数组, argc代表argv的数组元素个数。 argv里面的元素个数由argc决定。

        这里可以使用一个循环, 将argv里面的元素全部打印出来:

        然后我们运行这个程序, 或者运行这个程序的时候加上一些选项, 就能看到打印出来的结果分别是这样的:


 

        ps:这里有一个题外的问题——main函数是第一个被系统调用的函数吗?——不重要, 友友们自行跳过即可。

        为了回答这个问题, 我们就要思考如果main函数是第一个被调用的函数, 那么它是不是就势必不能被传参? 而我们的main函数是有参数的; 而且我们从c语言也说过第一个被系统调用的函数其实是叫做starUp的函数, 这个函数真正的无参。

        回到上面的图中, 想要知道为什么我们输入的选项越多, 打印的内容就越多,就涉及到了bash的知识点——其实我们在bash上面输入任何指令, 本质上都是在输入字符串。 就比如我们上面输入./process-7-11.exe -a -b -c, 这个其实就是输入了一个"./process-7-11.exe -a -b -c"字符串而已。 而bash在进行命令行解释的时候会将这些字符串按照空格进行分割, 这些字符串分成一个新的字符串一起传给main函数作为形参, 也就产生了下面这种效果, 然后for循环再依次打印。

bash命令行为什么要这么做呢?

我们来看一个程序, 就能知道bash为什么会这么做了:

我们运行这个程序, 就可以得到如下结果:

对比我们使用ls加选项的时候:

        对比上面的两个选项, 我们是不是就能发现, 我们常用的指令, 为什么要打上选项?是不是就是因为指令加选项 本质上都是运行一个程序, 只是根据不同的选项, 走到了不同的else if里面, 然后执行了对应的功能模块。 这就是指令选项的本质, 这就是命令行参数。——也就是说, 命令行参数的一个重要功能就是为指令、工具等提供命令行选项的支持!!!

        而只要需要选项, 那么就要用到命令行参数, 所以要有命令行参数——即命令行参数的意义就是, 为了让我们使用程序的时候根据不同的选项, 执行不同的操作。

        我们使用ls --help就能查看ls的所有选项

        也就是相当于我们自己编写的程序, 加上了一个--help选项

        最后要补充一点的就是对于argv来说, 它的最后一个元素默认是NULL,也就是说我们在上面程序模拟的时候, 其实是不需要使用if判断, 如下图:

        现在来看一个叫做向量表的概念。 这个向量表其实就是上面的argv, 类似下图:

知道了这些东西以后, 那么, 这里就可以回归正题——>环境变量。

命令行参数里的环境变量

        我们学习命令行参数不是无理头的, 命令行参数和环境变量具有一定的关系,在哪呢?——请问, 有没有人规定命令行参数只有argc, argv? 没有, 也就是说, main的参数可能还有别的。 那么, main函数还真有一个别的参数, 这个参数就叫做int* env[], 这个env[]里面保存的是main当前进程的所有环境变量。 而且, 这个env[]的结构这里也可以提一下——就是向量表。 也就是说, main函数的参数里, 有两张核心向量表, 一张用来保存选项, 一张用来保存环境变量!!!

        下面是实验:

        运行后, 就可以发现和我们使用env指令一样

综上, 我们以后再看待运行程序的时候, 就可以这么考虑——》一定是有一个startIp直接或者间接调用了main函数, 并将两张向量表, 一个选项表, 一个环境变量表传给了main函数。 然后main函数再跑起来。

        那么这里就有了结论, 首先我们知道我们自己运行的这个程序是一个子进程, 而bash是一个父进程。 但是我们在bash下使用env的时候和我们在子进程下打印的环境变量是一样的。 ——这个结论就是——我们所运行的程序, 都是子进程, bash本身在启动的时候,会从操作系统的配置文件中读取环境变量信息, bash再在自己的上下文中构建一个环境变量表。 当我们的子进程需要的话, 就可以将环境变量信息给子进程一份。也就是说, 子进程会继承父进程交给他的所有环境变量!!!这就是为什么环境变量具有全局属性——因为他会在子进程中一个一个地完整的继承下去。

        但是这里有一个问题, 就是环境变量也是数据, 我们知道进程之间是独立的。 而如果一个子进程想要修改环境变量, 那么就一定不能够影响父进程的环境变量(写时拷贝)

        那么,我们如何验证这些环境变量可以一个一个的传承下去呢?

        在这里我们可以自己添加一个环境变量——这里的变量有两种, 一种是直接变量名=变量, 这个是本地变量。 另一种是export变量名=比那辆, 这个是环境变量。 我们需要使用后者。

        

        这样, 就可以看到我们的环境变量了!但是, 这个环境变量是我们在bash上面创建的, 那么要验证环境变量的全局性, 就要看一下我们的子进程中有没有这个环境变量。那么有没有呢?答案是有的, 如下图:

        取消环境变量使用unset环境变量:

本地变量与内建命令

set指令可以查看当前shell中所有变量, 包括本地变量和环境变量

本地变量不会被继承, 只会在bash中被使用。 创建本地变量的方式上面已经提到, 就是变量名=变量

我们如何验证本地变量不会被继承呢? 这里, 我们来写一个程序:

这个程序可以打印环境变量

我们可以使用set, 查看当前到当前具有这个本地变量, 但是我们使用子进程进行查看的时候, 查看不到!

然后, 当我们把本地变量改成环境变量的时候, 就能查看到了:

以上, 就说明了本地变量不能被继承.

        那么, 看第二个问题:

        既然MY_VALUE是一个本地变量, 那么它就不能被子进程继承, 我们也知道, bash里面的指令, 其实就是一个个bash的子进程, 问题是, 为什么图中的echo可以打印出MY_VALUE呢?

        那么, 没有错, echo不是一个bash的子进程。 这里就可以纠正之前的一个认知错误, 那就是——bash里面的指令, 不全都是bash的子进程。

        命令其实分为两种:一种是常规指令, 通过创建子进程完成。 

                                        一种是内建命令, 这种命令bash不回去创建子进程, 而是自己亲自执行(就相当于我们自己写的程序, 但是没有fork子进程, 或者说bash调用了自己写的或者系统提供的函数。)

        我们可以通过cd来理解这个内建命令的概念:这里我们自己实现一个cd命令, 这里需要用到系统调用接口——chdir(const char* path)

原因就是因为我们自己写的程序是bash创建的子进程。 而cd是bash自己调用的本身代码块。 两者本质不一样, 但是我们同样可以看到我们自己写的程序的工作目录——就是proc进程查看里面的工作目录。 代码如下, 两次睡眠是为了我们进行更好的观察。

如图是刚刚运行程序, 这个时候工作路径还没有发生变化:

下图就是工作路径没有发生变化的时候子进程工作路径:

工作路径变化!说明子进程工作路径变化只改变自己, 而cd是是父进程, 它改变工作路径, 就意味着我们的命令路径变了!!!

在系统里面, 有一个变量, 可以让我们不适用main参数就打印全部的环境变量——environ, 使用如下:

打印结果如下:

以上, 就是本节全部内容, 下面是本节笔记:

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

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

相关文章

刷机维修进阶教程-----何谓“tee损坏” 指纹丢失 掉帧 传感器失效?详细修复步骤教程

TEE损坏指的是安卓机型中Key Attestation密钥认证所依赖的可信应用中的证书库被破坏了。然后拒绝为指纹密匙认证提供服务。加密的密匙由TEE负责管理。tee损坏只影响当前机型的密匙认证。不影响加密。通俗的理解。如果你机型维修或者刷机或者解锁或者格机 全檫除分区等等后有异常…

Python自然语言处理库之NLTK与spaCy使用详解

概要 自然语言处理(NLP)是人工智能和数据科学领域的重要分支,致力于让计算机理解、解释和生成人类语言。在Python中,NLTK(Natural Language Toolkit)和spaCy是两个广泛使用的NLP库。本文将详细介绍NLTK和spaCy的特点、功能及其使用方法,并通过具体示例展示如何使用这两…

押金原路退回,手机版一键操作秒到账,无需设备收银设备

传统收银 1.操作不熟练:对收银系统的功能和操作不熟悉,可能导致收银过程较长,顾客等待时间增加。 2无法适应新技术:对于一些新的支付方式或技术,不能自主学 3操作不熟练:鼠标使用不熟练,对收…

element DatePicker 日期选择器,只选择月,月份数据从0开始(0月31日),而不是从1开始,JavaScript的原因,如下为解决办法

<el-date-pickerv-model"queryParam.yuedTime"type"month"placeholder"选择月"change"handleMonthChange"></el-date-picker> 方式一&#xff1a;在前端处理 change"handleMonthChange" &#xff0c;增加此方…

PostgreSQL的学习心得和知识总结(一百四十九)|psql 的使用技巧:设置、预设、回显和已保存的查询

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

nms概念

nms基本概念&#xff1a;非极大值抑制 用途&#xff1a;在做目标检测的时候&#xff0c;往往会生成很多很多候选框&#xff0c;在做目标检测的时候&#xff0c;往往会生成很多很多候选框。 处理流程&#xff1a; 1.对某一类按score对候选框进行排序&#xff0c;并选出score最…

ffmpeg把pcm封装为wav

note 1.wav格式中&#xff0c;音频数据未经过压缩&#xff0c;直接封装即可 2.对于编码器的选择&#xff0c;应选择和pcm裸数据一致的编码器(本次实际不须编码) version #define LIBSWRESAMPLE_VERSION_MAJOR 2 #define LIBSWRESAMPLE_VERSION_MINOR 9 #define LIBSWRESAM…

Python网络爬虫详解:实战豆瓣电影信息采集

文章目录 前言一、爬虫是什么&#xff1f;二、常用库及其作用1.Requests2.BeautifulSoup3. lxml4. Scrapy5. Selenium6. PyQuery7. Pandas8. JSON9. Time 三、实现步骤步骤一&#xff1a;环境准备步骤二&#xff1a;数据采集步骤三&#xff1a;数据处理步骤四&#xff1a;数据存…

【数据分享】2008-2022年我国省市县三级的逐日NO2数据(excel\shp格式)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000-2022年的省市县三级的逐日PM2.5数据、2013-2022年的省市县三级的逐日CO数据和2013-2022年的省市县三级的逐日SO2数据&#xff08;均可查看之前的文章获悉详情&#xff09;&#xff01; 本次…

前端 SSE 长连接

使用 const options {withCredentials: true, // 默认 false}const eventSource new EventSource(/api, options);eventSource.addEventListener(open, () > {});eventSource.onmessage (event) > {}; // 或addEventListener(message,callback)eventSource.addEvent…

BGP选路之AS-PATH

原理概述 当一台BGP路由器中存在多条去往同一目标网络的BGP路由时&#xff0c;BGP协议会对这些BGP路由的属性进行比较&#xff0c;以确定去往该目标网络的最优BGP路由。首先要比较的属性是 Preferred Value&#xff0c;然后是Local Preference&#xff0c;再次是路由生成方式&a…

Ansible的脚本-----playbook剧本【上】

目录 1.playbook剧本组成 2.playbook剧本实战演练 2.1 实战演练一&#xff1a;给被管理主机安装httpd服务 2.2 实战演练二&#xff1a;定义、引用变量 2.3 实战演练三&#xff1a;指定远程主机sudo切换用户 2.4 实战演练四&#xff1a;when条件判断 2.5 实战演练五&…

Docker Compose V2 安装 ClickHouse v20.6.8.5 经验分享

前言 ClickHouse 是一款开源的分布式列式数据库管理系统,专门设计用于高性能的大数据分析和查询。 目前项目中用到的一个场景是将mongo的数据同步到clickhouse,使用clickhouse做报表,后续也将分享同步和使用方案 使用 Docker Compose 部署单机版,小项目和自己测试够用了,生…

【C#】visual studio打包winForm(依赖DLL)为安装程序exe

0.简介 IDE&#xff1a;VS2022 平台&#xff1a;C# .NetFramework4.7 WinForm界面 有GDAL、EEplus库的依赖&#xff0c;所以在其他未安装环境的电脑中功能无法使用。 1. 安装 1.1 运行文件 在VS扩展中选择管理扩展&#xff0c;Microsoft Visual Studio Installer Projects …

C#测试控制台程序调用Quartz.NET的基本用法

Quartz.Net是常用的任务调用框架之一&#xff0c;既能在客户端程序中使用&#xff0c;也支持在网页程序后台调用。本文结合参考文献4中的示例代码学习其在控制台程序中的基本用法。   VS2022新建控制台项目&#xff0c;在Nuget包管理器中搜索并安装Quartz包&#xff0c;如下所…

51单片机嵌入式开发:18、STC89C52RC嵌入式DS1302实时时钟实验及数码管显示

STC89C52RC嵌入式DS1302实时时钟实验及数码管显示 STC89C52RC嵌入式DS1302实时时钟实验及数码管显示1 概述1.1 DS1302简介1.2 DS1302功能和特点1.3 DS1302工作原理1.4 DS1302应用领域 2 DS1302设计原理2.1 引脚说明2.2 寄存器说明及使用&#xff08;1&#xff09;命令cmd字节说…

Redis的缓存问题:缓存穿透、缓存击穿和缓存雪崩

目录 一、缓存穿透 1、问题描述 2、解决方案 二、缓存击穿 1、问题描述 2、解决方案 三、缓存雪崩 1、问题描述 2、解决方案 3、雪崩案例 一、缓存穿透 1、问题描述 缓存穿透指的是⼤量请求的 key根本不存在于缓存中&#xff0c;每次针对此key的请求从缓存获取不到…

报红:找不到名称ref ts(2304)、‘ref‘ is not defined. eslint(no-undef)

接上篇 在上篇介绍了使用 unplugin-auto-import 和 unplugin-vue-components 配置完成后&#xff0c;项目可以正常运行&#xff0c;并且页面也正常显示&#xff0c;但vscode里就是报红 这个报红可能是由于 ts 发出的&#xff0c;也可能是由于 eslint 发出的 具体可以用鼠标…

如何使用 API list 极狐GitLab 群组中的镜像仓库?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…

某数据泄露防护(DLP)系统NetSecConfigAjax接口SQL注入漏洞复现 [附POC]

文章目录 某数据泄露防护(DLP)系统NetSecConfigAjax接口SQL注入漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现某数据泄露防护(DLP)系统NetSecConfigAjax接口SQL注入漏洞复现 [附POC] 0x01 前言 免责声明:请…