我们下面来讲一讲Linux中的环境变量
目录
一、什么是环境变量
二、查看环境变量
2.1 env指令
2.2 在代码中查看环境变量
2.2.1 调用main形参
main函数前两个形参的解析
2.2.2 使用environ变量
2.2.3 使用函数getenv
三、创建环境变量
四、环境变量的全局属性
五、环境变量PATH的讲解
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
环境变量本质就是一个内存级的一张表,这张表由用户在登陆系统的时候,进行给特定用户形成属于自己的环境变量表。每一个环境变量中,都有自己的用途:有的是进行路径查找的,有的时进行身份认证的,有的时进行动态库查找的,有的是用来进行确认当前路径等等
那么环境变量对应的数据,都是从哪里来的呢?
答案是从系统的相关配置文件中读取进来的!
我们可以在我们的Linux环境中进入到我们的根目录,然后查看一下目录里的文件:
其中可以看到有.bash_profile和.bashrc两个文件,这两个文件就是系统配置文件
现在都来看一看:
我们可以看到该两个文件都使用了脚本,我们目前还无法读懂,没关系我们慢慢深入学习。
在Linux中我们可以使用env指令来查看当前用户的所有环境变量:
下面来稍微做一下解释:
XDG_SESSION_ID:当前用户会话的唯一标识符。
HOSTNAME:主机系统的名称。
TERM:运行shell时模拟的终端类型。
SHELL:shell程序的路径。
HISTSIZE:命令历史中记住的命令数量。
SSH_CLIENT:SSH连接的客户端信息。
OLDPWD:上一个工作目录。
SSH_TTY:与当前SSH会话关联的TTY设备。
USER:当前用户名。
LD_LIBRARY_PATH:首先搜索库的目录的冒号分隔列表。
LS_COLORS:使用ls命令时,不同文件类型的颜色设置。
MAIL:用户邮箱的位置。
PATH:shell查找命令的目录的冒号分隔列表。
PWD:当前工作目录。
LANG:定义系统语言和国家。
HISTCONTROL:确定历史列表中如何处理重复条目。
HOME:当前用户的主目录。
LOGNAME:已登录用户的名称。
SSH_CONNECTION:SSH连接的远程信息。
LESSOPEN:less在打开每个文件时运行的命令。
XDG_RUNTIME_DIR:存储用户特定运行时文件的目录。
_:运行的最后一个命令。
在C语言中,main函数是可以传入形参的,只不过我们从来没有用过
main函数包含了三个形参:
int main(int argc, char *argv[], char *envp[])
我们先来看到第三个参数envp,它是一个char类型的指针数组,即该数组内存放的全部是char*类型的指针,每一个指针都指向了一个环境变量的字符串,并且最后一个有效数据的后一个指针指向的是NULL
这样一来直接遍历一篇envp,看看里面存的是什么:
int main(int argc, char *argv[], char *envp[])
{
for(int i=0;envp[i];++i)
{
printf("envp[%d]:%s\n",i,envp[i]);
}
return 0;
}
运行结果:
如此一来也达到了env指令的效果
main函数第三个形参传入的是环境变量表,那前两个参数是干嘛的?
第一个argc参数很简单,传入的是数组argv有效元素的个数,那第二个argv数组里是什么呢?
我们不妨打印出来看看:
#include
int main(int argc, char* argv[])
{
int i=0;
for(i;i
我们发现argv每个元素对应的是我们输入的指令的字符段!
每个用空格符分开的字符串(包括了我们所输入的指令和命令行参数)都会被存入argv!
可是这样子有什么用呢?
我们可以根据我们输入指令后面的选项对应实现不一样的功能:
#include
#include
#include
#include
void passage(const char* argv)
{
printf("\n passage:%s -[a|b|c]\n\n",argv);
exit(0);//终止程序
}
int main(int argc, char* argv[])
{
if(argc==1)
passage(argv[0]);
int i=1;
for(i;i
运行效果:
如果我们不想调用main函数的形参,也可以使用environ变量来查看:
我们可以看到该变量类型是char**(一个二级指针),包含在头文件unistd.h中
下面我们来试试看:
#include
#include
int main()
{
extern char** environ;//使用environ前先声明
int i=0;
for(i;environ[i];++i)
{
printf("environ[%d]:%s\n",i,environ[i]);
}
return 0;
}
运行效果:
也达到了相同的效果
用上述两个方法如果我们只想获取特定的环境变量还需要遍历一遍,十分的不方便。在这里推荐使用getenv函数(包含在头文件stdlib.h中):
下面我们使用该函数自己模拟实现pwd指令:
#include
#include
int main()
{
char* pwd=getenv("PWD");
if(pwd==NULL)//检查是否获取成功
perror("getenv");
else
printf("%s\n",pwd);
return 0;
}
运行效果:
我们在上述知道了环境变量实质上是一张表,在Linux环境下我们也可以直接创建环境变量
使用export指令来在环境变量中导入环境变量(如果该环境变量存在则会被修改):
export 环境变量名 = 想要定义的数据
下面我们来实验一下:
我们可以看到shell很好的将我们所要创建的环境变量导入到了表中
接下来我们验证一个:子进程是可以拿到父进程中的环境变量表中的数据的
我们知道所有的指令的运行进程都是建立在bash进程下的,我们所创建的环境变量是被保存在bash进程中所创建的空间下的,所以我们来写一段代码看能不能读取到bash中的环境变量:
#include
#include
int main()
{
char* hello=getenv("PWD");
if(hello==NULL)//检查是否获取成功
perror("getenv");
else
printf("%s\n",hello);
return 0;
}
运行结果:
我们可以看到子进程是可以读取父进程中的环境变量表的,即环境变量有全局属性。
在正式介绍这个环境变量之前,这里问一问大家:为什么Linux的指令输入了就可以直接运行(例如:ls、touch、mkdir等等),而为什么我们之间写的运行程序前面需要加上./才可以运行?这些指令也是可运行程序啊,为什么使用它们就不需要加上./呢?
这就是因为.表示当前路径,而/是路径分隔符,./就表示在当前路径下查找运行程序,所以说Linux下的基本指令可以直接运行的原因是系统可以自动在特定的目录下查找可运行程序,而这个目录不包含我们所写的可运行程序的目录,导致了我们要使用./来指定相对地址进行访问。
而保存指定命令的搜索路径的东西是一个叫PATH的环境变量
我们可以在使用echo指令来查看PATH所保存的具体的目录(在这里$有点类似于C语言中解引用的操作,如果不加$只能输出PAYH这四个字符):
我们可以看到,在我的环境下PATH中有七个目录,它们分别用:进行了分隔。
下面我们使用export指令来更改一个PATH这个环境变量:
在上面我们首先查看了当前运行程序所在目录,再使用export指令直接将PATH环境变量直接修改为当前所在目录,接着我们不加./直接运行myproc发现成功了!最后我们再查看一个PATH发现它只存有当前这个目录了,其他的指定目录全部都没了
当我们再使用ls这些Linux基本指令时已经不行了,没关系我们退出xshell,重新登录就可以恢复了。
从这个情况我们看出,上面操作是不合理的,我们不应该将PATH全部替换,而是在原有的目录上增添。这样子我们在PATH=后面加上$PATH:再跟上想要添加的目录即可:
当然我们不修改PATH这个变量,直接将想要直接运行的程序添加到PATH所包含的目录下也是可以的
本期博客又要结束了,下一期很快和大家见面~