环境变量基础

文章目录

  • 1.环境变量概念
  • 2.环境变量查看
  • 3.环境变量修改
  • 4.环境变量组织
  • 5.环境变量接口

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可执行文件的所在地,还有其他的地址,使用“:”进行分割
    
  2. 还可以使用命令env来查看当前系统的所有环境变量,这里输出结果有很多,可以看到所有的环境变量及其值(无法查看shell环境变量)

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

    $ limou=123456789
    $ set > text
    $ cat text | grep limou
    limou=123456789
    

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
    

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

    $ limou=1234567
    
    $ echo $limou
    1234567
    $ env | grep $limou
    
    $ export limou
    
    $ env | grep $limou
    limou=1234567 
    

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

  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;
}

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

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

5.环境变量接口

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

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

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

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

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

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

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

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

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

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

你可能感兴趣的:(操作系统学习笔记,linux)