💘作者:泠沫
💘博客主页:泠沫的博客
💘专栏:Linux系统编程,文件认识与理解…
💘觉得博主写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!
🏠 环境变量基本概念
-
Linux环境变量是指在操作系统中设置的具有特定含义的一些变量,它们可被各种程序和脚本调用访问。环境变量可以影响用户会话的运行方式,如控制应用程序的默认选项、设置系统语言等。
-
如我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但
是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。 -
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。
🏠 常见环境变量
-
PATH:用于指定可执行文件的搜索路径。
-
HOME:Linux用户的主目录,通常是/home/用户名。
-
USER:当前登录用户的用户名。
-
SHELL:当前用户使用的shell类型(比如bash、zsh等)。
-
LANG:指定系统默认语言和字符集,影响应用程序的输出和显示方式。
-
TEMP、TMP:指定临时文件存储位置。
-
PS1、PS2:控制终端提示符的样式。
-
DISPLAY:用于指定X11服务器的地址,只有在使用图形界面应用程序时才需要设置。
-
EDITOR:指定默认的文本编辑器,例如vim、nano等。
-
LD_LIBRARY_PATH:用于指定动态链接库的搜索路径,当应用程序调用共享库时会自动在此路径下寻找相关的库文件。
🏠 环境变量类型
-
全局环境变量:全局环境变量是对整个系统生效的环境变量,它们可以被所有用户和应用程序访问。一般情况下,全局环境变量被保存在/etc/profile文件或/etc/environment文件中。全局环境变量的设置将影响到整个系统,在启动终端会话时就会进行加载,并覆盖用户自定义的同名环境变量。
-
局部环境变量:局部环境变量只对当前用户或当前shell生效。当在bash shell脚本中定义和使用变量时,这些变量默认是局部变量。
-
如果想使局部变量变成环境变量(即全局变量),可以使用"export"命令将其导出至环境变量表中。例如,输入"export MY_VAR=hello",则"MY_VAR"就从局部环境变量转换成了全局环境变量。 与此相对的,unset命令也可以用来清除环境变量。
-
无论是全局环境变量还是局部环境变量,均只在本次登录shell时有效,一旦重新登陆,环境变量会重修变成初始默认值。
🏠 查看环境变量方式
-
printenv命令:该命令可以列出当前用户的所有环境变量及其取值。在终端上输入"printenv"即可执行该命令。
-
echo命令:该命令可以打印出单个变量(包括环境变量和局部变量)的取值。例如,要查看PATH环境变量,可以在终端上输入"echo $PATH"。
-
env命令:该命令可以列出所有环境变量及其取值,类似于"printenv"命令。在终端上输入"env"即可执行该命令。
-
set命令:该命令可以列出shell会话中的所有变量(包括环境变量和局部变量)及其取值。在终端上输入"set"即可执行该命令。
🏠 环境变量的全局属性
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int main()
{
char* mypwd = getenv("USER");
if(!strcmp(mypwd,"root"))
{
cout << "run succeed..." << endl;
}
else
{
cout << "-bash: ./pro : Permission denied" << endl;
}
return 0;
}
-
我们运行自己的可执行程序,该可执行程序就变成了一个进程,它的父进程就是bash。也就是说,我们执行的可执行程序是bash的一个子进程,但是我们发现该子进程在运行过程中,居然可以访问系统内环境变量。这说明,环境变量具有全局属性,可以被子进程继承下去,这可以用来应对不同的场景。
-
所以,有的时候我们执行某些指令的时候,为什么系统会报错Permission denied。就是因为有一个环境变量是USER,我们所敲的指令本质上也是一个一个的可执行程序,然后加载到内存中成为了bash的子进程。在那些指令内部,必然判断了我们是否为root,如果不是则不允许执行该指令,程序直接终止退出。试想如果环境变量没有全局属性,子进程无法继承环境变量,那么该功能也就无法实现。
子进程获得环境变量的三种方式
- getenv()函数
- main()函数的函数参数传递
- 系统有一个全局的环境变量表指针char ** environ
🏠 环境变量组织方式
每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串。
🏠 main函数的参数–命令行参数
一般情况下,我们大家在main函数的时候都是:int main(),参数一般都为空。
但实际上main函数也是有参数的:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main(int argc, char* argv[], char* env[])
{
for(int i = 0; env[i]; i++)
{
printf("env[%d]:%s\n", i, env[i]);
}
cout << endl;
for(int i = 0; i < argc; i++)
{
printf("argv[%d]:%s\n", i, argv[i]);
}
if(!strcmp(argv[1],"-a"))
printf("执行功能a\n");
if(!strcmp(argv[1],"-b"))
printf("执行功能b\n");
if(!strcmp(argv[1],"-c"))
printf("执行功能c\n");
if(!strcmp(argv[1],"-ab"))
printf("执行功能ab\n");
if(!strcmp(argv[1],"-ac"))
printf("执行功能ac\n");
if(!strcmp(argv[1],"-bc"))
printf("执行功能bc\n");
if(!strcmp(argv[1],"-abc"))
printf("执行功能abc\n");
return 0;
}
由此可见,main函数其实也可以传参数。只是一般情况下我们不需要给该程序带上特定的选项,且不用命令行的方式执行程序,所以才一般不传入参数。
对于main函数的三个参数:
-
argc表示的是指令该可执行程序命令行的指令个数,也就是第二个指针数组的大小。
-
argv表示执行该可执行程序的指令字符串,以空格作为字符串的分割。
-
env表示环境表指针,指向存放环境变量的数组的首元素。该方式可以让子进程继承bash的环境变量。
其实就算不传递第三个参数,子进程也可以拿到bash的环境变量,一种方式是调用getenv函数来获得,而另一种方式则是C语言提供了一个全局变量environ,该变量是一个二级指针,指向env环境表指针。
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int main()
{
extern char** environ;
for(int i = 0; environ[i]; i++)
{
printf("%d:%s\n", i, environ[i]);
}
return 0;
}
该方式执行结果与传入参数char* env[]一致。