• 环境变量基础


    1.环境变量概念

    首先要知道几个事实:

    1. Linux里面使用的命令行指令,也是经过代码编写产生的可执行文件。而在Linux下的任何文件路径都可以使用这些指令,那能不能让我们自己编写的代码也这样呢?答案是可以,不过需要使用环境变量。
    2. 在编译C/C++代码的时候,我们是不知道链接时期需要的的动态静态库在哪里的,都是照样可以链接成功,生成可执行程序,原因也是有相关环境变量帮助编译器进行查看。

    环境变量是指在操作系统中用来指定操作系统运行环境的一些参数(类似语言的全局变量),环境变量通常具有某些特殊用途,在系统中通常具有全局的特性。

    下面是一些常见的环境变量:

    1. PATH:指定命令的搜索路径

    2. HOME:指定用户的主工作目录(指令cd ~就是根据HOME变量来进行确认的)

    3. SHELL:当前Shell,其值通常为/bin/bash

    4. HISTSIZE:其值为设置shell历史记录大小的变量(使用history指令可以查看HISTSIZE条历史指令)

    5. LS_COLORS:环境变量是用于设置ls命令在终端中显示不同文件类型和属性时的颜色的变量。通过指定不同文件类型和属性对应的颜色码,可以使文件在终端中以不同的颜色进行区分和显示

    6. LOGNAME:记录登录的用户名

    7. PWD:保存当前的路径

    Linux中的环境变量有很多,基本都是独立工作的,各有各的功能(在Windows操作系统里也是有环境变量的)。

    2.环境变量查看

    1. 使用命令echo $NAME即可查看对应变量的情况,注意需要带上$符号。

      $ which pwd
      /usr/bin/pwd
      
      $ echo $PATH
      ...:/usr/bin:... #这里可以找到pwd可执行文件的所在地,还有其他的地址,使用“:”进行分割
      
      • 1
      • 2
      • 3
      • 4
      • 5
    2. 还可以使用命令env来查看当前系统的所有环境变量,这里输出结果有很多,可以看到所有的环境变量及其值(无法查看shell环境变量)

    3. set命令则是显示本地定义的shell变量和环境变量(关于shell变量后面有提及)

      $ limou=123456789
      $ set > text
      $ cat text | grep limou
      limou=123456789
      
      • 1
      • 2
      • 3
      • 4

    3.环境变量修改

    如果我们想要实现我们自己编写的可执行程序和Linux内置指令一样的使用效果,有两种方法:

    1. 把您自己写的可执行程序放进PATH环境变量中的文件路径下,这样就可以像使用Linux指令一样使用自己编写的可执行程序(一般放在/usr/bin下比较多,这种行为叫做“给系统安装程序”,但是这种做法不建议,有可能污染操作系统)。

    2. 还有一种方法是使用命令export <环境变量>=$<环境变量>:新值配置PATH环境变量,这样操作不会污染到系统的文件。如果使用命令unset 某环境变量可以清除某个环境变量,如果使用unset PATH后就会发现其他的Linux指令都无法使用了,不过不用担心,下次登录还是会恢复默认的PATH值的,这是因为系统再重新登录的时候,会重新读取保存环境变量的配置文件(也就是家目录下的.bash_profile文件),而父进程bash会重新加载环境变量。

      另外,可以使用export指令将已经存在的shell变量转变为环境变量,只需要使用export <已经存在的shell变量>即可。

      补充1:实际上对应环境变量这样的“系统变量”,还有一个“本地变量”,即:shell变量,就是直接在bash定义一个变量,这个变量的值可以使用echo $指令查看,但不能使用env命令查看,因为它还不是环境变量,其作用域只在bash父进程中,还没有被其他子进程继承。

      补充2:不过,既然不能将shell变量继承给子进程,那么在父进程下运行的echo不也是bash的子进程么,它是怎么读取到我们设置的shell变量的呢?如果我们使用PATH=""PATH清空,就会惊奇发现,其他大部分命令都失效了,但是echo命令依旧可以正常打印shell变量。

      $ limou=123456789
      $ echo $limou
      123456789
      
      $ PATH=""
      $ echo $limou
      123456789
      $ echo $PATH
      
      $ echo $HOME
      /home/ljp
      $ echo $SHELL
      /bin/bash
      
      $ ls
      bash: ls: No such file or directory
      
      $ touch
      bash: touch: No such file or directory
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19

      这是因为在Linux中,大部分的常规命令都是磁盘上真实存在,并且需要由fork()创建子进程来执行的,但是还有一些命令不需要创建子进程来执行,这种命令由bash自己来执行,也叫做bash的内建命令。因此echo命令不会创建子进程,直接在bash内执行,当然可以获取bash自己读取的到的变量(环境变量和shell变量)。这样的内建命令有很多,包括pwdexport等等。

      $ limou=1234567
      
      $ echo $limou
      1234567
      $ env | grep $limou
      
      $ export limou
      
      $ env | grep $limou
      limou=1234567 
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      上述环境变量添加操作实际上是加载到内存中,而不是加载到环境变量配置文件中。

    3. 直接将环境变量的名字和值以export <环境变量名>=<环境变量值>的形式写入.bash_profile则可以达到登录即可使用自定义环境变量的目的,但是也有污染的可能。

    注意:一般情况下,在Linux命令行中修改环境变量只适用于本次会话(本次登录),一旦退出登录就无效了,不过如果修改的是保存环境变量的文件就会永久有效。

    4.环境变量组织

    环境变量通常使用环境变量表组织起来,而环境表是一个字符指针数组,每个指针指向一个以\0结尾的环境变量字符串,并且最后一个元素指向NULL表示结尾,这样做就可以将所有环境变量组织起来。

    因此我们编写代码的时候可以使用以下的main()接口来接受和操作运行程序时使用的选项和环境变量:

    #include 
    #include 
    int main(int argc, char* argv[], char* env[])
    {
        if(strcmp(argv[argc - 1], "-order") == 0)
        {
            printf("---------\n");
            for(int i = 0; env[i]; i++)
            {
                printf("%s\n", env[i]);
            }
            printf("---------\n");
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这里的env数组也就对应上面提到的由环境变量构成的char*类型数组,该数组视NULL的结尾。

    上面的mian()程序被系统启动后,接受了两张表,一是命令行参数表,二是环境变量表

    5.环境变量接口

    在上面的代码中,main函数可以带上三个参数,第三参数实际上就是有关环境变量的参数(前两个数选项个数和选项字符数组):

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

    除了这种方法还可以使用unistd.h内定义的environ[]全局数组来获取环境变量的值。

    但是最常用的是使用stdlib.hgetenv()函数,可以根据参数来获取对应的环境变量值(其参数是想获取环境变量的变量名字符串)。

    还有一些其他有关环境变量的接口,您可以自行探索一下。

    补充1:一般main()的环境变量参数是由父进程继承过来的,父进程也是从它自己的父进程获取的,因此环境变量最终在bash进程获取,而所有进程的父进程是当前bash。这也就是环境变量之所以具有全局属性的本质原因,而env[]参数也是依靠父进程传参的。

    这种父子传递关系,您可以在bash下自己创建一个自定义的环境变量,然后使用C语言库内的getenv()函数读取环境变量来验证。

    欸,但是父进程的环境变量又是那里来的?只能是操作系统读取配置文件了。

    补充2shell变量没有办法在C代码中使用getenv()获取。

    shell变量实际上最常用的场景是在shell脚本里,这个shell脚本我们以后再提及。

  • 相关阅读:
    Charles基础使用指南
    简单有效的评估大小鼠的认知能力、空间记忆和学习能力——大小鼠T迷宫和Y迷宫
    Sentinel授权规则和规则持久化
    “我们为什么要做 iVX ? ” ——访 iVX CEO 孟智平 了解 iVX 企业文化
    《自卑与超越》生活对你应有的意义
    SpringBoot--@ModelAttribute--使用/实例
    华纳云:轻量云服务器怎么安装SSL证书
    JS数组对象去重
    使用VC++输出调频波
    随笔Kubernetes
  • 原文地址:https://blog.csdn.net/m0_73168361/article/details/133905465