Linux 环境变量

目录

0.前言

1.什么是环境变量

[2. 常见的环境变量](#2. 常见的环境变量)

[3. 用 echo 查看环境变量](#3. 用 echo 查看环境变量)

[3.1 示例](#3.1 示例)

[3.2 思考](#3.2 思考)

[3.2.1测试 PATH](#3.2.1测试 PATH)

[3.2.2测试 HOME](#3.2.2测试 HOME)

[4. 与环境变量相关的命令](#4. 与环境变量相关的命令)

5.获取环境变量的其他方法

[5.1 使用 main(int argc, char *argv[], char *env[])](#5.1 使用 main(int argc, char *argv[], char *env[]))

[5.2 使用 extern char **environ;](#5.2 使用 extern char **environ;)

[5.3 使用 getenv()](#5.3 使用 getenv())

[6. 环境变量的组织方式](#6. 环境变量的组织方式)

7.环境变量具有全局属性

8.小结


(图像由AI生成)

0.前言

在之前的内容中,我们已经探讨了进程的基本概念、进程优先级等相关知识。接下来,我们将继续深入介绍Linux系统中一个非常重要的概念------环境变量。环境变量不仅仅对操作系统有重要的影响,还对我们在Linux上的编程、调试、运行程序有着至关重要的作用。

1.什么是环境变量

环境变量(environment variables)是操作系统中一种用于指定操作环境的参数。这些变量以键值对的形式存在,允许操作系统和应用程序根据设定的环境进行相应的运行和配置。

环境变量的核心作用是传递信息,帮助操作系统和应用程序了解系统的配置和状态。例如,当我们编写C/C++代码并进行编译时,编译器会查找相关的库文件、头文件和编译选项,但我们不需要手动指定这些路径。原因是系统中已经设置了相关的环境变量,如LIBRARY_PATHINCLUDE_PATH等,编译器会根据这些变量自动查找所需资源。因此,环境变量使得复杂的系统配置变得简单高效。

环境变量的种类

  1. 系统级环境变量 :这些变量在系统启动时由操作系统初始化,通常影响所有用户和系统进程。系统级变量可以通过编辑系统配置文件(如/etc/profile/etc/environment)进行设置。它们在系统范围内生效,确保所有用户共享相同的系统配置。

  2. 用户级环境变量 :这些变量由用户在其个人配置文件中定义,影响该用户在当前会话中的操作。常见的用户级环境变量配置文件有~/.bashrc~/.bash_profile。这些变量仅对当前用户和该用户启动的进程有效,适合定制化用户的操作环境。

2. 常见的环境变量

在Linux系统中,有一些常见的环境变量,它们在日常使用和系统操作中发挥着重要作用:

  • PATH :定义系统查找可执行文件的目录路径。当我们在终端中输入命令时,系统会根据PATH中的目录顺序查找该命令的可执行文件。如果找到,就会执行该命令,否则提示找不到命令。

  • HOME :指向当前用户的主目录。用户的个人文件、配置文件等通常存放在这个目录中,用户可以通过$HOME轻松访问自己的文件。

  • SHELL :定义用户当前使用的Shell类型,如/bin/bash表示使用Bash Shell,/bin/zsh表示使用Zsh Shell。这决定了用户在终端中的命令解释器。

3. 用 echo 查看环境变量

在Linux中,使用echo命令可以很方便地查看环境变量的值。通过echo $变量名的方式,我们能够直观地显示某个环境变量的当前设置。例如,查看PATHHOME等环境变量。

3.1 示例

使用echo查看PATH变量的值:

使用echo查看HOME变量的值:

3.2 思考

通过实际操作,理解环境变量的影响非常重要。我们可以通过以下步骤来测试和理解PATHHOME的作用。

3.2.1测试 PATH

  1. 创建hello.c文件

    首先,我们创建一个简单的C程序文件hello.c,内容如下:

    cpp 复制代码
    #include <stdio.h>
    int main() {
        printf("Hello, World!\n");
        return 0;
    }
  2. 编译hello.c

    使用gcc或其他C编译器将hello.c编译成可执行文件:

    bash 复制代码
    gcc hello.c -o hello
  3. 对比./hellohello执行

    • 直接在当前目录下执行./hello,成功输出"Hello, World!":

      bash 复制代码
      ./hello
    • 然后尝试直接输入hello运行,会提示找不到命令。这是因为我们的程序不在PATH环境变量指定的目录中,系统无法找到它。

  4. 将程序路径加入PATH

    我们可以将当前目录加入到PATH环境变量中,这样就可以直接通过hello运行程序:

    export PATH=$PATH:/path/to/hello

    (注意:/path/to/hello应该替换为实际的程序路径)

  5. 对比测试

    重新运行hello,此时系统能够找到程序并执行。我们可以看到添加路径后,不用再输入./hello,可以直接输入hello来运行程序。

  6. 其他方法

    除了修改PATH变量,还可以通过以下方式使程序可以直接运行:

    • 将可执行文件放置在系统的某个PATH包含的目录中,如/usr/local/bin
    • 为程序创建软链接,将链接文件放在PATH目录中。

3.2.2测试 HOME

  1. 用root和普通用户分别执行echo $HOME
    • 使用root用户运行echo $HOME

      bash 复制代码
      echo $HOME


      输出结果通常为/root,这是root用户的主目录。

    • 切换到普通用户并运行echo $HOME,输出结果为/home/username,其中username为当前用户的名称。

4. 与环境变量相关的命令

在Linux中,管理和操作环境变量的常用命令包括echoexportenvunsetset,它们分别具有不同的功能:

  • echo:用于查看环境变量的值。由于前面已经介绍过(见3.1),此处不再演示。

  • export :用于设置或修改环境变量,并使其在当前会话的子进程中生效。

    示例:

    bash 复制代码
    export PATH=$PATH:/new/path
  • env :用于显示当前的所有环境变量,或临时设置环境变量来运行某个命令。

    示例:

    bash 复制代码
    env
  • unset :用于删除指定的环境变量。

    示例:

    bash 复制代码
    unset PATH
  • set :用于设置或显示shell变量和环境变量的值,通常用于配置shell的运行环境。

    示例:

    bash 复制代码
    set

5.获取环境变量的其他方法

除了通过命令行工具获取环境变量外,在C语言编程中,可以通过多种方式访问和获取环境变量。以下介绍三种常用的方法:通过main函数的参数、environ变量以及getenv()函数。

5.1 使用 main(int argc, char *argv[], char *env[])

在某些C语言的实现中,main函数可以接收第三个参数env[],它是一个指向环境变量字符串的指针数组。通过遍历env[],可以获取所有的环境变量。

示例

cpp 复制代码
#include <stdio.h>

int main(int argc, char *argv[], char *env[]) {
    for (int i = 0; env[i] != NULL; i++) {
        printf("%s\n", env[i]);
    }
    return 0;
}

这个程序会输出系统中所有的环境变量。

5.2 使用 extern char **environ;

在大多数Unix/Linux系统中,environ是一个外部全局变量,它是一个指向所有环境变量的指针数组。通过访问environ,可以获取到与env[]类似的效果。

示例

cpp 复制代码
#include <stdio.h>

extern char **environ;

int main() {
    for (int i = 0; environ[i] != NULL; i++) {
        printf("%s\n", environ[i]);
    }
    return 0;
}

这个程序同样会输出所有的环境变量。

5.3 使用 getenv()

getenv()函数用于获取单个环境变量的值。传递环境变量的名称作为参数,返回该变量的值,如果变量不存在则返回NULL

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

int main() {
    char *path = getenv("PATH");
    if (path != NULL) {
        printf("PATH: %s\n", path);
    } else {
        printf("PATH environment variable not found.\n");
    }
    return 0;
}

这个程序会输出PATH环境变量的值。

6. 环境变量的组织方式

在Linux系统中,每个程序在启动时都会接收到一张环境表 ,这张表是一个由字符指针组成的数组。每个字符指针指向一个以'\0'(空字符)结尾的字符串,这个字符串包含了环境变量的名称和值。环境变量的形式通常是NAME=VALUE,如HOME=/home/userPATH=/usr/bin:/bin等。

从图片中可以看到,environ是一个指向指针数组的指针。数组中的每个元素指向一个环境变量字符串,这些字符串的格式为NAME=VALUE,并且以'\0'结尾。这个指针数组最后一个元素是NULL,用于表示数组的结束。

环境变量的存储结构

  1. 指针数组environ是一个指向指针数组的指针,每个数组元素是一个指向具体环境变量的指针。每个环境变量的值都是一个字符串,采用"NAME=VALUE"的格式。
  2. 环境变量字符串 :每个指针指向的是一个以\0结尾的字符串,表示环境变量的名称和值。例如,HOME=/home/akaedu\0 表示环境变量HOME的值是/home/akaedu
  3. 结束标记 :指针数组的最后一个元素是NULL,用于标记环境表的结束。程序可以通过遍历数组,直到遇到NULL,来逐个获取环境变量。

图中展示了environ的组织方式,环境表包含了四个常见的环境变量:

  • HOME=/home/akaedu
  • PATH=/usr/sbin:/usr/bin:/sbin:/bin
  • SHELL=/bin/bash
  • USER=akaedu

每个环境变量都是以\0结尾的字符串,并通过指针关联到指针数组中的相应位置。指针数组中最后一个元素是NULL,表示环境表的结束。

7.环境变量具有全局属性

在Linux和大多数操作系统中,环境变量具有全局属性 ,这意味着一旦某个环境变量被设置,它不仅对当前进程有效,还可以被该进程创建的子进程继承和使用。这种机制为系统中多个进程之间共享环境信息提供了便捷途径。

当一个进程启动另一个子进程时,子进程会自动继承父进程的环境变量。这种继承机制确保了子进程可以在相同的环境中运行,并使用父进程定义的路径、配置等。例如:

  • 当我们在终端中启动一个Shell,所有在这个Shell中运行的程序都会继承Shell中的环境变量。
  • 如果在终端中设置了某个环境变量,如export VAR=value,随后启动的程序(例如编辑器或编译器)都能够访问到这个变量。

示例

  1. 父进程中设置环境变量

    bash 复制代码
    export MY_VAR="Hello, World!"
  2. 启动子进程 : 运行一个新进程,比如bash或某个应用程序,子进程将继承MY_VAR变量:

    bash 复制代码
    echo $MY_VAR
  3. 结果 : 子进程能够正确输出MY_VAR的值Hello, World!,说明它继承了父进程中的环境变量。

注意事项

  • 临时性 :环境变量虽然具有全局属性,但仅在当前会话中有效。一旦用户关闭当前的Shell或终端,所有设置的环境变量都会丢失。为了使其持久生效,通常需要将其写入诸如~/.bashrc~/.profile等配置文件中。

  • 修改和继承 :子进程可以修改自己继承的环境变量,但这些修改不会影响父进程。例如,子进程可以更改自己的PATH,但父进程的PATH不会受到影响。

8.小结

本博客介绍了Linux环境变量的概念及其重要性,解释了如何查看、设置和管理环境变量,常见的环境变量如PATHHOME等,以及如何通过C语言获取环境变量。此外,讨论了环境变量的全局属性及其在父子进程之间的继承性,展示了环境变量在操作系统中的灵活应用和组织方式,帮助用户更好地理解和使用环境变量来配置和优化系统环境。

相关推荐
YRr YRr25 分钟前
解决Ubuntu 20.04上编译OpenCV 3.2时遇到的stdlib.h缺失错误
linux·opencv·ubuntu
认真学习的小雅兰.27 分钟前
如何在Ubuntu上利用Docker和Cpolar实现Excalidraw公网访问高效绘图——“cpolar内网穿透”
linux·ubuntu·docker
zhou周大哥43 分钟前
linux 安装 ffmpeg 视频转换
linux·运维·服务器
不想起昵称9291 小时前
Linux SHELL脚本中的变量与运算
linux
loong_XL1 小时前
服务器ip:port服务用nginx 域名代理
服务器·tcp/ip·nginx
夕泠爱吃糖1 小时前
C++中如何实现序列化和反序列化?
服务器·数据库·c++
the丶only2 小时前
单点登录平台Casdoor搭建与使用,集成gitlab同步创建删除账号
linux·运维·服务器·docker·gitlab
书生-w2 小时前
Docker部署GitLab服务器
服务器·docker·gitlab
Ling_suu2 小时前
SpringBoot3——Web开发
java·服务器·前端