赞
踩
需要云服务器等云产品来学习Linux的同学可以移步/-->腾讯云<--/-->阿里云<--/-->华为云<--/官网,轻量型云服务器低至112元/年,新用户首次下单享超低折扣。
目录
环境变量是操作系统为了满足不同的应用场景而预先在系统内设置的一大批全局变量。
- ./test
- ls
我们自己写的可执行程序需要带上路径,而系统中ls指令不用路径即可执行。因为环境变量PATH中存放系统的默认搜索路径,我们的可执行程序不能直接执行,是因为可执行程序的路径不在PATH中。
环境变量PATH中存在/usr/bin目录(这个目录其实是指令存放的目录)。我们可以把自己写的可执行程序添加到/usr/bin目录中,让用户的可执行程序无需指令也能运行。将可执行程序test拷贝至/usr/bin/目录下:
- sudo cp test /usr/bin/
- sudo rm /usr/bin/test
错误的添加路径的方法:
export PATH=路径
注意,直接用等号的话原有路径是会被覆盖的,如果误操作,可以把Xshell重启一下。重启恢复的原因是家目录中有这两个配置文件,每次启动时会将对应的环境变量导入到bash的上下文环境中:
正确添加路径的方法:
export PATH=$PATH:路径
1、set:显示本地定义的shell变量和环境变量。
2、unset:取消环境变量。
3、export:将本地变量设置为全局变量。
export NEWVAL="123"
4、env:显示所有环境变量。
5、echo:显示某个环境变量的值
- echo $PWD//查看PWD环境变量
- echo $PATH//查看PATH中的路径
操作系统在启动的时候,存在一个叫PATH的环境变量,这个变量在系统内是全局有效的。查看PATH中的路径:
路径之间以冒号间隔(Windows中是分号),这些路径决定了shell去哪些目录中寻找命令或指令。
- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- char* name=getenv("USER");
- printf("%s\n",name);
- return 0;
- }
不同的用户使用getenv函数获得当前name环境变量的内容不同。
getenv()是第一种获取环境变量的方式(最推荐)。
我们在命令行输入命令的时候,本质上是输入了一个大的字符串,这些字符串会被单独拆开。指针数组char* argv[]中按顺序存储这些个被拆开的字符串的地址。bash负责字符串的解析和传参。
再看,main函数是有三个参数的,第三个变量就是环境变量指针数组:
有了第三个参数,环境变量就能被进程拿到了,char* env[]是第二种获取环境变量的方式。
再看,为什么我们平常写代码main函数不传参数代码也能运行?他是怎么获取到环境变量的?
environ是系统中的一个全局的二级指针,它指向命令行参数表,作为参数传递给char* env[]。environ没有包含在任何头文件中,所以在使用时 要用extern声明。
- int main()
- {
- extern char** environ; //声明
- for(int i = 0; environ[i]; i++)//environ[i]最后会走到NULL停止循环
- {
- printf("%d:%s\n", i, environ[i]);
- }
- return 0;
- }
char** environ是第三种获取环境变量的方式。
那么有人会问了,平常写代码我也没声明environ啊,为什么程序也能找到它的环境变量?那是因为环境变量本身是被加载到物理内存,再映射到进程的进程地址空间中,这样,每个程序即使不主动获取环境变量,这些环境变量也已经被加载到虚拟内存中了。
- int main()
- {
- if(argc != 2)
- {
- printf("Usage: \n\t%s [-a/-b/-c/-ab/-bc/-ac/-abc]\n", argv[0]);
- return 1;
- }
- if(strcmp("-a", argv[1]) == 0)
- {
- printf("功能a\n");
- }
- if(strcmp("-b", argv[1]) == 0)
- {
- printf("功能b\n");
- }
- if(strcmp("-c", argv[1]) == 0)
- {
- printf("功能c\n");
- }
- if(strcmp("-ab", argv[1]) == 0)
- {
- printf("功能ab\n");
- }
- if(strcmp("-bc", argv[1]) == 0)
- {
- printf("功能bc\n");
- }
- return 0;
- }
指令的设计就是使用这种方式,在函数中对输入指令进行判断,再执行对应指令。无非就是使用C语言对具体功能进行封装。
先创建一段本地变量:
myval=123456
写一段代码:
- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- char* val=getenv("myval");
- if(val==NULL)
- {
- printf("未找到myval\n");
- }
- else
- {
- printf("%s\n",val);
- }
- return 0;
- }
可以发现这个程序是找不到本地变量的。
那我们使用export修改一下本地变量myval为全局变量:
export myval
可执行程序便能找到myval这个全局变量了。
我们知道,bash是一个系统进程,mytest会通过fork()变成bash的子进程。环境变量具有全局属性,可以被子进程继承。我们可以通过这些全局变量找指令路径,进行身份认证等。
而本地变量仅当前进程(bash)有效,它的子进程无效。
因为有一个PWD的环境变量,它维护着用户当前所处的绝对路径,可以看到,当用户所处的路径变化时,PWD环境变量会自动更新,我们在执行的指令,这些指令本质上是bash的子进程,它们可以拿到这个全局变量,这些指令也就知道了目前所处的绝对路径。
- #include <stdio.h>
- #include <stdlib.h>
- #define MYPWD "PWD"
- int main()
- {
- char* p=getenv(MYPWD);
- printf("%s",p);
- return 0;
- }
写完后再命令行使用sudo cp mypwd /usr/bin/将可执行程序放入/usr/bin/目录下(/usr/bin/是PATH中的一个路径,用于存放指令)
所以该类指令本质上是通过C语言封装后的接口。
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- int main()
- {
- char* name=getenv("USER");
- if(strcmp(name,"root")==0)
- {
- printf("%s\n",name);
- }
- else
- {
- printf("权限不足\n");
- }
- return 0;
- }
可以发现,通过"USER"环境变量可以对不同角色进行权限的限制。
见本文第四节。
广告别信:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。