目录
[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.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. 环境变量的组织方式)
(图像由AI生成)
0.前言
在之前的内容中,我们已经探讨了进程的基本概念、进程优先级等相关知识。接下来,我们将继续深入介绍Linux系统中一个非常重要的概念------环境变量。环境变量不仅仅对操作系统有重要的影响,还对我们在Linux上的编程、调试、运行程序有着至关重要的作用。
1.什么是环境变量
环境变量(environment variables)是操作系统中一种用于指定操作环境的参数。这些变量以键值对的形式存在,允许操作系统和应用程序根据设定的环境进行相应的运行和配置。
环境变量的核心作用是传递信息,帮助操作系统和应用程序了解系统的配置和状态。例如,当我们编写C/C++代码并进行编译时,编译器会查找相关的库文件、头文件和编译选项,但我们不需要手动指定这些路径。原因是系统中已经设置了相关的环境变量,如LIBRARY_PATH
、INCLUDE_PATH
等,编译器会根据这些变量自动查找所需资源。因此,环境变量使得复杂的系统配置变得简单高效。
环境变量的种类
-
系统级环境变量 :这些变量在系统启动时由操作系统初始化,通常影响所有用户和系统进程。系统级变量可以通过编辑系统配置文件(如
/etc/profile
或/etc/environment
)进行设置。它们在系统范围内生效,确保所有用户共享相同的系统配置。 -
用户级环境变量 :这些变量由用户在其个人配置文件中定义,影响该用户在当前会话中的操作。常见的用户级环境变量配置文件有
~/.bashrc
或~/.bash_profile
。这些变量仅对当前用户和该用户启动的进程有效,适合定制化用户的操作环境。
2. 常见的环境变量
在Linux系统中,有一些常见的环境变量,它们在日常使用和系统操作中发挥着重要作用:
-
PATH :定义系统查找可执行文件的目录路径。当我们在终端中输入命令时,系统会根据
PATH
中的目录顺序查找该命令的可执行文件。如果找到,就会执行该命令,否则提示找不到命令。 -
HOME :指向当前用户的主目录。用户的个人文件、配置文件等通常存放在这个目录中,用户可以通过
$HOME
轻松访问自己的文件。 -
SHELL :定义用户当前使用的Shell类型,如
/bin/bash
表示使用Bash Shell,/bin/zsh
表示使用Zsh Shell。这决定了用户在终端中的命令解释器。
3. 用 echo
查看环境变量
在Linux中,使用echo
命令可以很方便地查看环境变量的值。通过echo $变量名
的方式,我们能够直观地显示某个环境变量的当前设置。例如,查看PATH
、HOME
等环境变量。
3.1 示例
使用echo
查看PATH
变量的值:
使用echo
查看HOME
变量的值:
3.2 思考
通过实际操作,理解环境变量的影响非常重要。我们可以通过以下步骤来测试和理解PATH
和HOME
的作用。
3.2.1测试 PATH
-
创建
hello.c
文件首先,我们创建一个简单的C程序文件
hello.c
,内容如下:cpp#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }
-
编译
hello.c
使用
gcc
或其他C编译器将hello.c
编译成可执行文件:bashgcc hello.c -o hello
-
对比
./hello
与hello
执行-
直接在当前目录下执行
./hello
,成功输出"Hello, World!":bash./hello
-
然后尝试直接输入
hello
运行,会提示找不到命令。这是因为我们的程序不在PATH
环境变量指定的目录中,系统无法找到它。
-
-
将程序路径加入
PATH
我们可以将当前目录加入到
PATH
环境变量中,这样就可以直接通过hello
运行程序:export PATH=$PATH:/path/to/hello
(注意:
/path/to/hello
应该替换为实际的程序路径) -
对比测试
重新运行
hello
,此时系统能够找到程序并执行。我们可以看到添加路径后,不用再输入./hello
,可以直接输入hello
来运行程序。 -
其他方法
除了修改
PATH
变量,还可以通过以下方式使程序可以直接运行:- 将可执行文件放置在系统的某个
PATH
包含的目录中,如/usr/local/bin
。 - 为程序创建软链接,将链接文件放在
PATH
目录中。
- 将可执行文件放置在系统的某个
3.2.2测试 HOME
- 用root和普通用户分别执行
echo $HOME
-
使用root用户运行
echo $HOME
:bashecho $HOME
输出结果通常为/root
,这是root用户的主目录。 -
切换到普通用户并运行
echo $HOME
,输出结果为/home/username
,其中username
为当前用户的名称。
-
4. 与环境变量相关的命令
在Linux中,管理和操作环境变量的常用命令包括echo
、export
、env
、unset
和set
,它们分别具有不同的功能:
-
echo:用于查看环境变量的值。由于前面已经介绍过(见3.1),此处不再演示。
-
export :用于设置或修改环境变量,并使其在当前会话的子进程中生效。
示例:
bashexport PATH=$PATH:/new/path
-
env :用于显示当前的所有环境变量,或临时设置环境变量来运行某个命令。
示例:
bashenv
-
unset :用于删除指定的环境变量。
示例:
bashunset PATH
-
set :用于设置或显示shell变量和环境变量的值,通常用于配置shell的运行环境。
示例:
bashset
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/user
、PATH=/usr/bin:/bin
等。
从图片中可以看到,environ
是一个指向指针数组的指针。数组中的每个元素指向一个环境变量字符串,这些字符串的格式为NAME=VALUE
,并且以'\0'
结尾。这个指针数组最后一个元素是NULL
,用于表示数组的结束。
环境变量的存储结构
- 指针数组 :
environ
是一个指向指针数组的指针,每个数组元素是一个指向具体环境变量的指针。每个环境变量的值都是一个字符串,采用"NAME=VALUE
"的格式。 - 环境变量字符串 :每个指针指向的是一个以
\0
结尾的字符串,表示环境变量的名称和值。例如,HOME=/home/akaedu\0
表示环境变量HOME
的值是/home/akaedu
。 - 结束标记 :指针数组的最后一个元素是
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
,随后启动的程序(例如编辑器或编译器)都能够访问到这个变量。
示例
-
父进程中设置环境变量:
bashexport MY_VAR="Hello, World!"
-
启动子进程 : 运行一个新进程,比如
bash
或某个应用程序,子进程将继承MY_VAR
变量:bashecho $MY_VAR
-
结果 : 子进程能够正确输出
MY_VAR
的值Hello, World!
,说明它继承了父进程中的环境变量。
注意事项
-
临时性 :环境变量虽然具有全局属性,但仅在当前会话中有效。一旦用户关闭当前的Shell或终端,所有设置的环境变量都会丢失。为了使其持久生效,通常需要将其写入诸如
~/.bashrc
或~/.profile
等配置文件中。 -
修改和继承 :子进程可以修改自己继承的环境变量,但这些修改不会影响父进程。例如,子进程可以更改自己的
PATH
,但父进程的PATH
不会受到影响。
8.小结
本博客介绍了Linux环境变量的概念及其重要性,解释了如何查看、设置和管理环境变量,常见的环境变量如PATH
、HOME
等,以及如何通过C语言获取环境变量。此外,讨论了环境变量的全局属性及其在父子进程之间的继承性,展示了环境变量在操作系统中的灵活应用和组织方式,帮助用户更好地理解和使用环境变量来配置和优化系统环境。