前言:在结束完上一篇的命令行参数时,我们简单的了解了一下Linux中的环境变量PATH
,而环境变量不只有PATH
,关于更多环境变量的知识我们将在本篇展开!
本篇主要内容:
常见的环境变量
获取环境变量的三种方式
本地变量与环境变量
环境变量的配置文件
内建命令与常规命令
环境变量
- 1. 初识环境变量
- 2. 获取环境变量的方法
- 2.1 方法一:getenv
- 2.2 方法二:通过main函数
- 2.3 方法三:全局变量environ
- 3. 环境变量的配置文件
- 4. 本地变量与环境变量
- 5. 环境变量的全局性
- 6. 内建命令与常规命令
- 7. 总结
1. 初识环境变量
首先,我们先来了解一下什么是环境变量!
基本概念:
- 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
- 我们编写代码在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
- 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性
而我们介绍几个比较常见的环境变量
常见环境变量:
PATH
: 指定命令的搜索路径
HOME
: 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
PWD
: 记录当前路径,pwd就是调用了PWD环境变量
拓展:我们在登录xshell的时候系统其实会做以下操作:
- 输入用户名,密码
- 认证
- 形成环境变量
- 根据用户名,初始化HOME=/root,HOME=/home/…
- cd $HOME
在Linux中环境变量有很多,我们可以使用指令来查看所有环境变量
指令:env
系统中会存在大量的环境变量,每一环境变量都有自己的用途来完成特定的功能!
2. 获取环境变量的方法
在Linux我们有很多种方法能够过去环境变量,这里我们简单介绍三种!
2.1 方法一:getenv
其实在Linux中我们有直接获取的函数:getenv()
我们来简单操作一遍:
1 #include<stdio.h>2 #include<stdlib.h>3 4 int main()5 {6 printf("PATH: %s\n",getenv("PATH"));7 return 0;8 }
这是最简单的一种获取环境变量的方式,让我们继续来介绍几种!
2.2 方法二:通过main函数
在我们查看环境变量时,其实他也是一个类似于命令行参数表的
系统在进行创建启动程序时,可以给进程(main)提供两张表:
- 命令行参数表
- 环境变量表
而这个环境变量表也是可以通过main
函数来获取的
1 #include<stdio.h>2 #include<stdlib.h>3 4 int main(int argc, char *argv[], char *env[])5 {6 int i = 0;7 for(i = 0; env[i]; i++)8 {9 printf("env[%d]: %s\n",i, env[i]);10 }11 return 0;12 }
2.3 方法三:全局变量environ
最后要介绍的一种方法是全局变量environ
1 #include<stdio.h>2 #include<stdlib.h>3 #include<sys/types.h>4 #include<unistd.h>5 6 int main()7 {8 extern char **environ;9 int i = 0;10 for(i = 0; environ[i]; i++)11 {12 printf("%d: %s\n",i, environ[i]); 13 }14 return 0;15 }
3. 环境变量的配置文件
命令行启动的进程都是shell/bash的子进程,子进程的命令行参数和环境变量是父进程bash给我们传递的!
当我们将PATH环境变量置为空串时:
我们发现有很多的指令都用不了了,但当我们重新登录之后,又可以恢复正常!
其实:我们直接更改的是bash进程内部的环境变量信息!每一次重新登陆,都会给我们形成新的bash解释器并且新的bash解释器自动从读取形成自己的环境变量表信息!
而它的实质其实是每次重新登陆都会读取系统自带的配置文件.bash_profile
,配置文件中的内容,为我们bash进程形成一张环境变量表信息!
如果我们想让我们的环境变量能够保存可以直接在配置文件中更改,下面会讲!
4. 本地变量与环境变量
Linux中,我们可以在bash中直接定义环境变量
指令:变量名=内容
但是当我们在环境变量表里获取我们自定义的变量时,是获取不了的。使用env也获取不了刚才定义的环境变量
实际上: 我们用户自己定义的环境变量是本地变量
如果想要我们定义的环境变量我们该怎么办,这时我们需要一条新的指令
指令:export 变量名
有了export
我们就可以将我们自定义的环境变量添加到bash上下文的环境变量中
除了这种写法,我们还可以直接省略成一步。
我们用
export
指令可以将自己写的环境变量添加到父进程bash的进程上下文中,但是如果我们重新登录后,之前导入的变量是否还会存在?
- 答案很明显,我们变量之会被添加到内存中,并不会改变配置文件,所以重新登录后并不会被保存
- 因此如果我们想让我们的环境变量能够保存可以直接在配置文件中更改
5. 环境变量的全局性
环境变量的全局性能够被所有进程获取
让我们先来看看下面这段代码:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<sys/types.h>4 #include<unistd.h>5 6 int main()7 {8 pid_t id = fork();9 if(id == 0)10 {11 // 子进程12 extern char **environ;13 int i = 0;14 for(i = 0; environ[i]; i++)15 {16 printf("%d: %s\n", i, environ[i]);17 }18 }19 sleep(4); 20 return 0;21 }
我们在程序中直接创建子进程,然后让父进程什么也不做,来测试一下子进程能否获取父进程的父进程bash的环境变量?
那我们自定义的本地变量能不能被子进程继承呢?
OUR_ENV=2004printf("OUR_ENV: %s\n",getenv("OUR_ENV"));
在了解完环境变量的全局性时,我们现在再来看看本地变量和环境变量的区别:
- 本地变量只在bash进程内部有效,不会被子进程继承下去
- 环境变量通过让所有的子进程继承的方式,实现自身的全局性!
6. 内建命令与常规命令
我们在之前就提到过,bash中的指令可以直接使用,不用加./是因为存在环境变量PATH,所以我PATH置空后,这些命令就会失效
但是我们置空PATH
后,pwd
依然可以正常使用,这是为什么呢?到了这里我们有得引出新的概念:
Linux的命令分类:
- 常规命令,shell fork让子进程成执行的
- 内建命令,shell命令行的一个函数,当然可以直接读取shell内部定义的本地变量!
我们虽然让PATH挂掉了,但是我们并没有让shell挂掉,因此shell内部定义的变量我们依然可以正常使用
注意:
echo
也是一个内建命令
7. 总结
本篇我们了解环境变量,让我们来回顾一下和环境变量相关的命令:
- echo: 显示某个环境变量值
- export: 设置一个新的环境变量
- env: 显示所有环境变量
- unset: 清除环境变量
- set: 显示本地定义的shell变量和环境变量
环境变量的学习重在理解,细节比较多,而且有很多新概念,所以认真,细心的学习环境变量是很重要的。
谢谢大家支持本篇到这里就结束了,让我们期待下一篇的进程地址空间