🏷基本概念
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性
🏷常见环境变量
PATH
: 指定命令的搜索路径
HOME
: 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL
: 当前Shell,它的值通常是/bin/bash。
🏷查看环境变量方法
📌方法一
使用指令:
指令:
echo $NAME
//NAME:你的环境变量名称
或者使用函数getenv()
eg:
printf("name: %S\n", getenv("name")); //name是环境变量的名字
📌方法二
main
函数可以有两个参数也可以有3个参数
int main(int argc, char *argv[], char *env[])
当你在linux
下输入指令env
时屏幕上会打印一大片的内容,像下面这样:
这些东西其实就是系统的环境变量,他们存放在env[]
这个数组当中
如下:
env[]
数组必须以 null
结尾
系统在启动我们的程序的时候,可以选择给我们的进程(main)提供两张表:
- 命令行参数表
- 环境变量表
我们可以写个函数来打印一下环境变量
我们这里使用的是云服务器,安装的centos7
系统
- 在
vim
中使用makefile
写一个文件,文件名:Makefile
具体的内容:
第一步使用指令:vim Makefile
第二步,在里面写下如下代码:
mytouch:myproc.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f myproc
如果无法理解上面的代码,可以去搜索:makefile 如何使用
- 使用
vim myproc.c
来创建并编辑一个名为myproc.c
的文件
文件的内容如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char *argv[], char* env[])
{
int i = 0;
for(; env[i]; i++)
{
printf("env[%d]: %s\n", i , env[i]);
}
}
保存之后推出:
在命令行中 make
后执行你的程序(mytouch
) : ./mytouch
便可以看到它把环境变量都打印出来了。
我们可以适当的修改一下myproc.c
的代码,以便来查看当前进程的环境变量,如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
int main(int argc, char *argv[], char* env[])
{
int i = 0;
for(; env[i]; i++)
{
printf("pid: %d, env[%d]: %s\n", getpid(), i , env[i]);
}
运行之后,我们可以看到打印的结果:
这个就是进程22456
运行时,系统给它的环境变量。
📌方法三
这时候我们要修改一下myproc.c
的代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
extern char **environ;
int i = 0;
for(; environ[i]; i++)
{
printf("%d: %s\n", i, environ[i]);
}
return 0;
}
然后运行上面的代码:
🏷环境变量的信息从哪里来的
当我们在命令行里输入ls
pwd
这类命令的时候,系统会执行我们的命令,命令行启动的进程都是shell/bash
的子进程, 就是说ls, pwd
这样的进程是shell/bash
的子进程。
子进程的命命令行参数和环境变量 是父进程 bash
传过来的。
这里有个疑问,那父进程的环境变量是重哪里来的呢?
我们之前就知道,当你执行一个指令的时候(比如:ls
, pwd
),它能够跑起来是因为系统当中存在着相应的环境变量,我们这里可以查看一下:
使用指令:echo $PATH
上面的环境变量,以冒号作为分割符号,会有多种路径。
同时你也可以修改这个环境变量,使用指令:PATH=''
这样你的环境变量就被改成了空串。
为啥大部分命令不能够运行呢?因为我们把他系统默认的搜索路径给清理掉了,所以找不到了。
但是这个时候你不要慌,你别以为改了之后就改不回去了,这个时侯你改的就只是内存里的环境变量 ,你把机子关了重启,一切就会恢复如初的。
其实也不是内存中的环境变量,说白了,我们修改的是bash 进程内部的环境变量信息 , 因为进程是在内存里的所以你修改就无所谓。当你登录时,系统会为你创建一个bash
来给你提供命令行服务,当你退出时这个bash
就被自动释放掉了
每一次重新登陆,都会给我们形成新的bash
解释器,并且新的bash解释器会自动重相应的位置读取自己的环境变量表信息。
环境变量信息在系统中是以脚本配置文件的形式存在的,
用cd ~
指令回到家目录
用指令ls -al
找到隐藏文件:bash_profile
当你这个用户登录时,你的shell会自动读取这个文件当中的内容。
我们可以查看一下这个文件的内容vim .bash_profile
你会发现,它里面就是有关环境变量的信息。
看到这里上面的问题的答案就揭晓了,父进程bash
的环境变量是从配置文件中来的
所以,每一次登录时,你的bash进程都会读取
. bash_profile
配置文件中的内容,为我们的bash
进程形成一张环境变量表信息。
🏷我们也可以添加自己的环境变量
比如我们自己想一个环境变量出来,先取个名字(用大写的字母遵循规则):MYENV_666
使用指令:MYENV_666=hellolinux
定义好了之后,我们使用echo $MYENV_666
来查看环境变量中的内容。
但是这个时候,如果我们使用指令env | grep MYENV_666
却找不到我们自己定义的环境变量:
因为我们自己定义的环境变量MYENV_666
并没有导入到bash
对应的环境变量表中。
所以接下来我们要把它导入到bash
对应的环境变量中
使用指令:export MYENV
就可以了。
这个时候就可以看到已经导入成功了:
我们也可以一步到位,边导入边定义自己的环境变量。
像这样: export MYENV_888=12345
==这个时候当我重启,我自己定义的环境变量留的住吗? ==
直接看结果:
没有了
因为,不管你怎么导入,你导入的地方始终是在bash
的上下文进程当中。所以你的导入只是在内存当中的,并没有更改配置文件。
接下来就是要去更改配置文件才行,配置文件的名字叫.bash_profile
我们使用指令:vim ~/.bash_profile
来编辑这个配置文件
加入下面红框内容,
这样就成功修改了配置文件,当你重启之后,你自己定义的环境变量也就不会消失了。
一旦我们导入了一个环境变量,只要我们愿意,这个环境变量是可以被所有进程读到的,所以我么经常说,系统环境变量具有全局属性
上面说到,如果我们创建一个进程,它的环境变量是从bash中获取到的,那如果我们再在这个进程中frok
一个子进程,那这个子进程能不能获取到环境变量呢?
我们来实验一下,我们首先修改一下myproc.c
的代码。
pid_t id = fork();
if(id == 0)
{
//子进程
extern char **environ;
int i = 0;
for(; environ[i]; i++)
{
printf("%d: %s\n", i, environ[i]);
}
}
sleep(3); // 让父进程睡上三秒钟
return 0;
}
我们运行上面的代码,发现这个 孙子
进程也可以获得的到环境变量:
🏷本地变量与环境变量
之前,我们试过直接在命令行定义变量
export OUR_ENV=10000
这种变量我们称为本地变量
就像这种:
a=10
b=7
...
那本地变量和环境变量有什么区别吗?
本地变量只在bash进程内部有效,不会被子进程继承下去
环境变量通过让所有子进程继承的方式,实现自身的全局性。
🏷Linux命令的分类
📌 常规命令:
shell fork 让子进程来执行的,这种命令就读取不到本地变量,因为,本地变量只在bash进程内部有效,不会被子进程继承下去。
📌内建命令
shell 命令行的一个函数,比如echo
就是,但shell 检测到是echo命令时, 就会直接执行这个函数,不会去创建子进程来执行,所以echo
就可以直接读取到本地变量。
🏷和环境变量相关的命令
echo: 显示某个环境变量值
env: 显示所有环境变量
export: 设置一个新的环境变量
export HEllO=666
unset: 清除环境变量
unset HELLO
set: 显示本地定义的shell变量和环境变量
就是可以显示包含环境变量在内的其他的本地变量
本章图集