文章目录
本章讲的环境变量,操作是基于Linux上的。
环境变量的基本概念
环境变量是操作系统中用于保存配置信息的一种机制。它们在系统中充当全局变量,主要用于存储操作系统和应用程序运行时所需的重要参数和配置,提供了与系统交互和动态配置的途径。
环境变量的基本特点
- 键值对形式 :环境变量通常是一个键值对结构,例如
PATH=/usr/local/bin
。键(例如 PATH)表示变量名称,值(例如 /usr/local/bin)表示变量内容。 - 全局可访问性:环境变量在一个用户会话或进程环境中被全局访问,可以被所有程序使用。
- 动态配置:环境变量提供了一种在不修改代码的情况下调整程序行为的方法,通过更改变量的值,可以影响程序运行的方式。
环境变量的作用
- 配置操作系统和应用程序:操作系统和应用程序依赖环境变量来决定它们的工作方式。例如,PATH 环境变量用于指定可执行文件的搜索路径。
- 存储系统信息:环境变量用于存储系统的基本信息,例如主机名、用户名和用户主目录等。
- 设置编译和运行环境:在软件开发和运行时,环境变量可以用于指定编译器路径、库路径等。
常见环境变量
- PATH:指定可执行程序的搜索路径,当用户在终端输入命令时,系统会在此路径中查找对应程序。
- HOME:用户的主目录路径。
- USER:当前用户名。
- SHELL:当前用户使用的 Shell 类型,如 Bash 或 Zsh。
- LANG:指定系统的语言和区域设置,用于国际化支持。
环境变量的管理
在 Linux 和 Unix 系统中,可以通过以下命令管理环境变量:
查看环境变量:使用 printenv 或 env。
查看单个环境变量:echo $NAME
//NAME:环境变量名称
设置环境变量:使用 export 命令,例如 export VAR_NAME=value
。
删除环境变量:使用 unset 命令,例如 unset VAR_NAME
显示本地定义的 shell 变量和环境变量: set
命令行参数的概念
C语言中的 main 函数其实也是有参数的:int argc
和 char *argv[]
,它们用于处理命令行参数,为程序提供灵活的输入方式。
argc (Argument Count)
:参数计数,是一个整数,表示命令行传递给程序的参数个数,包括程序名本身。argv (Argument Vector)
:参数向量,是一个字符串数组,包含命令行传递的所有参数。argv[0] 通常是程序的名称,后续的 argv[1]、argv[2] 等是用户输入的其他参数。
举个例子:
输出结果:
我们在命令行中输入的指令会被指令读取到argv维护的一段空间里,结尾会自动加上一个NULL。
这两个参数是用来接收命令行参数的,但在某些特定的编译器或操作系统环境中,main 函数可以接收一个非标准的第三个参数,通常是 char *envp[],用于访问环境变量。这种形式的 main 函数签名如下:
cpp
int main(int argc, char *argv[], char *envp[])
envp 的作用
envp (Environment Pointer) :这是一个指向字符串数组的指针,其中每个字符串都是一个环境变量的键值对,格式为 KEY=VALUE 。
环境变量提供了一些系统级的配置信息,比如用户主目录、系统路径等,这些信息可以被程序读取和使用。
示例:
运行结果:
注意事项:
- 并不是所有的系统或编译器都支持将 envp 作为 main 的第三个参数。使用这种形式时需要确保系统支持,或使用 POSIX 标准的 -getenv 函数来访问环境变量。
我们再通过 env 命令来查看一下在当前的bash中的环境变量:
可以看到,我们写的程序和 bash 的环境变量是一样的,这也说明了环境变量是具有全局属性的,可以被子进程继承下去。
此外我们不仅可用通过 main 函数的第三个参数来获取环境变量,也可以通过一个外部变量:environ
来获取环境变量
- 定义: environ 通常被定义为一个指向字符指针数组的指针,即 char **environ 。这个数组中的每个元素都是一个以 \0 结尾的字符串,每个字符串代表一个环境变量,其格式为 name=value ,其中 name 是环境变量的名称, value 是其对应的值。
- 存储位置:环境变量由操作系统维护,在程序启动时,操作系统会为程序创建一个环境列表,并将其地址赋值给 environ ,这样程序就可以通过 environ 来访问环境变量了。
运行结果:
除了上述两个方式可以获取环境变量之外,还可以通过C语言中的标准库函数,其函数原型为:
char *getenv(const char *name);
- 功能: getenv 函数的主要功能是在程序的环境变量列表中查找指定名称的环境变量,并返回其对应的值(如果存在)。如果指定的环境变量不存在,则返回 NULL 。
- 参数说明: getenv 函数接受一个 const char * 类型的参数 name ,这个参数就是要查找的环境变量的名称,例如,要查找 PATH 环境变量的值,就可以将 "PATH" 作为参数传递给 getenv 函数。
- 返回值:如果找到匹配的环境变量, getenv 函数返回一个指向包含该环境变量值的字符串的指针,这个指针指向的字符串是环境变量列表中的一部分,不应该被修改,因为这可能会破坏程序的运行环境。如果没有找到指定的环境变量,函数返回 NULL 。
示例:
输出结果:
与 environ 的比较
- 便利性: getenv 函数比直接使用 environ 更方便,特别是当只需要获取一个或几个特定环境变量的值时。使用 getenv 函数,不需要遍历整个环境变量列表,函数内部已经实现了查找机制。
- 可移植性: getenv 函数是C标准库的一部分,在符合标准的C实现中都可以使用,具有良好的可移植性。而直接使用 environ 虽然也能实现相同的功能,但在代码风格和可移植性上可能稍逊一筹,因为 environ 的实现细节可能因操作系统和编译器的不同而有所差异。
- 局限性: getenv 函数仅适用于获取单个环境变量的值,如果需要对整个环境变量列表进行操作,如打印所有环境变量或修改环境变量列表,还是需要使用 environ 或者其他操作系统提供的特定接口。
添加环境变量
在 Linux 中,添加环境变量有几种方法,具体取决于环境变量的生效范围(临时会话、当前用户、所有用户)和加载方式。
- 为当前会话临时添加环境变量
在当前的终端会话中,可以直接使用 export 命令来添加环境变量。这种方法在关闭终端或注销后就会失效。
bash
export VAR_NAME="value"
// 例如:
export PATH="$PATH:/my/custom/path"
这里需要注意:
在 PATH 这个环境变量中,每个路径是以 : 来进行分割的
所以,我们添加环境变量是令 PATH="$PATH:/my/custom/path"
,这样相当于是在原来的 PATH 后多加一个 /my/custom/path 路径,如果直接写成 PATH=/my/custom/path 可能会直接被覆盖。
但该修改仅在当前终端会话中有效。
- 为当前用户永久添加环境变量
要使环境变量在每次登录时都生效,可以将其添加到用户主目录中的~/.bash_profile
或~/.bashrc
文件中:
- 打开 ~/.bash_profile 或 ~/.bashrc 文件,在文件末尾添加环境变量设置,例如:
bash
export VAR_NAME="value"
export PATH="$PATH:/my/custom/path"
保存并关闭文件后,使环境变量立即生效:
bash
source ~/.bash_profile
# 或
source ~/.bashrc
- 为所有用户添加系统范围的环境变量
要为所有用户添加系统范围的环境变量,可以将环境变量添加到/etc/profile
或/etc/environment
文件中:
/etc/profile
:适用于所有用户的登录 shell。
在/etc/profile
文件末尾添加环境变量设置:
bash
export VAR_NAME="value"
export PATH="$PATH:/my/custom/path"
保存并关闭后,新的会话或用户登录时将会加载该变量。
/etc/environment
:专门用于环境变量的文件,不需要使用 export 关键字,添加如下关键字:
bash
VAR_NAME="value"
PATH="$PATH:/my/custom/path"
注意:/etc/environment
仅适用于环境变量,而不支持 shell 命令或复杂的路径操作(如 "$PATH:/my/custom/path" 可能无法在此文件中正确解析)。
在 Linux 中,~/.bash_profile
、~/.bashrc
和 /etc/bashrc
都是 Bash shell 的配置文件,但它们的作用和加载时机有所不同。以下是它们的主要区别:
-
~/.bash_profile
-
位置:用户主目录中的 ~/.bash_profile。
-
用途:设置用户的登录 shell 环境(包括环境变量、路径、启动脚本等)。
-
加载时机:只在登录 shell 中加载(即当用户通过终端或 SSH 等方式登录系统时加载)。
-
内容:一般用于定义用户的全局环境变量和启动配置。在 .bash_profile 中,通常会调用 ~/.bashrc,以确保交互式非登录 shell 也加载相应的配置
-
-
~/.bashrc
- 位置:用户主目录中的 ~/.bashrc。
- 用途:设置交互式 shell 环境(别名、shell 函数、shell 选项等)。
- 加载时机:每次启动交互式非登录 shell 时加载,例如通过终端窗口打开新 shell 或执行 Bash 时。
- 内容:适合放置命令别名、shell 函数、PS1 提示符配置等,通常不直接定义环境变量(环境变量一般在 .bash_profile 中定义)。~/.bashrc 也会被 ~/.bash_profile 调用,以确保登录 shell 能共享到 ~/.bashrc 的配置。
-
/etc/bashrc(或 /etc/bash.bashrc)
- 位置:系统范围的 Bash 配置文件,通常在 /etc/bashrc 或 /etc/bash.bashrc。
- 用途:为系统上所有用户提供默认的 shell 配置。
- 加载时机:在每次启动交互式 shell 时加载,不管是登录还是非登录 shell。通常由 ~/.bashrc 调用,因此每个用户都可以继承系统范围的配置。
- 内容:适合定义系统范围的默认别名、shell 函数、PS1 提示符等。也可以根据需要对不同用户或环境设置不同的默认配置。
我演示一遍通过配置文件 ~/.bash_profile
来让我每次登录机器时,会有一些欢迎语:
bash 中的本地变量
在 Linux 和编程中,"本地变量"指的是只在特定的作用域内有效的变量。例如,它们只在当前 shell、当前函数、当前代码块中存在,离开作用域后这些变量会被销毁。
在 Bash Shell 中的本地变量
在 Bash 脚本中,本地变量仅在当前 shell 会话或当前函数内有效。要定义一个本地变量,可以简单地使用赋值语句。如果想要明确将变量限制为函数内本地,可以使用 local 关键字。
bash
#!/bin/bash
VAR="I am a local variable" # 定义一个本地变量
echo $VAR # 输出本地变量的值
在该脚本运行时,变量 hello 的作用范围仅限于该脚本的 shell 会话。运行完脚本后,hello 不再存在。
本地变量和环境变量在作用范围、继承特性、以及使用场景上有显著区别:
-
作用范围
本地变量 :作用范围只在当前 shell、当前函数或当前代码块中。在 shell 会话中定义的本地变量只在当前 shell 进程中有效,退出后这些变量会被销毁。环境变量:可以在当前 shell 及其子进程中访问,具有更广的作用范围。环境变量会被当前 shell 继承到子进程中,因此可以在运行的程序或脚本中被访问到。
-
定义方式
本地变量 :直接赋值即可,比如 VAR="value"。在 shell 函数中,可以通过 local 关键字来限定变量为函数级别的本地变量。环境变量:通过 export 命令将变量标记为环境变量,比如 export VAR="value"。这样 VAR 就会成为环境变量,并且在当前 shell 及其子进程中都可用。
-
继承性
本地变量 :不能被子进程继承。即使在父进程中定义了本地变量,子进程中也无法访问到。环境变量:可以被子进程继承。只要将变量 export 成环境变量,任何从当前 shell 派生的子进程都能访问它。
-
使用场景
本地变量 :适用于只在当前 shell 或函数中临时使用的数据,不希望其他 shell 会话或子进程受到影响。典型使用场景是在 shell 脚本中定义临时变量,避免变量污染。环境变量:适用于需要在整个系统中共享的信息,如 PATH、HOME、USER 等系统级配置信息,或者希望某些配置传递给子进程使用。
我们可以写一段代码来演示一遍:
bash
#!/bin/bash
VAR="local variable" # 本地变量
export ENV_VAR="environment variable" # 环境变量
echo "In parent shell: VAR=$VAR, ENV_VAR=$ENV_VAR"
# 启动一个子进程,尝试访问变量
bash -c 'echo "In child shell: VAR=$VAR, ENV_VAR=$ENV_VAR"'
bash -c
:bash
是一个命令,用于启动新的 Bash shell。-c
选项表示"命令模式",即在新启动的 shell 中运行后面的命令字符串。这是要在子 shell 中执行的命令字符串。这个字符串中的 echo 命令用于输出 VAR 和 ENV_VAR 变量的值。
运行这段脚本文件的步骤如下:
保存脚本:将脚本内容保存到一个文件中,例如 test.sh。
赋予执行权限:使脚本具有执行权限。可以在终端中使用 chmod 命令赋予文件执行权限:
bash
chmod +x test.sh
运行脚本:在终端中执行脚本,可以使用以下命令:
bash
./test.sh
第一行输出来自父进程,它能访问 VAR 和 ENV_VAR。
第二行输出来自子进程。由于 VAR 是父进程的本地变量,无法传递到子进程,所以显示为空。而 ENV_VAR 是环境变量,可以被子进程继承并输出其值。