环境变量概念详解!(4千字长文)

环境变量!

文章目录

  • 环境变量!
    • 环境变量
      • PATH
        • export
          • export的错误用法
      • 定义命令行变量
      • 环境变量哪里来的
      • 其他各种环境变量
        • HOME
        • HOSTNAME
        • LOGNAME
        • HISTSIZE
      • PWD
    • 环境变量相关指令
      • echo
      • env
      • getenv——相关函数!
      • export
      • set
      • unset
    • 命令行参数
      • argc
      • argv
      • envp
        • environ
      • putenv

环境变量

我们是否可以认为我们平时写的程序是一个指令呢?可以的!

其实我们平时写的程序和我们在linux下执行的指令是同一个东西!

image-20221218120056463

都是可执行程序!

那为什么我们执行的时候,需要用到./xxx这样来执行我们的程序,但是使用系统里面的指令就只要输入就可以呢?

image-20221218141601462

我们从报错我们就可以看出要执行一个程序,就要先找到这个指令!

而 ./ 就是当前路径!通过这个系统找到我们程序的!

所以有两种方法来使我们的程序变的像指令一样使用

  1. 将我们的程序拷贝在==/usr/bin/这个路径下!——但是不建议因为我们的程序没有经过测试,没有经过测试的程序最好不要安装在系统里面!会污染指令池拷贝就是linux的安装!==image-20221218142521259
  2. 修改环境变量——PATH

PATH

PATH是系统中的一个环境变量!操作系统在启动的时候会在shell的上下文之中给我们定义的一个环境变量!是全局有效!

echo PATH//这样查看是不行的!
echo $PATH//这样才能正确查看!

image-20221218143216709

我们可以看到里面有很多的路径!每个路径都按照 : 来分隔开来!

而操作系统在执行指令的时候就是在这些路径下面!来一个个的检索对应的指令!如果指令存在运行!如果不存在就报错!

所以我们只要让我们的路径添加到PATH里面就可以像系统指令一样的去使用了!而且还不会影响指令池!

export

export就是一个用来专门修改环境变量的指令!

export的错误用法
export PATH=xxxxx//指某个路径

这样写会发生什么事情?

会导致这个环境变量下面的所有路径被这个路径给覆盖了!image-20221218144610245

所以绝不可以怎么写,这样还会导致所有的指令都失效了!

image-20221218144649189

不过解决的方法也很简单重启一下就好了,因为这只是一个内存级的环境变量

定义命令行变量

linux的命令行解释器是可以定义命令行式的变量,环境变量也是属于这的一种!

image-20221218145543115

image-20221218145932009

环境变量其实很好理解

我们要明白shell本质也是一个进程!

我们以前在写c/c++程序的时候!我们会去使用new/malloc来申请空间!

new/malloc就是在进程运行的时候申请空间的!

也就是说进程在运行期间是可以对它的空间进行动态的调整的!

有了空间就可以存储数据!环境变量本质也是一个数据!就是一个字符串!

所以在命令行上面定义环境变量其实也是差不多的效果!就是申请空间将数据保存起来!

环境变量哪里来的

上面我们说到PATH这个环境变量重启之后就可以恢复!但是是根据什么来恢复的?

答案是在用户的工作目录下面的两个文件!

image-20221218150345091

我们进入.bash_profile里面看

image-20221218150538906

里面开始就是一个shell脚本 —— 当前工作路径下.bashrc如果存在就执行它

然后里面也定义了一个环境变量 然后导环境变量!

image-20221218150743034

.bashrc里面的内容也是相似的!会先去检查系统/etc路径里面的bashrc会不会存在存在会去执行它!

image-20221218150945768

而这个系统bashrc里面会会存在很多的动作用来构建环境变量!

vim /etc/bashrc //用vim进行查看!

而系统每次启动就会把当前工作路径下的bash_profile执行一次,将环境变量导入当前的shell中!

所以内存中就会存在一个PATH,即使我们将它覆盖了下一次系统启动后也会重新根据这个生成出来!

这种具有全局属性和特殊功能的变量我们称为环境变量!——也可以怎么说环境变量就是操作系统为了满足不同的应用场景而预先在系统内设置的一堆全局变量!

就是有各种各样的环境变量!操作系统才能完成各种各样的功能!所以才需要开始就预先设置好!

其他各种环境变量

HOME

这个环境变量就是当前用户的工作目录!

image-20221218151759817

所以我们使用 **~**的时候本质就是进入$HOME所对应的路径下!

cd ~
cd $HOME//这个和上面的结果是一样的!都是切换到当前的工作目录!

HOSTNAME

这个环境变量对应的是主机名

image-20221218152028702

LOGNAME

这个是对应的这个系统的用户名!

image-20221218152041143

HISTSIZE

image-20221218152230127

当我们在命令行按上下的时候,就会显示出以前的历史的指令!

这个就是就是可以记录的历史命令的数量!

PWD

这个环境变量记录着我们的当前路径!

image-20221219171410241

当我们的路径改变的时候!bash也会跟着修改PWD的这个环境变量的值!

我们调用ls指令 我们查看当前路径下的时候都是直接后面跟文件名的!

ls test.c

例如上面这样!而其实ls是通过调用PWD这个环境变量用来知道我们所处的路径的!

环境变量相关指令

echo

显示环境变量的值!

echo $xxx// xx就是环境变量的名称!

env

用看查看所有的环境变量!

image-20221218152455884

这些都是系统里面的环境变量!

getenv——相关函数!

这是一个函数专门用来获取环境变量的!

image-20221218164326316

这是一个用来专门获取环境变量的C语言函数接口!

返回值是个该变量的指针!如果找不到就返回一个null

使用

#include <stdio.h>    
#include <stdlib.h>    
#include <string.h>    
#define USER "USER"    
int main()    
{    
 char* who = getenv(USER);    
 if(strcmp(who,"root")== 0)                              
 {     
     printf("user:%s\n",who);    
     printf("user:%s\n",who);    
     printf("user:%s\n",who);    
     printf("user:%s\n",who);    
     printf("user:%s\n",who);    
 }    
 else{    
     printf("权限不足!\n");    

 }    
 return 0;    
}  

USER的环境变量的最大意义就在于可以识别当前linux用户!

linux的很多指令都是通过USER来识别的!

image-20221218170148261

export

用来修改环境变量!

也可将命令行的上定义的本地变量变成环境变量!

我们可以用以下代码来验证

#include <stdio.h>    
#include <stdlib.h>    
#include <string.h>    
#define USER "USER"    
#define MY_ENV "myval"    
int main()    
{    
    char *myenv = getenv(MY_ENV);    
    if(myenv == NULL)    
    {    
        printf("%s,not found\n", MY_ENV);    
        return 1;    
    }    
    printf("%s = %s\n",MY_ENV,myenv); 
}

image-20221219163603131

我们可以发现是找不到!

但是如果我们使用

export myval
export myval=1000//也可以这样定义的时候导

image-20221219164318129

我们上面说过!bash本质是一个进程!而mycmd本质也是一个进程!是bash的子进程!

通过的是fork函数来实现的!

而我们的环境变量是定义在bash这个进程上的!

但是我们的子进程也可以识别到这个环境变量!——这个说明全局变量,具有全局属性的根本就是环境变量会被子进程给继承下去的!

为什么要继承下去?

为了适应不用的应用场景!

像是我们使用cd这个切换指令!当我们不是root用户的时候想要切换到home目录下的其他用户的路径的时候!我们就会被告知权限不足!cd指令本质也是一个子进程!就是通过继承读取USER这个环境变量来做身份认证的!

而区别的本地变量!(还没有用exprot导入的)就只在当前的进程(bash)下面有效!

set

即显示本地变量!又显示环境变量!将所有的变量显示出来!

image-20221219170358573

unset

取消环境变量!

image-20221219170638567

这样环境变量就被我们取消了

取消本地变量!

image-20221219170945608

命令行参数

我们使用的main()函数虽然我们一般都是这样使用的!

但是main函数本质也是有参数的!一共有三个

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

那么这三个参数分别有什么用吗?

argc

argc相当于是第二个数组的大小!

argv

而且我们都知道main函数是一个主函数!那么是谁调用了main函数? ——是操作系统!

==argv是一个指针数组!==那么重点来了?那它的值是谁传的?——就是操作系统/父进程

那传的是什么呢?

我们可以测试一下!

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

image-20221219214525816

我们可以看到argv数组的内容其实就是命令行上的内容!——命令行上的内容都是要传给argv的!

第一个就是程序名!剩下的都是选项!

同理我们使用的一些指令!例如 ls都是一样的!ls -a -l 这个会被传入到ls这个程序里面的argv数组!

image-20221219215547672

这个工作是由shell和操作系统一起完成实现的!

那么这个参数的最大的意义是什么呢?

假如我们以后写一个程序 想要让这个程序根据不同点选项执行程序内不同的功能的时候!那么这个参数就会发挥用处了!(例如ls 我们可以在后面跟上 -a,-l之类的选择让它执行不同的功能!)

举个例子

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char* argv[])
{
    if(argc != 2)
    {
        printf("Usage: \n\t%s [-a/-b/-ab/-ac/-bc/abc]\n",argv[0]);
        return 1;
    }
    if(strcmp("-a",argv[1])== 0)
    {
        printf("功能a\n");
    }
    if(strcmp("-b",argv[1])== 0)
    {
        printf("功能b\n");
    }
    if(strcmp("-c",argv[1])== 0)
    {                                                                                   
        printf("功能c\n");
    }    
    if(strcmp("-ab",argv[1])== 0)
    {
        printf("功能ab\n");  
     }
    if(strcmp("-bc",argv[1])== 0)
    {
        printf("功能bc\n");
    }
    return 0;
}

image-20221220102141491

例如在ls下面执行不同的打印就是通过命名行参数!来读取继承获得的!

envp

也是一个指针数组!

只不过它指向的是一个个的环境变量!结尾也是NULL

环境变量的就是一行行的字符串!

所以其实当main函数被调用的时候!如何带有这些参数!

那么系统就会自动的生成两张表!一个是命令行参数表!一个是环境变量表!

每个进程都会生成!

这就是为什么进程可以拿到环境变量的原因!

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

image-20221220104958608

我们发现所有的环境变量全都都导入到了这个进程里面!

image-20221220105008877

我们发现我们导入的环境变量也可以被传进入!

environ

如果我们既不想用环境变量参数envp也不想使用getenv话C语言还为我们提供了一个参数让我们来使用!

image-20221220105730042

这是一个全局变量的二级指针!这个指针本质其实就是指向envp这张表上使用这个参数前面要加上extren

我们可以通过这来访问环境变量!

因为数组传参的时候会发生降维,会降维成只想内部元素类型的指针!

所以envp发生降维就是内部元素是char*型,那么降维就是char**

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

image-20221220110834541

这样我们就有在我们进程的上下文中获取环境变量的三种方式!

  1. getenv——函数!
  2. envp参数!
  3. environ——二级指针!

不过我们一般都是使用getenv更多!

putenv

image-20221220111442137

putenv是改变或者添加一个环境变量!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自动化面试题4

1、工业中常见的通信方式都有哪些&#xff0c;各自特点是什么&#xff1f; 2、对于一台新的伺服驱动器来说&#xff0c;需要设置哪几个方面的参数&#xff1f; &#xff08;1&#xff09;参数初始化 &#xff08;2&#xff09;点动测试电机旋转方向 &#xff08;3&#xff09;惯…

Android创建项目

目录 创建Android项目 配置项目结构 创建安卓模拟器 模拟器运行 HelloWorld 应用 真机运行 HelloWorld 应用 创建Android项目 打开 Android studio 工具&#xff0c;选择Project&#xff0c;选择 New Project 由于现在是教程博客&#xff0c;所以我们随便选择 一个 空 Ac…

Java使用elasticjob实现定时任务(v2.1.5)

elastic是一个定时任务库 https://shardingsphere.apache.org/elasticjob/index_zh.html 项目结构 ​依赖 <dependency><groupId>com.dangdang</groupId><artifactId>elastic-job-lite-core</artifactId><version>2.1.5</version>&…

5.Java循环控制语句

Java循环控制语句 循环是Java中应用最为广泛的一个知识点&#xff0c;所以也是很需要掌握的。所谓循环&#xff0c;即通过判断条件&#xff0c;重复执行一段代码&#xff0c;根据条件的变化&#xff0c;来确定代码是否执行&#xff0c;执行次数。 一、循环结构 1、while循环…

C风格的字符串赋值方式

文章目录&#xff08;1&#xff09;C语言中&#xff0c;没有字符串类型但可以用字符数组模拟字符串。&#xff08;2&#xff09;C语言中&#xff0c;字符串是以’\0’作结尾字符。&#xff08;3&#xff09;C语言中&#xff0c;字符串常量本质上是一个无名的字符数组。C风格的字…

代码自动发布系统

之前是jenkins发现gitlab代码更新了就自动获取直接部署到服务器 现在是jenkins自动获取Code之后打包成镜像上传到仓库然后通知docker去拉取更新的镜像 分析 旧∶ 代码发布环境提前准备&#xff0c;以主机为颗粒度静态 新: 代码发布环境多套&#xff0c;以容器为颗粒度编译 …

适合销售使用的CRM系统特点

销售人员抱怨CRM系统太复杂&#xff0c;这是一个很重要的问题。毕竟&#xff0c;如果系统太难使用&#xff0c;会导致CRM实用率和效率下降&#xff0c;最终影响公司的运作。在这篇文章中&#xff0c;我们来探讨当销售抱怨crm客户系统太复杂了&#xff0c;企业该如何解决。 缺少…

VCS4 debug with DVE

1、重点讲解&#xff1a; 在verilog源代码中嵌入VCD 系统函数&#xff0c;重点如testbench文件中。VCD文件是VCS产生的仿真波形文件&#xff0c;未经压缩&#xff0c;占用空间较大。VCD是压缩后的波形文件。 编译、仿真以生成VCD文件。 在后处理模式中使用激活DVElog对产生的…

NodeJS Cluster模块基础教程

Cluster简介 默认情况下&#xff0c;Node.js不会利用所有的CPU&#xff0c;即使机器有多个CPU。一旦这个进程崩掉&#xff0c;那么整个 web 服务就崩掉了。 应用部署到多核服务器时&#xff0c;为了充分利用多核 CPU 资源一般启动多个 NodeJS 进程提供服务&#xff0c;这时就…

当ChatGPT续写《红楼梦》,能替代原著吗?

来源: 清华大学出版社 近段时间&#xff0c;人工智能聊天机器人ChatGPT火爆网络&#xff0c;“AI写作是否会让文字工作者被替代&#xff1f;”成为人们关注并持续讨论的话题。 闲聊、问答、解题、写代码、写诗、创作小说&#xff0c; 连续回答&#xff0c;不断纠错&#xff0c…

拥抱自动化测试,快速升职加薪丄Selenium+Pytest自动化测试框架教你如何做到

目录&#xff1a;导读 引言 SeleniumPytest自动化测试框架是目前最流行的自动化测试工具之一&#xff0c;其强大的功能和易用性援助许多开发人员和测试人员。 selenium自动化 pytest测试框架禅道实战 选用的测试网址为我电脑本地搭建的禅道 conftest.py更改 config.ini更…

MyBatis配置文件 —— 相关标签详解

目录 一、Mybatis配置文件 — properties标签 二、Mybatis配置文件 — settings标签 三、Mybatis配置文件 — plugins标签 四、Mybatis配置文件 — typeAliases标签 五、Mybatis配置文件 — environments标签 六、Mybatis配置文件 — mappers标签 一、Mybatis配置文件 —…

2023年第十四届蓝桥杯 C++ B组参赛经验总结

没错&#xff0c;今年本菜狗又来啦~~ hhh &#xff0c; 文章当时比赛完就写完了&#xff0c; 发的有点晚 比赛成绩 &#xff08;等出来我就写这里&#xff09; 感觉最多省二 估计没省一了555 赛前准备 赛前把蓝桥杯课基本都刷了 &#xff0c; 但是还是感觉有点慌 刷题经验 …

【网络原理】网络通信与协议

✨个人主页&#xff1a;bit me&#x1f447; ✨当前专栏&#xff1a;Java EE初阶&#x1f447; 目 录一. 网络发展史二. 网络通信基础1. IP地址2. 端口号3. 认识协议&#xff08;核心概念&#xff09;4. 五元组5. 协议分层6. 封装和分用一. 网络发展史 独立模式&#xff1a;计…

springboot从2.1.3升级到2.3.5后控制台自动输出http请求日志RequestResponseBodyMethodProcessor

springboot从2.1.3升级到2.3.5后控制台自动输出http请求日志RequestResponseBodyMethodProcessor和RequestMappingHandlerMapping推荐使用第二个方案简单 明了 方便 快捷方案一第一步定义TurboFilter第二步配置logback方案二 直接配置logback的配置XML推荐使用第二个方案简单 明…

【三十天精通 Vue 3】 第四天 Vue 3的模板语法详解

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: 三十天精通 Vue 3 文章目录引言一、Vue 3 模板语法概述1. Vue 3 模板语法的简介2. Vue 3 模板…

Openlayers(五)点位聚合Cluster

Openlayers&#xff08;五&#xff09;点位聚合Cluster 1.业务问题 由于点位在地图上显示过多&#xff0c;会造成页面卡顿、点位标注信息相互叠加导致看不清 优化后效果 不断放大层级 2.聚合类Cluster OpenLayers 中聚合是通过 ol.source.Cluster 实现&#xff0c;聚合的原…

Flink的窗口机制

窗口机制 tumble&#xff08;滚动窗口&#xff09; hop&#xff08;滑动窗口&#xff09; session&#xff08;会话窗口&#xff09; cumulate&#xff08;渐进式窗口&#xff09; Over&#xff08;聚合窗口&#xff09; 滚动窗口&#xff08;tumble&#xff09; 概念 滚…

系统复杂度之【高性能】

系统复杂度之【高性能】 今天我们来谈一谈系统复杂度的根源之【高性能】 对性能的不懈追求一直是人类科技持续发展的核心动力。例如计算机&#xff0c;从电子管计算机到晶体管计算机&#xff0c;再到集成电路计算机&#xff0c;运算性能从每秒几次提高到每秒几亿次。然而&#…

VUE_学习笔记

一、 xx 二、模板语法 1.模板语法之差值语法 &#xff1a;{{ }} 主要研究&#xff1a;{{ 这里可以写什么}} 在data中声明的变量、函数等都可以。常量只要是合法的javascript表达式&#xff0c;都可以。模板表达式都被放在沙盒中&#xff0c;只能访问全局变量的一个白名单&a…