目录
一. 环境变量的基本概念
1.1 什么是环境变量
环境变量是用于指定操作系统相关参数的、全局的变量。通过env指令,可以查看系统中全部的环境变量。
下面是几个常见的环境变量:
- PATH:指令的搜索路径
- HOME:特定用户的家目录,即:用户登录时默认所在的路径。
- SHELL:当前的shell外壳,一般为/bin/bash
查看环境变量值的方法:echo $环境变量名
环境变量有如下几点特性:
- 某个进程环境变量是从它的父进程中继承下来的。
- 默认所有的环境变量都会被子进程继承。
- 环境变量具有全局属性。
1.2 环境变量的功能测试
- 测试PATH
PATH表示指令的默认搜索路径,我们首先通过echo $PATH,获取当前的PATH值,如图1.1所示,我们看到所有的路径被:分割,OS会依次从PATH的路径中搜索用户输入的指令,直到找到指令为止,如果到了最后一个路径还没有找到,那么OS就认为指令不存在,无法执行。
我们创建编译下面的代码,生成可执行程序mytest.exe,分别在命令行中输入./mytest.exe和mytest.exe,前者成功运行,后者运行失败,详见图1.2。这是因为mytest.exe并不是一条指令,mytest.exe文件所在的路径不包含在PATH值内。
结论:Linux系统内置的指令不需要路径,输入指令名称就可以运行。用户自主编译生成的可执行程序,需要加上路径./XXX才可以运行。
接下来,通过指令 export PATH=$PATH:(pwd) 修改修改环境变量PATH的值,然后再次在命令行中直接输入mytest.exe,可见这次程序运行成功了(详见图1.3)!此时通过echo $PATH查看PATH的值,可见当前路径被加入到了PATH中,因此直接输入mytest.exe可以成功运行程序。
- 测试HOME
在两个终端下,分别使用普通用户zhangHHH和root用户登录,分别使用echo $HOME指令在不同用户登录的情况下查看环境变量HOME的值,可以看到HOME就是用户的家目录。
二. 与环境变量相关的操作
- echo $ -- 获取环境变量值
语法:echo $val_name,可以输出环境变量的值。这里的$不能省略,如果省略,那么输出的就是环境变量本身了,如echo PATH输出PATH。
- export -- 定义环境变量
语法:export 环境变量名称=值,如:export VAL=1234,就定义了一个名称为Val,值为1234的环境变量,这个变量具有全局属性。
- env -- 获取系统中的所有环境变量
如果我们通过export设定了环境变量,那么使用env同样能够查到。
- unset -- 清除环境变量
语法:unset [环境变量名称]
- putenv -- 在程序中导入环境变量
语法:putenv("[valName]=VAL")
putenv是C语言提供的函数,被包含在头文件<stdlib.h>中
如:putenv("MYVAL=1234"),就导入了名为MYVAL,值为1234的环境变量。导入父进程环境变量的子进程,也会接收到这个环境变量。
三. 环境变量的组织方式
一个main函数,最多可以有三个形参。即:main(int argc, char* argv[], char* env[]),其中argc为运行可执行程序时命令行参数的个数,argv为指向命令行参数列表的指针数组,env为指向环境变量列表的指针数组。
env指向一个存有若干char*类型变量的指针数组,数组以NULL结尾,数组中的每个数据指向一个环境变量的值,见图3.1。argv的组织方式与env基本完全相同,只不过不会以NULL结尾,但会有argc来获取记录选项的个数。
四. 通过代码获取环境变量的值
- 方法1:通过main函数的第三个参数获取
main(int argc, char* argv[], char* env[]))函数的第三个参数为指向环境变量列表的指针数组,通过evn[i],可以依次获取每个环境变量。代码4.1通过for循环,以env[i] != NULL为循环条件,依次打印每个环境变量的值。程序运行结果见图4.1。
代码4.1:通过main函数第三个参数获取环境变量
#include<iostream>
main(int argc, char* argv[], char* env[])
{
for(int i = 0; env[i]; ++i)
{
printf("env[%d] = %s\n", i, env[i]);
}
return 0;
}
- 方法2:通过第三方变量char **environ获取
变量char **environ被包含在头文件<unistd.h>中,在使用时,需要显示的包含头文件<unistd.h>或者在程序中声明外部变量extern char **environ。代码4.2展示了environ的用法。
代码4.2:通过第三方变量environ获取环境变量
#include<iostream>
#include<unistd.h>
int main()
{
for(int i = 0; environ[i]; ++i)
{
printf("environ[%d] = %s\n", i, environ[i]);
}
return 0;
}
- 方法三:通过函数getenv获取
语法:char* env_name = getenv("环境变量名称")
如果企图获取不存在的环境变量,那么程序会在运行期间报错Segmentation fault。
代码4.3:通过getenv函数获取环境变量值
#include<iostream>
int main()
{
char* path = getenv("PATH");
char* home = getenv("HOME");
printf("PATH:%s\n", path);
printf("home:%s\n", home);
return 0;
}
补充知识:
我们可以直接在命令行中使用 val_name=val 类似的指令来定义局部变量的值,但是,这并不属于全局变量,如果我们企图使用getenv获取它们的值,会在运行期间报错Segmentation fault。
这里由于提到了main函数的三个参数,因此也顺便对int argc和char* argv[]进行解读。argv表示可执行程序运行时命令行参数的个数,如果仅输入./XXX运行,那么命令行参数的个数就为1。
命令行参数的主要功能是让同一个函数,根据输入的选项,执行不同的代码。如代码4.4所示,我们要求至少有两个命令行参数,如果只输入一个(argc < 2),那么程序报错退出,如果输入选项-a,那么就执行function1,如果输入选择-b,那么就执行function2。
结论:选项 + 命令行参数可以实现同一份代码执行不同工作。
代码4.4:通过命令行参数让同一份代码执行不同工作
#include<iostream>
#include<string.h>
int main(int argc, char *argv[], char *env[])
{
//至少有两个命令行参数(一个选项)
if(argc < 2)
{
std::cout << "至少两个命令行参数" << std::endl;
}
if(strcmp(argv[1], "-a") == 0)
{
std::cout << "function1" << std::endl;
}
else if(strcmp(argv[1], "-b") == 0)
{
std::cout << "function2" << std::endl;
}
return 0;
}
五. 总结
- 环境变量是用于定义操作系统相关参数的全局变量,主要有PATH、HOME、SHELL等,每个进程的环境变量从它的父进程中继承。
- 通过echo $、export、unset、env等指令,可以实现对环境变量的增删查改。
- 环境变量是通过指针数组来组织的,char* env[]可作为main函数的第三个参数。
- 有三种方法可以实现在代码中获取环境变量的值:通过main函数的第三个参数char* env[]、通过第三方变量extern char **environ、通过getenv函数。
- main函数的第一个参数argc表示命令行参数的个数,第二个参数为指向命令行参数存储地址的指针数组,通过 命令行参数+选项 的组合使用,可让一份代码根据用户需要实现不同的功能。