一、环境变量
1. 概念
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
如:在Windows系统下,很多软件安装都需要配置环境变量,比如安装jdk,如果不配置环境变量,在非软件安装的目录下运行javac 命令,将会报告找不到文件类似的错误。
再如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们所链接的动态静态库
在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
环境变量通常具有某些特殊用途,而且在系统当中通常具有全局特性
2. 常见环境变量
PATH
: 指定命令的搜索路径
HOME
: 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL
: 当前Shell,它的值通常是/bin/bash
3. 查看环境变量
echo $NAME #NAME:你的环境变量名称
4. 环境变量应用场景
- PATH
我们知道自己写的代码编译生成的可执行程序必须带上路径才能运行
有什么方法可以不用带路径,直接就可以运行呢?就像ls
指令一样可以直接执行,不需要带路径
- 将我们的程序所在路径加入环境变量PATH当中,
export PATH=$PATH:mytest程序所在绝对路径
注意,现在设置的PATH变量都是临时的,在当前shell退出或者系统重启后即失效
- 将可执行程序拷贝到/usr/bin/目录下
sudo cp mytest /usr/bin/
这样就可以直接执行mytest程序,不用带路径。
- HOME
执行 cd ~
和pwd
,会进入家目录和打印当前工作路径,那么系统是如何知道家目录在哪,当前路径在哪。实际上系统是通过环境变量HOME和PWD来辅助完成的,cd -
回到上一次的路径,同样是借助环境变量OLDPWD完成
用root和普通用户,分别执行 echo $USER
, 会打印出root和用户名,我们知道一些操作是只有root才能执行的,系统也是通过环境变量USER来区分命令的执行者是谁。
二、环境变量相关的命令
- echo: 输出字符串或提取后的变量值
- export: 将变量提升成环境变量
- env: 显示所有环境变量
- unset: 清除环境变量
- set: 显示本地定义的shell变量和环境变量
三、获取环境变量的方式
每个程序都会有一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串
1. 通过命令行参数获取
一个C程序是从main函数开始执行的,main函数是操作系统调用的函数,而main函数实际上是有三个参数:
- argc - 命令行参数个数
- argv - 命令行参数数组 (命令行参数以字符串形式“存储”于指针数组中)
- env - 环境变量数组 (环境变量以字符串形式“存储”于指针数组中)
#include <stdio.h>
int main(int argc, char* argv[], char* env[])
{
for (int i = 0;argv[i]; ++i) {
printf("argv[%d]: %s\n", i,argv[i]);
}
for (int i = 0;env[i]; ++i) {
printf("env[%d]: %s\n",i, env[i]);
}
return 0;
}
2. 通过environ获取
libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时要用extern声明。
#include <stdio.h>
int main()
{
extern char** environ;
for (int i = 0;environ[i]; ++i) {
printf("%s\n", environ[i]);
}
return 0;
}
3. 系统调用getenv获取
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%s\n", getenv("USER"));
return 0;
}
四、全局变量和局部变量
环境变量分为两类:
- 全局变量
- 局部变量
全局环境变量对bash和生成的所有子进程都是可见的。局部变量只对进程自己可见
#include <stdio.h>
#include <stdlib.h>
int main()
{
char * env = getenv("MYENV");
if(env) {
printf("%s\n", env);
}
return 0;
}
直接查看,发现没有结果,说明该环境变量根本不存在
export MYENV="hello world"
再次运行程序,发现结果就有了。说明:环境变量是可以被子进程继承下去的