• 3环境变量


    前言

    大家一开始学习Linux时候,是否对其各种命令感到过好奇,为何这样输入不同就会执行不同,他的底层实现逻辑到底是怎么样的呢?

    在解答这个疑惑之前,我们需要学习环境变量以及怎样利用


    1. 概念引入

    当我们写好一个程序并进行编译链接后,需要使用命令./二进制文件名运行,而我们前面每次查看进程pid时候都是用的

    ps -ajx | head -1 && ps -ajx | grep 二进制文件名(以StatR.exe举例)
    
    • 1

    但Linux系统给我们显示的确是./StatR.exe

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E12KGBFu-1668514789267)(https://gitee.com/du-weiwei/typora/raw/master/image-20220308230248256.png)]

    (./StatR.exe是我们的运行的进程,下面是grep命令的进程)

    通过这个现象我们可以看出运行中的程序,进程,指令等各种称呼在Linux系统中其实是一个概念,都为进程,既然是一个概念,为何像ls pwd ps 等命令不需要加./,而我们自己写的程序就需要呢?可以不加./吗?

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ifkwc3RU-1668514789269)(https://gitee.com/du-weiwei/typora/raw/master/image-20220308231354244.png)]

    可以看到,如果不加./告诉linux执行指令StatR.exe,OS就会提供命令找不到的错误.

    也就是说Linux在执行StatR.exe这个命令之前去了某个地方查找,但是没有找到.

    那这个地方是什么呢? PATH.


    2. 环境变量PATH

    环境变量说到底也是变量,即某种类型的一个具体实例化,就像我们学习C语言时候的变量一样,如int a,a就是变量;

    linux系统中,定义变量的方法是变量名="字符串内容",打印变量内容的方法是echo $变量名,注意美元符号不可以丢掉,其作用是提醒echo这是一个变量

    test="hello everyone,welcome to my world";
    echo $test
    
    • 1
    • 2

    运行以后结果为:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gHA89F40-1668514789269)(https://gitee.com/du-weiwei/typora/raw/master/image-20220309110746671.png)]

    既然PATH是环境变量,那么它的内容是什么呢,我们利用echo进行展示.

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VeB5G5XP-1668514789269)(https://gitee.com/du-weiwei/typora/raw/master/image-20220309103249069.png)]

    可以发现PATH中有很多路径,也就是说,当我们执行命令时,linux会先去PATH里面的各个路径中查找是否会有该指令,如果有就执行,反之就会报错Command not found;

    因此我想要不加./运行程序StatR.exe,就只有把该名字放进PATH中的其中一个路径中,这里提供了两种方法:

    • 把当前指令文件添加到环境变量PATH ,通过cp 命令

      •   cp ./StatR.exe /home/MakeBigMoney/bin
        
        • 1
    • 把当前路径添加到环境变量PATH, 通过PATH=$PATH : 当前路径

      •   PATH=$PATH:/home/MakeBigMoney/linux_class/class1进程
        
        • 1

    当执行完毕上面的任何一种方法后就达到了我们的需求

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EVUjGlIn-1668514789270)(https://gitee.com/du-weiwei/typora/raw/master/image-20220309113829417.png)]

    所以

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

    了解了PATH环境变量以后,博主这里告知还有环境变量HOME , SHELL等,大家自行去尝试下打印他们的内容;


    3. 本地环境变量与系统环境变量

    环境变量分为两种类型,分别是本地环境变量与系统环境变量

    上文所提到的由linux自带的变量(PATH,HOME,SHELL)等都是系统环境变量,不随着用户的改变而改变,而我们自定义的如test就是本地环境变量.

    本地变量的定义方式: 变量名="字符串"

    dog="I have a dog"
    
    • 1

    系统变量的定义方式:export 本地变量名或者export 变量名="字符串"

    export pig="I have a pig"
    
    • 1

    其中系统变量可以被子继承使用,具有全局属性,本地变量不可以被子继承使用,不具备全局属性(命令行中运行的大部分指令都可以说是解释器bash的子进程)下面演示:

    这里提供了一个获取系统环境变量内容的函数getenv(),只需要输入用双引号包含起来的变量名,就可以打印;

    //该程序名为:proc
    #include 
    #include 
    #include 
    int main()
    {
        printf("%s",getenv("pig"));
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GfjRrUvi-1668514789270)(https://gitee.com/du-weiwei/typora/raw/master/image-20220309132427257.png)]

    如果改成dog,会发现报段错误

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D1uvyRH4-1668514789271)(https://gitee.com/du-weiwei/typora/raw/master/image-20220309132517603.png)]

    如果把dog变成环境变量,发现又可以正常运行

    因为./proc是bash的子进程,而子进程只能使用系统环境变量,所以一开始的dog并不可以被使用;


    4. set 和 env

    set: 可以显示系统环境变量和本地定义的shell(本地)变量,如果如果不加任何参数,默认全部(系统和本地变量)显示

    dog="hello ,I have a dog";
    export ppig="hello ,I have a ppig";
    set | grep dog  && set | grep ppig;
    
    • 1
    • 2
    • 3

    dog是本地shell变量,ppig是环境变量

    在这里插入图片描述

    env: 只可以显示系统环境变量,如果如果不加任何参数,默认全部(指系统变量)显示

    fish="hello ,I have a fish";
    export tree="hello ,I have a tree";
    env | grep fish;
    env | grep tree;
    
    • 1
    • 2
    • 3
    • 4

    因为fish不是系统变量,所以enc无法显示

    在这里插入图片描述

    小问题: 既然fish是本地变量,请问echo $fish是否可以显示其内容,如果可以,请问是否和上面说的子进程无法使用本地变量矛盾?

    答: echo可以显示本地变量内容,但是并不矛盾.因为echo,set,env,export等命令不是bash的子进程,他们是shell的内建命令,即shell程序内部的一个函数而已,而本地变量只能在shell内部被访问,所以echo可以访问fish且不矛盾


    5. main函数带参数

    main函数其实是可以带参数的,而它带参数的需求就是访问环境变量和指令;

    main函数的参数有三个

    int main(int argc,char* argv[],char* env[]) // 如果不写参数就全不写,如果想省略参数,一般只省略最后一个
    
    • 1

    argc用于表示数组argv元素数量,argv存储的是外部命令行指令,env存储的是所有系统环境变量

    说到这里,大家可能突然明白了linux系统是怎么接收各种指令的了,没错,就是利用的main函数参数,这里示范一个利用main函数接收外部linux指令的程序(程序名为rechive):

    #include 
    #include 
    int main(int arc,char* argv[])
    {
        for(int i = 0;i<arc;i++)
        {
            printf("arc[%d]: %s\n",i,argv[i]);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    问题:main函数带参数的好处?

    可以帮助我们设计出利用同一个程序便可以有不同的业务功能!(可以通过获取外部不同的指令,进而完成不同的功能)

    第三个参数到底获取的是什么呢?

    我们第四小节介绍了set和env,而第三个参数就是获取了所有的env(直接在linux中运行env命令的时候)

    char* argv[] 和 char* env[]的数组都是以一个空字符结尾.其ASCII码值为0;以env为例,作图:

    在这里插入图片描述


  • 相关阅读:
    STM32CubeMX学习笔记(47)——USB接口使用(MSC基于内部Flash模拟U盘)
    万字 HashMap 详解,基础(优雅)永不过时
    Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
    Stream流中的 mapToInt()方法
    spark RDD转换算子 sample
    修改vscode的相对路径计算逻辑
    kvm虚拟机出现启动不了,NOT available,PV大于分区
    Linux CentOS 8(磁盘容量配额(Quota))
    react native使用5-搭建ios环境
    1158 Telefraud Detection – PAT甲级真题
  • 原文地址:https://blog.csdn.net/m0_51723227/article/details/127873075