【Linux】Linux的环境变量(PATH、env、子进程继承环境变量等)

news2024/10/7 2:31:00

文章目录

    • 环境变量
      • 1、从一个小案例认识环境变量PATH
      • 2、常用的环境变量相关指令与系统调用
      • 3、子进程如何继承环境变量的?
      • 4、测试其它环境变量

环境变量

1、从一个小案例认识环境变量PATH

我们在shell中通过file查看文件信息,看到我们常使用的指令都是可执行文件(exe)。

在这里插入图片描述
我们自己编写的程序,毫无疑问也是可执行文件。

在这里插入图片描述

我们发现一个问题,在软件执行的时候,我们在任何路径下都可以使用ls、pwd等系统自带的,而我们自己的软件需要确定路径才能允许。

如果要让自己写的程序直接输入程序名就能运行,该怎么办?

  • 通过环境变量PATH
    命令echo $PATH 查看系统的所有指令的路径。

    执行的程序的路径都在PATH变量里,我们可以把我们程序的路径放在里面,这种环境变量属于一种内存级变量,重启会恢复。
    通过export PATH=$PATH:添加的程序所在路径
    :前面$PATH代表原先的添加,:后代表添加程序所在的路径。
    在这里插入图片描述

  • 通过添加到指令空间

    我们所用的系统指令文件一般都是在/usr/bin目录下的。
    在这里插入图片描述
    我们可以将我们的程序拷贝到系统安装指令的空间/usr/bin中。
    在这里插入图片描述
    在这里插入图片描述

    但是这种方式非常不推荐,因为我们写的程序没经过测试,可能会污染指令池。
    所以测试完,记得删除。
    在这里插入图片描述

通过这个小测试,我们知道了如果我们想通过程序名直接运行程序,需要让操作系统知道我们程序在哪。
上面第二种方式很好理解,就是作为文件放在和其它系统指令所在一样的空间。
那么 第一种方式通过环境变量是如何做到的? 以及

什么是环境变量?PATH具体是什么?

首先
一个软件需要运行 >> 操作系统就必须要找到可执行程序 >> 需要在特定的路径下找 >> 操作系统启动时默认从配置文件中读取曾经将软件安装到了哪些路径 >> 当软件启动,操作系统就将对应路径导入到内存里构建了一个内存级变量 >> 环境变量PATH因此产生
(冯诺依曼体系规定,程序需要运行必须先加载到内存。)

其中配置文件就是每个用户目录下的 .bash_profile,在用户每次登录系统时被读取,里面所有命令都会被shell执行。包括环境变量的配置命令。
在这里插入图片描述

PATH当操作系统在启动命令行解释器shell的时候,导入到shell的上下文当中,当我们执行相应的指令时,就必须通过PATH的方式,让系统通过PATH指定的路径去执行对应的可执行程序。

并且,操作系统在启动bash为我们做一些命令行解释的时候,必须提前准备一些变量,变量中包含单个或多个程序需要用到的信息,这些变量就是环境变量。

综上:简单来说,环境变量是一堆操作系统为解释命令的变量,其中PATH是记录程序所在完整路径的变量。

2、常用的环境变量相关指令与系统调用

  • env
    首先通过env可以查看系统在启动后默认导的所有环境变量。
    这里截取一部分
    在这里插入图片描述
    当然也有PATH
    在这里插入图片描述

  • set、unset和本地变量
    首先本地变量和环境变量定义名字建议大写,内容建议加双引号!
    本地变量可以直接在命令行定义,因为是本地变量,所以在环境变量中是没有的。
    在这里插入图片描述
    通过set命令显示所有的环境变量和本地变量,所以我们确定12345添加导了本地变量中。
    在这里插入图片描述
    通过unset取消环境变量或者本地变量
    在这里插入图片描述

    为什么可以在命令行中定义环境变量?

    程序可以动态开辟空间,字符串占用空间是空间数据。

    ==
    进程是程序也可以动态开辟空间,环境变量作为字符串空间数据,放在空间中。
    (bash本身就是个进程,环境变量其实就是字符串)

  • export
    export 设置一个新的环境变量,通过这个指令可以将本地变量设置为环境变量。
    在这里插入图片描述

再来看一个系统调用函数。

  • getenv()
    getenv依据name字符串在环境变量表中查找,找到返回指向环境变量的指针。(前面也说过环境变量本质就是字符串)
    在这里插入图片描述
    先看一个小程序,测试环境变量中的USER。

      1 #include <stdio.h>  
      2 #include <unistd.h>  
      3 #include <string.h>  
      4 #include <stdlib.h>  
      5                                                                                                                                                   
      6 #define USER "USER"                     
      7 int main()                              
      8 {                                       
      9     char* who = getenv(USER);//获取环境变量USER         
     10     if(strcmp(who, "yzh") == 0)        
     11     {                                   
     12         printf("user: %s\n", who);      
     13     }                                   
     14     else                                                                                                                                       
     15     {                                                                                                                                          
     16         printf("Permission denied\n");                                                                                                         
     17     }                                   
     18     return 0;                           
     19 }
    

    在这里插入图片描述
    我们切回root然后运行程序,看到用户名不匹配了。
    在这里插入图片描述

    环境变量USER最大的意义,可以标识当前使用的Linux用户。
    其实环境变量USER,也参与了一些核实用户权限的实现。(比如用户访问其它用户的文件,通过USER来判断当前用户是否符合)

  • 子进程继承父进程
    我们再来看一个小程序

      1 #include <stdio.h>
      2 #include <unistd.h>
      3 #include <string.h>
      4 #include <stdlib.h>
      5 
      6 #define myval "HELLO"
      7 int main()
      8 {
      9     char* myenv = getenv(myval);
     10     if(NULL == myenv)
     11     {
     12         printf("%s, not found\n", myval);
     13         return 1;
     14     }
     15     else
     16     {
     17         printf("%s : %s", myval, myenv);                                                                                                        
     18     }
     19     return 0;
     20 }
    

    通过定义本地变量,然后运行程序,HELLO没有找到,这是对的。
    在这里插入图片描述
    将HELLO定义为环境变量,然后运行程序,找到,这也没问题。
    在这里插入图片描述

    看到结果后,我们来看一下问题。

    环境变量在bash中是可以直接查看的,这没问题,为什么在我们写的程序里也能查看呢?
    getenv()只是从环境中读取字符串,来获取对应环境变量的值的。我们的程序是如何会有环境变量的?

    其实bash本身是一个进程,我们写的程序是bash中的一个子进程,子进程继承父进程,这也就使得了环境变量具有全局属性。(使得适应不同应用场景,让bash为我们找指令、身份认证)。

3、子进程如何继承环境变量的?

从main函数开始说起,main函数其实也有参数,由父进程或是系统传的参。
这些参数其实叫命令行参数

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

用处:

  1. argc 是argv数组里指针的数量。
  2. argc是一个数组,里面有多个指向字符串的指针。

通过一个简单的程序来看它的作用。

  1 #include <stdio.h>
  2                                                                                                                                                     
  3 int main(int argc, char* argv[])
  4 {
  5     int i = 0;
  6     for(i = 0; i < argc; ++i)
  7     {
  8         printf("argv[%d] -> %s\n", i, argv[i]);
  9     }
 10     return 0;
 11 }

在这里插入图片描述

argv数组其实就是用来接收程序名和选项的,argc用来计数,shell将这整个字符串进行拆分,操作系统进行传参。(比如" ./myprocess -1 -2 -3 -4 -5 " 这一串字符串,拆成"./myprocess",“-1”,“-2”…)
其实和我们之前使用的ls -l,ls -l -a等一样,这种命令行参数的最大意义就是能够介绍命令行选项,让一个程序通过不同选项实现不同功能。

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

其实如果你写了这三个参数,系统会为你传两张表,一个是命令行参数表,一个是环境变量表。
没错,env就是一个一个环境变量的指针数组。
稍稍修改上面的程序

    1 #include <stdio.h>
    2 
    3 int main(int argc, char* argv[], char* env[])
    4 {
    5     int i = 0;
    6     for(i = 0; env[i]; ++i)
    7     {
    8         printf("env[%d] -> %s\n", i, env[i]);                                                                                                     
    9     }
   10     return 0;
   11 }

打印的结果就是所有环境变量(这里截一部分)
在这里插入图片描述

拓展一下,不传参获取环境变量的方式
通过第三方变量二级指针environ获取环境变量表。
(有人可能不理解为什么是二级指针:环境变量表是一个数组,数组里面存放很多一级指针指向环境变量,environ指向数组,是存放一级指针的指针,所以是二级指针。)
在这里插入图片描述

  1 #include <stdio.h>  
  2 #include <unistd.h>
  3 int main()
  4 {
  5     extern char** environ;                                                                                                                          
  6     for(int i = 0; environ[i]; ++i)  
  7     {                                      
  8         printf("%d:%s\n", i, environ[i]);  
  9     }                 
 10                       
 11     return 0;         
 12 }

在这里插入图片描述
结果也是打印所有环境变量(这里也是截取了一部分)

  • 最后解释一个现象!
    HELLO是我们定义的一个本地变量不能被子进程继承,echo命令是一个子进程,为什么echo能打印HELLO?
    在这里插入图片描述
    其实就是因为命令行参数读取HELLO。


总结:

1. 查看环境变量的方式有三种,getenv(),命令行参数,第三方变量environ。
2. 后面两个内容太多,具体变量也不好定位,所有其实还是getenv()用的多。

4、测试其它环境变量

环境变量具有全局性。

  • 环境变量HOME和~
    HOME是用来显示当前用户名所在路径

在这里插入图片描述在这里插入图片描述
在之前学cd命令的时候,有一个cd ~ 意思是到用户目录下。
通过echo ~我们发现~的信息和$HOME是一样的。
在这里插入图片描述

本章完~

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

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

相关文章

C++ 类的静态成员详解

目录 前言 一、类的静态成员 1.static关键字 2.静态成员变量 3.静态成员函数 二、程序样例 1.程序演示 2.程序截图 总结 前言 本文记录C中 static 修饰类成员成为静态成员&#xff0c;其中包括静态成员类别、作用和程序演示。 嫌文字啰嗦的可直接跳到最后的总结。 一、类的静…

特征提取 - 骨架、中轴和距离变换

目录 1. 介绍 骨架 skeleton 中轴变换 Medial axis transformation 距离变换 distance transform 2. 距离变换的代码实现 distanceTransform 函数介绍 normalize 函数介绍 取局部最大值 完整代码 3. comparation 1. 介绍 骨架 skeleton 骨架的定义&#xff1a;就是…

【毕业设计】33-基于单片机的直流电机的转速检测与控制设计(原理图工程+PCB工程+源代码工程+仿真工程+答辩论文)

typora-root-url: ./ 【毕业设计】33-基于单片机的直流电机的转速检测与控制设计&#xff08;原理图工程PCB工程源代码工程仿真工程答辩论文&#xff09; 文章目录typora-root-url: ./【毕业设计】33-基于单片机的直流电机的转速检测与控制设计&#xff08;原理图工程PCB工程源…

盘点国内主流数字孪生厂商!你了解几家?

在国内&#xff0c;主流的数字孪生解决方案厂商包括华龙迅达、精航伟泰、羚数智能、力控科技、华力创通、同元软控、优也科技、51world、卡奥斯、摩尔元数、易知微、木棉树软件等。由于中国数字孪生市场仍处于早期发展阶段&#xff0c;且受限于建模、仿真和基于数据融合的数字线…

基于单RGB相机的全新三维表示方法|NeurIPS 2022

随着深度学习的发展&#xff0c;基于单张RGB图像的人体三维重建取得了持续进展。 但基于现有的表示方法&#xff0c;如参数化模型、体素栅格、三角网格和隐式神经表示&#xff0c;难以构筑兼顾高质量结果和实时速度的系统。 针对上述问题&#xff0c;天津大学团队联合清华大学…

Linux用户管理

文章目录一. 引子二. 用户管理1. 用户切换2. 注销用户3. 添加用户4. 设置用户密码5. 删除用户6. 查询用户信息三. 用户组管理1. 新增用户组2. 新增用户时添加组3. 修改用户的组四. 用户和组相关文件1. /etc/passwd2. /etc/shadow3. /etc/group一. 引子 Linux是一个多用户、多任…

【JavaScript作用域】

JavaScript作用域1 本节目标2 作用域2.1 作用域概述2.2 全局作用域2.3 局部作用域3 变量的作用域3.1 变量作用域的分类3.2 全局变量3.3 局部变量3.4 从执行效率看全局变量与局部变量3.5 JS没有块级作用域4 作用域链1 本节目标 说出JavaScript的两种作用域区分全局变量和局部变…

TinyML:是否是FPGA在人工智能方面的最佳应用?

TinyML 也是机器学习的一种&#xff0c;他的特点就是缩小深度学习网络可以在微型硬件中使用&#xff0c;主要应用在智能设备上。超低功耗嵌入式设备正在“入侵”我们的世界&#xff0c;借助新的嵌入式机器学习框架&#xff0c;它们将进一步推动人工智能驱动的物联网设备的普及。…

机器学习:一文从入门到读懂PCA(主成分分析)

深度学习&#xff1a;PCA白化前置知识内积的几何意义基基变换不同基下的向量变换逆矩阵不同基下的空间变换方差协方差协方差矩阵协方差矩阵对角化特征值分解、空间变换主成分分析&#xff08;PCA&#xff09;两个原则公式推导求解流程代码实现PCA的优缺点优点缺点前置知识 维度…

【测试沉思录】18.如何测试微信小程序?

作者&#xff1a;雷远缘 编辑&#xff1a;毕小烦 一. 先知道小程序是什么 啥是小程序&#xff1f; “小程序是一种不需要下载安装即可使用的应用&#xff0c;它实现了应用 “触手可及” 的梦想&#xff0c;用户扫一扫或者搜一下即可打开应用。也体现了 “用完即走” 的理念&am…

[附源码]Python计算机毕业设计SSM基于Java的民宿运营管理网站(程序+LW)

环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 Maven管理等…

详解 Spring Boot 项目中的配置文件

目录 1. Spring Boot 项目中配日文件的作用是什么 2. Spring Boot 配置文件的两种格式 3. properties 配置文件 3.1 properties 配置文件的基本语法 3.2 properties 配置文件的分类 3.3 如何读取配置文件 3.4 properties 配置文件的优缺点分析 4. yml 配置文件 4.1 yml …

【JavaSE】初识泛型

大家好&#xff01;我是保护小周ღ&#xff0c;本期为大家带来的是 Java的泛型&#xff0c;会来大家初步了解什么是泛型&#xff0c;以及泛型的使用&#xff0c;感受一手泛型的思想&#xff0c;面向对象编程太爽了~ 目录 一、泛型是什么&#xff1f; 二、泛型的语法 三、包…

Java给图片增加水印,根据图片大小自适应,右下角/斜角/平铺

Hi&#xff0c;I’m Shendi 最近写自己的文件服务器&#xff0c;上传图片时需要自动增加水印&#xff0c;在这里记录一下 文章目录效果展示读取图片从 byte[] 读取图片获取画板绘制水印根据图片大小自适应水印大小右下角文字水印斜角水印平铺水印图片水印输出图片水印就是在图片…

《剑指 Offer 》—58 - I. 翻转单词顺序

《剑指 Offer 》—58 - I. 翻转单词顺序 注意&#xff1a;本题与151 题相同&#xff1a;https://leetcode-cn.com/problems/reverse-words-in-a-string/ 注意&#xff1a;此题对比原题有改动 文章目录《剑指 Offer 》—58 - I. 翻转单词顺序一、题目内容二、个人答案&#xf…

Git 打patch (打补丁)的使用

patch 的使用 一般是diff ,apply ,format-patch,am 1 生成patch git diff > test.patch 这个是打补丁(test.patch自己取的名字,这个命令可以看出没有指定修改的问题所以默认把所有修改的文件都打patch了,同时还需要注意,这里是本地修改的没有执行add缓存的) 如果想指定某…

FPGA实现图像对比度自动调整,提供2套工程源码和技术支持

目录1.算法原理介绍2.HLS算法实现3.工程1介绍&#xff1a;zynq7100实现4.工程2介绍&#xff1a;Kintex7实现5.上板调试验证6.福利&#xff1a;工程源码获取1.算法原理介绍 使用直方图均衡技术实现 使用直方图均衡技术将原始图像的灰度直方图从比较集中的某个灰度区间变成在全部…

学习axure都要经历哪个阶段,如何快速入门

作为初学Axure同学们&#xff0c;正在学习AxureRP在这个过程中&#xff0c;我们应该经历每个阶段&#xff0c;掌握每个阶段的特点&#xff0c;明确如何在不同阶段学习&#xff0c;这样我们才能快速做到axure快速掌握这个工具。还能根据自己的实际工作需要&#xff0c;掌握自己的…

关系抽取(二)远程监督方法总结

目录 前言 1. 远程监督关系抽取开山之作 1.1 介绍 1.2 训练过程 1.2.1 数据标注方法 1.2.2 训练方法 1.3 测试过程 1.4 思考 1.5 总结 2. PCNN 2.1 介绍 2.2 模型结构 2.2.1 文本特征表示 2.2.2 卷积 2.2.3 分段最大池化 2.2.4 softmax多分类 2.3 多实例学习的…

【elementUI样式】模态框中的el-select下拉框不跟随页面滚动问题

文章目录1.在el-select标签中设置:popper-append-to-body"false"2.样式穿透&#xff08;比较普遍的写法&#xff09;模态框中的el-select下拉框不跟随页面滚动问题在使用elementUI写界面的时候&#xff0c;偶然遇到了如下图所示bug当页面滚动的时候&#xff0c;el-se…