环境变量
本节目标
1. 环境变量
1.1 环境变量的概念
1.2 环境变量PATH
1.3 其他常见环境变量
2. 和环境变量相关的命令
2.1 env 命令
2.2 export命令
2.3 set命令
2.4 unset命令
3. 环境变量的意义
4. 命令行参数
4.1 什么是命令行参数?
4.2 命令行参数的作用
5. 总结环境变量
本节目标
掌握环境变量的相关知识。
1.环境变量
1.1环境变量的概念
1. 什么是环境变量?
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。
2. 为什么会有环境变量?
在Linux系统中,我们发现我们在执行一些指令时,比如ll等指令,直接就可以输入ll指令获得结果,而对于我们自己编译的程序,比如make之后的文件,就需要./文件才能执行。对于执行一个命令来说,我们知道,命令事实上也是一种文件,对于执行这个文件,我们就需要先找到这个文件,在将这个文件执行。而对于ll来说,其对应的文件事实上已经是Linux系统分配到全局的,也就是在默认路径(根目录),因此不需要指定路径搜索这个指令对应的文件,直接ll就代表从根目录查找从而执行。而对于make生成的程序,我们知道这个可执行程序是在当前路径下,并不在根目录中,因此我们也就无法直接输入文件名从而执行,而是需要找到这个文件对应的路径再去执行,因此./就代表着当前路径,而./此文件就代表找到这个文件的路径并且去执行它!
command not found就意味着并没有从根目录找到这个命令对应的文件。
经过上面的描述,我们知道,如果我们将可执行程序也复制到根目录,那么就也可以直接输入文件名就可以执行该程序了。下面演示一下:
但是这么做是不好的,因为我们在根目录下拷贝就相当于下载了一个文件,这样不经过测试的指令程序事实上会污染系统的指令池的,因此为了改善这种方式,就有了环境变量的方式去处理这种问题!
(在此之前,需要删除我们刚才已经拷贝的文件,指令:sudo rm /usr/bin/myprocess
删除成功。)
1.2环境变量PATH
为什么能够在系统中找到对应的指令呢?事实上系统中存在一个环境变量PATH,它能够去检索对应的指令,找到了就会去执行,找不到就会像上面一样提示not found,因此我们如果想用另一种方式去直接执行文件,就可以将这个文件路径添加到环境变量PATH中。
当我们查看PATH变量时,每一个:所间隔的就是一个检索的路径,因此只要把想直接执行的文件的路径也添加到这个里面,就能够检索到从而执行。
当然这里有一个小插曲,如果我们直接通过指令:export PATH=/home/cfy/sbl/lesson13,虽然可以添加到PATH中,但这样的话,PATH中的其他路径也就被覆盖了,这就导致一些系统的指令也用不了,当然这也是可以解决的,我们只需要重新登陆这个系统,就可以恢复过来,因为这些环境变量是保存在内存中的,属于内存中的环境变量。
通过指令 :export PATH=$PATH:/home/cfy/sbl/lesson13
就可以将这个指令追加到PATH环境变量中。
1.3其他常见环境变量
- HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
- HOSTNAME:主机名
- USER:当前用户名
- PWD:当前系统路径
- HISTSIZE:shell 能记忆的最多历史命令的条数
2.和环境变量相关的命令
1.echo: 显示某个环境变量值
2.export: 设置一个新的环境变量
3.env: 显示所有环境变量
4.unset: 清除环境变量
5.set: 显示本地定义的shell变量和环境变量
2.1env 命令
env: 显示所有环境变量
1.观察内部:
我们通过env命令,就可以显示这些所有的环境变量,事实上是可以通过代码来模拟的,我们拿其中的USER来演示。
2. getenv函数
即我们可以通过调用getenv来调用这里的变量,那我们先来看一下getenv的使用条件及内部参数。
通过man getenv
指令:
我们发现返回值是char* ,即满足条件返回相应的值,不满足则返回NULL。
那我们可以利用getenv来编辑代码了:
#include<stdio.h> #include<stdlib.h> #define USER "USER" int main() { char* who = getenv(USER); printf("user: %s\n", who); return 0; }
即这样就可以获取到对应的身份。此外,如果我们su -到超级用户(root),我们同样执行这个mycmd,他就会出现user: root的结果。因此,在我们执行一些命令的时候,涉及到权限的问题,其中系统就会通过USER来判断你的身份,从而显示你能否调用一些需要权限的指令。
扩展:
我们发现,bash可以直接给变量赋值,但是env并不能查到,因此这种变量只能称为shell当中的本地变量,即所谓的局部变量。我们同样通过代码验证:
#include<stdio.h> #include<stdlib.h> #define MY_ENV "myval" #define USER "USER" int main() { char *myenv = getenv(MY_ENV); if(NULL == myenv) { printf("%s, not found\n", MY_ENV); return 1; } printf("%s=%s\n", MY_ENV, myenv); return 0; }
即这样同样说明了在全局中找不到对应的myval。
2.2export命令
export: 设置一个新的环境变量
在PATH中我们已经知道,export命令可以在PATH环境变量中添加相应的路径,即可以全局查找。但我们看看下面的这种格式的命令:
与之前不同的是,这个指令里面没有=和:等符号格式,但是我们发现,仍然可以通过这种方式使得myval能够查找到。事实上,这并不是将myval添加到了环境变量中,而是因为如下原因:
我们知道,bash是一个系统进程,并且bash进程是所有创建进程的父进程,即我们./mycmd的mycmd在运行时,mycmd也会变成一个进程(fork),而bash就是mycmd的父进程。而环境变量具有全局属性,也就是说环境变量本来就是定义给bash的,但是bash的环境变量会被子进程继承下去(为什么要继承,为了不同的应用场景 ——让bash帮我找指令路径,身份认证),也就是说子进程能够使用bash的环境变量,因此mycmd能够使用bash的环境变量。而myval本地变量能够使用bash的环境变量的前提是只在当前的进程(bash)内有效。
2.3set命令
set: 显示本地定义的shell变量和环境变量
我们发现,我们所创建的本地变量(局部变量)不能被env找到,但是却可以被set找到,这也就说明了set能够找到shell本地的变量和环境变量,也就是局部变量和全局变量。
而对于set本身,因为里面既有环境变量又有本地变量,因此其内容远多于env,对于类似于续行符 \这样的符号,其内部也存在。
2.4unset命令
unset: 清除环境变量
我们在上一部分中所创建的本地变量myval仍然存在,虽然是本地变量,但由于bash的存在也就是父进程的存在,可以将此myval看成是环境变量,因此我们才可以将其显示。此外,如果我们想删除环境变量,就可以通过unset的命令删除。(myval从理解上也可作为环境变量被删除,因为bash存在,myval就有bash所对应的属性)能否被删除,这个和本地或者环境变量无关,一个东西能被添加,就一定要能被删除
即这样就将环境变量删除了。
注:对于export定义的本地变量,实际上是字符串类型,并且可以加双引号,也可以不加双引号,但是对于字符串来说,建议加上双引号,因为字符串可能会有空格这种字符。