目录
环境变量
常见环境变量
HOME
和环境变量相关的命令
通过代码如何获取环境变量
环境变量参数
通过第三方变量environ获取
通过getenv函数来特定访问获取
通过setenv函数来特定访问获取
环境变量
命令:which ls
将命令ls的完整路径写入到标准输出。
#include <stdio.h>
int main()
{
while(1)
{
printf("hello world\n");
sleep(1);
}
return 0;
}
都是可执行程序,但是系统自带可执行程序能直接运行,而我们写的可执行程序需要带路径。
- 初识:
系统命令可以直接运行,我们自己写的程序必须带路径!
- 问题:
如果不想带?如果我们想让和运行一个普通命令一样,可以运行我们的程序该怎么办?
(以环境变量PATH为例)
查看环境变量方法
命令:echo $NAME //NAME:环境变量名称
查看环境变量名称中所存储的环境变量
因为如果想让系统运行一个命令,必须先找到它,所以不带路径,系统就没办法找到我们所写的程序,而系统的命令是默认可被找到的。原理就是利用环境变量。
命令:echo $PATH
查看PATH中所存储的环境变量
系统执行ls命令,即找到类似的位置,系统会在环境变量内以' : '为分割,经过一一对应的在每段路径下寻找。所以,PATH环境变量里维护了大量的路径,是搜索命令时的路径。
如果想将我们所写的可执行程序如同系统命令一样执行的方法有:
- 将我们可执行程序,拷贝放到PATH环境变量中的任意一个一个路径中。(强烈不推荐!因为拷贝放置这个行为就叫做安装,相当于把我们写的命令安装到系统里了,但是,这样会污染别人写的命令池的)
- 将我们当前所写的程序的路径放在PATH环境变量里:
可以使用pwd命令查看当前可执行程序的位置:博客此处是/home/qcr/linux/test_22_12_4
命令:export PATH=$PATH:/home/qcr/linux/test_22_12_4
将我们当前所写的程序的路径放在PATH环境变量里
which在环境变量PATH中查找命令(可执行程序)的所处路径
不用担心,一般命令行上更改环境变量,只会在本次对话当中、本次登陆当中时被修改,当退出此次登录后就无效了。所有的环境变量实际上都是在系统的配置文件上保存着的,所以当启动之前自己改动过配置文件,就会影响,而且影响很大,如果不改配置文件,就在命令行上,就可以谁便乱搞了。
常见环境变量
- PATH : 指定命令的搜索路径
- HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
- SHELL : 当前Shell,它的值通常是/bin/bash。
(看Linux中所有的环境变量)
使用命令env(environment的缩写)。
命令:env
打印当前bash的全部环境变量。
HOME
当前用户的家目录会保存在里面。
命令:echo &HOME
取出并在命令行上打印HOME中保存的当前用户的家目录。
和环境变量相关的命令
- echo: 显示某个环境变量值
- export: 设置一个新的环境变量
- env: 显示所有环境变量
- unset: 清除环境变量
- set: 显示本地定义的shell变量和环境变量
通过代码如何获取环境变量
命令行main函数第三个参数
#问:main函数可以带参数吗?如果可以,那main函数最多可以带几个参数?(main函数有三个参数)
int main(int argc, char *argv[], char *env[])
{
return 0;
}
环境变量参数
其是每一个在进程启动的时候,启动该进程的进程传递给它的环境变量信息,都可以以该参数传导进来。而环境变量参数的类型为指针数组,所以实际上的结构为:
数组内是char*类型的, 保存的是环境变量字符串。以此形式一个个的维护起来。然后再把这个数组整体作为一个参数传递给我们所对应的main函数。
我们可以尝试将其打印出来:
#include<stdio.h>
int main(int argc, char *argv[], char *env[])
{
printf("begin.....................\n");
for(int i = 0; env[i]; i++){
printf("%s\n", env[i]);
}
printf("end.......................\n");
return 0;
}
通过第三方变量environ获取
通过代码如何获取环境变量,除上述main函数中利用env[]查看环境变量外,还可以利用通过第三方变量environ获取。
man environ
#include <stdio.h>
int main(int argc, char *argv[])
{
extern char **environ; //声明一下,申明environ这个环境变量是系统给的
printf("begin.....................\n");
for(int i = 0; environ[i]; i++){
printf("%s\n", environ[i]);
}
printf("end.......................\n");
return 0;
}
就相当于C语言提供的全局变量,但刚启动的时候该指针就会被指向环境变量表,以通过此方式获取。
注:前两种获取方式main与environ,几乎是都不会用的,因为最致命的缺陷就是将环境变量当字符串了。所以后买你提取并使用哪个环境变量还需要自己分析。
通过getenv函数来特定访问获取
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%s\n", getenv("PATH"));
return 0;
}
通过setenv函数来特定访问获取
man setenv
我们之所以能使用一些方法获取变量,是因为是有导入,导入是由父进程导入的,是通过由父进程那里继承得来的,父进程又由它的父进程继承过来的,所以一定会有最开始,命令行写shell的时候是从bash作为开始的。
因为在命令行上运行命令,包括自己执行自己的程序,所有的最初父进程都是当前bash:
验证是bash作为最开始向下导入的环境变量:
- 向bash中导入一个不存在的环境变量:
命令:exprort hello=你好
在当前bash,增加一个名为hello内容为你好的环境变量。
命令:env
打印当前bash的全部环境变量,通过加入管道可以针对性的查找环境变量。
- bash向下导入了:
int main()
{
printf("%s\n", getenv("hello"));
return 0;
}
所以我们在bash当中,可以通过向bash当中导入环境变量,这样所有的子进程就会继承环境变量。而bash有它的子进程,而子进程又有着自己的子进程,如果不更改默认参数,那么环境变量就会像一颗树一样传递下去。所以环境变量具有全局属性。
环境变量具有全局属性的本质:可以被所有子进程继承下去,所有进程都可以拿到环境变量。
Note:
命令:hello=你好
此时的hello不是环境变量,而是局部变量。
在命令行我们可以定义两种变量:
- 环境变量(全局变量)
- 局部变量(普通变量)。
这个时候需要通过命令:set(打印当前bash的所有变量),然后加上管道查询变为命令:set | grep hello才能查到局部变量hello。
如果在执行文件中使用getenv函数查询hello,是会出现段错误,局部变量(普通变量)是不会被子进程继承下去,这就是局部变量(普通变量)与环境变量(全局变量)的区别。
命令行main函数第一、二个参数
argc是命令行参数的个数,argv[]是存储命令行参数的char*类型的指针数组。
命令行参数就是,对于执行的时候传入的选项,看作字符串,将其用指针数组存起来。
#问:那为什么要有这两个参数?有什么意义?
答:这两个参数,就是我们日常使用的命令行命令,之所以带上选项就不同的原因。(如:ls的ls -a、ls -a -l),通过此实现同一个程序的不同功能选项的含义。换而言之命令行参数也是父进程。