Linux---环境变量

发布时间:2026/9/7 3:37:17
Linux---环境变量 基本理解环境变量⼀般是指在操作系统中用来指定操作系统运行环境的⼀些参数环境变量可以理解为“系统或程序运行时用的‘隐藏小助手’”它们像标签一样贴在系统或程序背后默默提供关键信息让程序能正确运行。例如你刚搬到一个新城市需要快速适应生活。你会在手机里存些重要信息超市地址相当于PASH方便你随时找到最近的超市买日用品。默认快递地址相当于HOME别人寄东西时直接填这个地址不用每次重复。环境变量就是这类“系统级的快捷信息”程序或系统需要它们时直接调用不用每次都手动输入。再例如1.你在终端输入c命令但系统不知道c安装在哪里会报错“命令未找到”。而通过PATH环境变量告诉系统“C在/usr/bin/cpp 这个目录下”这样这个命令就不需要指定路径可以直接执行。2.程序需要保存文件但不知道存到哪里可能乱存到系统目录。而HOME这个环境变量指向你的用户目录如/home/yourname程序会自动把文件存到你的“家目录”里。类似你快递寄存地点为“XX小区X栋X室”这那该地址设置为默认地址之后以后就不需要每次都告诉快递员你的地址。命令行参数之前的学习中我们找到 main是程序的入口但其实main函数不是第一个被执行的函数它也是被其他的函数所调用的_start是程序真正的入口点main通常由_start间接调用但具体实现与具体的操作系统与编译器有关。所以main函数里面也可以有参数的只不过这个参数是可写可不写的。只不过命令行参数并非所有程序都需要如果程序不需要参数强制要求参数会增加代码复杂度。如下main函数第一个参数argc是一个int类型的变量第二个参数argc是一个char*类型的指针数组。 如果我们把argc里面的内容都打印出来可以发现打印的结果是我们的程序名./code。而如果我们打印的时候像指令一样带参数的话 对应的参数也会被打印出来所以命令行输入的参数会以空格为分隔 把输入的内容划分为多份分别放入argv这个char*指针数组当中而第一个参数argc统计的就是里面元素的个数在argv数组中需要以NULL为结尾。假设我们期望我们的code程序的使用方式为code [-a/-b/-c](只能带一个参数 -a/-b/-c)其他方式都是错误的使用错误就会告诉使用者正确的使用方法。如下我们根据argv及argc的数据就能设计上面这样的code程序。main的命令行参数 是实现程序不同子功能的方法我们也就可以理解了 指令为什么通过不同的参数就可以执行不同的运行结果。具体环境变量PASH自己的程序与指令的区别既然指令就是按照这样的方式来实现的但是在使用上还是和我们有差别我们执行我们自己写的code程序的时候需要用 ./code的方式来执行(通过路径的方式找到当前目录下的code程序)而我们执行指令的时候不管在哪个目录下却可以直接ls pwd使用 却不用带他们的路径。而如果把我们自己的程序拷贝到 /usr/bin路径下(需要root权限)就会发现我们自己的程序执行时候不需要带路径了就像指令一样可以直接执行 并且像指令一样在任何目录下都可以直接执行那么上面这样的情况是为什么呢其实这就是因为系统当中存在环境变量的原因执行程序需要带路径而自带的指令在 /usr/bin路径下通过环境变量PATH可以直接找到所以把我们自己的程序放到这个路径下也可以不带路径了。PATH系统中搜索指令的默认路径查看环境变量env查看所有环境变量环境变量包含 名字内容如下通过env可以看到里面有很多的环境变量环境变量 显示的方式是等号左边是名字等号右边是内容。echo $具体环境变量名字查看具体的环境变量内容如上面查看PASH环境变量的内容看到里面的内容是多个路径 路径之间以冒号为分隔划分成了多条路径。而我们在执行一个命令的时候如果没有手动指定路径就会优先在PASH第一条路径下找如果没找到就看下一个路径以此类推如果所有路径找完了还没有找到就会报not found这样的错误 。所以这就能解释了上面的现象(code不在/usr/bin路径下直接使用会报not found而把code放到/usr/bin路径下直接使用可以正常执行)就是因为/usr/bin路径在PAH环境变量中既然code程序放到/usr/bin路径下可以直接使用 是因为该路径在PATH环境变量里面那么如果把code所在的路径直接放到这个PASH环境变量里面是不是code也就能直接执行了是的接下来就来测试一下。给PASH环境变量添加新路径添加方式PATH$PATH:新添加的路径$PATH就是原有的PASH里面的路径如果不加$PATH直接PATH新添加的路径那么原有的PATH下的路径就没有此时ls这样指令就不能直接执行了(但是pwd、cd这些能执行 因为他们是最后提到的内建命令)当然如果重启一下Xshell后PATH会恢复原有的路径。如何理解环境变量(存储角度) 环境变量从哪里来之前学习我们知道当一个用户登陆的时候操作系统会给我们创建一个bash进程。而bash就会从系统当中读取所有的环境变量信息然后再bash进程内部形成一张表---环境变量表 。所以结合命令行参数表和环境变量表 此时我们执行 code -a这样的命令的时候(没有手动带路径)1.会先以空格为划分把输入的code -a分为两块(code 和 -a)分别放到argv中的对应位置中。2.然后看argv[0]也就是程序名称的目录是否在环境变量表中的PATH路径当中如果在就创建子进程然后执行它如果不在报not found。环境变量最初在哪环境变量内容存储在bash进程中而bash进程是在登陆用户的时候系统分配的那如果不登录用户不就没有环境变量环境变量最初在哪环境变量最开始是从系统相关配置文件中来的bash进程创建的时候会从系统配置文件中读取环境变量然后加载到自己进程当中。如下系统给每个用户的家目录下存在些bash隐藏文件/.bash_profile、/.bashrcz这两个用户级配置最终会调用到系统级配置/etc/bashrc来加载环境变量。总结所以一个bash进程会有两张表(命令行参数表 环境变量表) 通过自动动态申请。而之前的学习中我们知道了一个用户登陆就会被系统分配一个bash进程那么如果有10个用户登陆就会被分别10个bash进程而每一个bash进程都会有这两张表命令行参数表来读取命令行的各种参数而环境变量表在进程被创建的时候就会从系统的配置文件中读取环境变量填充到自己的环境变量表当中。这样一个命令被执行的时候就会优先通过空格把输入的命令划分为多块内容然后放到命令行参数表当中而argv[0]就是程序的名称如果该程序没有自己带路径就会看程序名称所在的目录是否在环境变量表中的PASH里面有就执行没有就提示not found而bash进程退出的时候会把两张表给释放但是环境变量还存在系统的配置文件当中下次创建bash时候还可以重新加载。更多的环境变量之前指令部分我们知道cd ~可以直接到家目录下其实就是通过环境变量HOME。cd ~ 作为两个字符串到了命令行参数表bash进程就知道我们执行的是cd命令并且参数是~就把~替换成了HOME的内容。HOME当前用户的家目录SHELL显示当前用户的默认 Shell 路径USER当前用户是谁LOGNAME当前登陆用户是谁su和su -的区别之前很常用的命令 (ctrlr、上下键、!v) 这些能使用就是因为bash把我们历史的命令记录了下来而系统不可能把我们所有的几万几十万条命令都记录下来只会记录最新的1000条 这个数字就是HISTSIZE里面记录的数字 。HISTSIZE历史命令存储条数history该指令就会打印下面历史的指令HOSTNAME打印当前主机名LS_COLORS配色的信息例如我们有的文件内容打印出来时彩色的PWD当前shell所在的路径OLDPWD上一次的路径所以cd -可以回到上一次的路径下就类似于cd~回到家目录获取环境变量的方法上面我们提到了下面这两种env查看所有环境变量echo $环境变量名称查看具体的环境变量自己导入/去除环境变量export自己导入的环境变量unset去除的环境变量代码方式获取环境变量的三种方式1.main参数开始的命令行参数那里我们知道了在main函数中可以有两个参数其实main函数里面还可以有第三个参数---char* env[] 它就是环境变量表是通过父进程bash创建子进程时继承而来的 (之后学习会详细了解到)。父进程bash在创建的时候就会通过配置文件把系统的环境变量加载到自己的进程当中而这里的子进程完全就是从父亲那里继承而来的如果通过export往父bash里面增环境变量或者去环境变量子进程得到的是完全一模一样的。而如果此时子进程再有一个自己的子进程这个孙进程仍然会继续继承它父进程的环境变量所以环境变量具有全局特性那么main函数既可以没有参数有可以有一个两个或者三个参数 是怎么做到的呢在命令行参数中提到main函数不是第一个被执行的函数在linux中第一个被执行的是_startmain函数被_start执行而_start会首先知道main函数里面写了几个参数然后就会调用对应不同个数参数的main函数。2.系统调用 getenvgetenv通过环境变量名字获取该环境变量的内容获取成功返回环境变量名字对应的内容没找到返回NULL 。所以基于此我们就可以设计一个程序只有指定的用户才能执行的代码即使root账户也不可以。我们知道bash可以获取环境变量USER(当前用户是谁)子进程会继承得到父进程的USER 然后通过getenv来获取对应的USER看其内容是否为yx只要是yx才会执行否组不能执行。3.environenviron是一个的全局变量它存储了当前进程的所有环境变量指向环境变量表 是一个二级指针因为环境变量表里面存的是一级指针。推荐第二种方式因为第一第三种通常都是访问所有的环境变量而第二种可以访问指定的环境变量。理解环境变量的特性1.环境变量具有全局性这在上面的获取环境变量的main参数方式中也提到过因为进程会继承父进程的环境变量2.本地变量如下我们直接在命令行输入 i10 此时用类似打印具体环境变量方式那样打印发现也可以打印出它而不能用env来查看因为它不是环境变量可以通过set来找到set显示环境变量本地变量bash会记录这两种变量。下面是两个本地变量 PS1的前面就是命令行的格式 PS2可以实现一行的内容分行来写本地变量与环境变量区别在与不会被子进程继承 只在bash内部被使用unset i取消本地变量此时export i把i直接从本地变量变为环境变量新的环境变量通过export指令导入到了bash进程当中但是指令不是创建一个子进程容纳后程序替换执行的那么如果export是bash的子进程那这不就子进程把数据放到父进程环境变量表中了但是进程不是直接具有独立性吗父进程可以把数据给子进程而子进程是不能把数据给父进程的。那它怎么做到的因为export是内建命令不会创建子进程而是让bash自己亲自执行。而之前环境变量PASH在被新路径替换掉原有的所有路径后ls这样的命令就不能执行了而cd、pwd这些还能执行就是因为他们也是内建命令只要bash能运行他们就能运行。