哈喽,编程搭子们!😜 又到了沉浸式敲代码的快乐时间~把生活调成「代码模式」,带着满满的热爱钻进编程的奇妙世界——今天也要敲出超酷的代码,冲鸭!🚀
在这里插入图片描述
✨ 我的博客主页:喜欢吃燃面
📚 我的专栏(持续更新ing):
《C语言》 |
《C语言之数据结构》 |
《C++》 |
《Linux学习笔记》

💖 超感谢你点开这篇博客!真心希望这些内容能帮到正在打怪升级的你~如果有任何想法、疑问,或者想交流学习心得,都欢迎留言/私信,咱们一起在编程路上互相陪伴、共同进步呀!

一.环境变量的概念

环境变量(Environment Variable)是操作系统级别的、可被所有进程(程序 / 命令)访问的动态参数。

  • 可以理解为环境的动态属性,只有进程运行时才可见。
  • 环境变量可以操作系统或人为修改,所以不同进程运行时的环境变量可能不同。
    修改方式分「临时(快速测试)」和「永久(长期生效)」,需根据场景选择
  • 通常具有全局性,类似C/C++的全局变量。

二.常见环境变量

1.PATH

  • 系统查找可执行命令的目录清单。输入命令时,系统会按此清单中的目录顺序查找对应可执行文件,避免输入完整路径。
:~/20260128$ $PATH
-bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin: No such file or directory

2.HOME

  • 当前用户的主目录路径。是用户个人文件、配置的默认存储位置(如 Linux 的 /home/用户名,即家目录)。

3.SHELL

  • 当前终端使用的 Shell 程序路径(如 /bin/bash、/bin/zsh),决定终端的命令语法、交互逻辑。

4. PWD

  • 英文 “Present Working Directory” 的缩写,代表当前工作目录的路径。执行 pwd 命令即读取此变量的值。

5.OLDPWD

  • 代表上一次工作目录的路径。由系统自动记录,配合 cd - 命令可快速切换回上一个目录。

三.获取环境变量

在 Linux 下,获取环境变量的方法可分为终端操作编程实现两类。

1.终端中获取环境变量

1.1 查看单个环境变量

直接通过 echo $变量名 读取,这是最常用的方式:

# 示例:查看HOME
echo $HOME
# 示例:查看PATH
echo $PATH

1.2 查看所有环境变量

  • env 命令:简洁列出所有环境变量(键值对形式)
    env
    
  • printenv 命令:功能与 env 类似,支持直接指定变量名(等价于 echo $变量名
    # 查看所有环境变量
    printenv
    # 查看单个变量(效果同echo $PATH)
    printenv PATH
    
  • set 命令:列出当前 Shell 的所有变量(包含环境变量 + 局部变量)
    set
    

1.3 查看进程的环境变量

查看正在运行的进程的环境变量(需知道进程 PID):

# 替换[PID]为目标进程的ID
cat /proc/[PID]/environ | tr '\0' '\n'

(注:/proc/[PID]/environ 中环境变量以空字符 \0 分隔,tr '\0' '\n' 用于转换为换行格式方便阅读)

2.编程中获取环境变量(以Linux例 )

2.1 C/C++

  • 通过 getenv() 函数(标准库 <stdlib.h>):
    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
        // 获取HOME环境变量
        const char* home = getenv("HOME");
        if (home != NULL) {
            printf("HOME: %s\n", home);
        }
        return 0;
    }
    
  • 也可通过 main 函数的第三个参数(envp)获取所有环境变量:
    #include <stdio.h>
    
    int main(int argc, char* argv[], char* envp[]) {
        // 遍历所有环境变量
        for (int i = 0; envp[i] != NULL; i++) {
            printf("%s\n", envp[i]);
        }
        return 0;
    }
    
  • 补充
    main 函数三个参数的核心作用
  1. argc:整数,记录命令行参数的总个数(包含程序名本身);
  2. argv[]:字符串数组,存储所有命令行参数(argv[0] 是程序名,后续是传入的参数);
  3. envp[]:字符串数组,存储程序启动时继承的所有环境变量(格式为“变量名=值”)。
    总结
  4. argc/argv 是程序接收命令行输入的入口;
  5. envp 是程序获取系统环境变量的原始方式;
  6. 三者都是操作系统在程序启动时传递给 main 函数的初始信息。

2. 2 Shell 脚本

直接使用 $变量名 读取,与终端语法一致:

#!/bin/bash
# 获取并打印HOME
echo "HOME: $HOME"

以上是 Linux 下获取环境变量的常用方法,终端操作适用于手动查看,编程方式适用于程序中动态读取配置。

四.linux下,环境变量和C/C++,进程的关系

1.基础逻辑:环境变量是「进程级」的配置,C/C++ 程序运行成进程后才关联环境变量

Linux 中环境变量不属于 C/C++ 代码本身,而是「进程的运行属性」:

  • 当你编译 C/C++ 代码生成可执行文件时,环境变量仅影响编译过程(比如 PATH 找编译器 gccLD_LIBRARY_PATH 找编译依赖的库),但不会被写入可执行文件;
  • 当你运行可执行文件(生成进程)时,操作系统会为这个进程分配一套环境变量(继承自父进程,比如终端),此时 C/C++ 进程才能访问/使用环境变量。

简单说:环境变量是进程的“运行时配置”,C/C++ 程序是“代码载体”,进程是“代码运行的实例”,环境变量绑定到进程而非代码

2. 核心关联1:环境变量的继承(进程间的传递规则)

C/C++ 进程的环境变量遵循「父→子」继承规则:

  1. 父进程(比如终端)启动时,会加载自身的环境变量(来自系统配置/用户配置);
  2. 当你在终端运行 ./a.out(C/C++ 可执行文件)时,终端作为父进程,会把自己的环境变量复制一份传给 a.out 对应的子进程;
  3. C/C++ 子进程拿到的是“副本”:修改自身环境变量,不会影响父进程(终端),也不会影响其他无关进程。

举例:

  • 终端(父进程)中设置 export TEST=123
  • 运行 C/C++ 程序(子进程),能读到 TEST=123
  • 程序中修改 TEST=456,终端里 echo $TEST 仍为 123。

3. 核心关联2:C/C++ 进程访问/修改环境变量的方式(接口层面)

C/C++ 标准库提供了专门接口,让进程操作自身的环境变量副本:

操作 常用接口 作用说明
读取单个变量 getenv("变量名") 从进程的环境变量副本中读取指定变量值,找不到返回 NULL
修改/新增变量 setenv("变量名", "值", 1) 新增或覆盖进程的环境变量(第三个参数 1 表示覆盖已有值)
删除变量 unsetenv("变量名") 从进程的环境变量副本中删除指定变量
读取所有变量 main 函数 envp 参数 直接获取进程启动时继承的所有环境变量(原始数组,格式为“变量名=值”)
全局环境数组 extern char **environ 全局变量,指向进程的环境变量数组(与 envp 等价,无需通过 main 参数传递)

关键特点:以上操作仅作用于当前 C/C++ 进程的环境变量副本,不会修改系统/父进程的环境变量。

4.核心关联3:环境变量对 C/C++ 进程的实际影响(场景层面)

环境变量直接决定 C/C++ 进程的运行行为,常见场景:

  1. 查找依赖库LD_LIBRARY_PATH 告诉 C/C++ 进程去哪里加载动态链接库(.so 文件),如果路径不对,进程会提示“找不到库”;
  2. 执行外部命令:C/C++ 进程中调用 system("ls") 时,PATH 决定系统去哪里找 ls 可执行文件;
  3. 配置程序行为:开发者可自定义环境变量(比如 APP_ENV=dev),C/C++ 进程读取后加载不同配置(开发/生产环境),无需修改代码;
  4. 系统级配置HOME 告诉进程当前用户的家目录(比如程序要写入用户配置文件时),LANG 决定字符编码(避免中文乱码);
  5. 编译/运行联动:编译时 CFLAGS/CXXFLAGS 环境变量可传递编译参数(比如 export CFLAGS="-O2"),gcc 会读取这些参数优化编译。

5.特殊场景:启动 C/C++ 进程时自定义环境变量

你可以在启动 C/C++ 进程时,临时给它指定专属环境变量(仅对该进程生效):

# 临时设置 MY_CONFIG=test,启动 ./a.out
MY_CONFIG=test ./a.out

此时 C/C++ 进程能读到 MY_CONFIG=test,但终端的环境变量中没有这个值,实现“进程专属配置”。

总结

  1. 环境变量是进程的「运行时配置副本」,C/C++ 程序运行成进程后,继承父进程的环境变量;
  2. C/C++ 可通过标准库接口读写当前进程的环境变量副本,无法修改系统/父进程的环境变量;
  3. 环境变量直接影响 C/C++ 进程的核心行为(找库、执行命令、加载配置等),是程序与系统交互的重要桥梁。

五.环境变量,本地变量,shell内建命令

三者属于Shell不同层级的概念:本地/环境变量是Shell存储的“数据”(键值对),内建命令是Shell自带的“指令”(可操作变量/执行功能),核心区别和关联用「数据vs指令」就能快速理解。

1. 核心三要素对比表(最直观,建议收藏)

概念 本质 作用范围 生命周期 核心操作命令 典型例子
本地变量 Shell的局部数据 当前Shell会话有效 关闭当前终端/退出Shell即消失 定义:var=值
查看:echo $var/set
name=linux
age=10
环境变量 Shell的全局数据 当前Shell+所有子进程有效 关闭终端消失(临时)/重启仍在(永久) 定义:export 变量=值
查看:echo $var/env/printenv
PATH=/usr/bin
HOME=/home/ubuntu
内建命令 Shell自带的指令 随Shell生效,无“范围”一说 Shell启动即存在,退出则失效 直接执行命令即可 cd/echo/export/set/unset

2.通俗拆解+关键区别(避坑核心)

2.1 本地变量:Shell的“私人小本本”

  • 理解:只给当前终端窗口用的临时数据,其他窗口、子进程都看不到,相当于自己的私人笔记,别人拿不到。
  • 关键:无需加export,直接变量名=值定义,仅当前Shell生效,子Shell(比如执行脚本、敲bash新建Shell)无法继承。
  • 实操:
    test=123  # 定义本地变量,无export
    echo $test  # 输出123,当前Shell能查到
    bash        # 新建子Shell
    echo $test  # 无输出,子Shell查不到本地变量
    exit        # 退出子Shell
    unset test  # 删除本地变量
    

2.2 环境变量:Shell的“公共通讯录”

  • 理解:当前Shell共享给所有子进程的全局数据,相当于公司公共通讯录,自己和同事(子Shell/脚本/程序)都能查,是Linux最常用的变量类型。
  • 关键:必须加export定义(或declare -x),能被子进程继承,系统默认的PATH/HOME等都是环境变量。
  • 实操:
    export test=123  # 定义环境变量,加export
    echo $test  # 输出123,当前Shell能查到
    bash        # 新建子Shell
    echo $test  # 输出123,子Shell继承到环境变量
    exit
    unset test  # 删除环境变量
    

2.3 Shell内建命令:Shell的“自带工具”

  • 理解:不是数据,是指令,是Shell本身内置的功能(而非系统里的独立程序),执行速度极快,核心作用是操作变量、管理Shell本身
  • 关键:
    • 无独立可执行文件(用which cd查不到路径,普通命令如ls能查到/bin/ls);
    • 大部分变量操作的命令(export/set/unset)都是内建命令,是操作“本地/环境变量”的工具。

3.核心关联:内建命令是操作变量的“手”

本地/环境变量是被操作的对象(数据),内建命令是操作对象的工具(指令),三者的核心关联全靠内建命令实现:

  1. export:内建命令,把本地变量升级为环境变量(最核心的关联);
  2. set:内建命令,查看所有变量(本地+环境),也可定义本地变量;
  3. env/printenv:内建命令,仅查看环境变量
  4. unset:内建命令,删除本地/环境变量(通用);
  5. echo:内建命令,打印单个变量的值(本地/环境都可)。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐