1、基本概念:
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。
系统环境变量有多种多样,比如:
- PATH:指定可执行程序的搜索路径(命令也属于程序)
- LD_LIBRARY_PATH:指定动态库的搜索路径
举个简单的例子:
我们查看PATH这个变量,可以发现该目录下有许多路径(每个路径用冒号(:)分隔),其中包括shell命令目录。若果我们将/bin这个路径从PATH中删除掉,那么ls就不能直接使用了,而必须在命令行下输入:/bin/ls,所以为了方便,将shell命令这种可执行文件的路径加入到PATH变量中来,就可以实现不带路径执行。那么带路径也是同样的效果,如下所示(虽然我们在根目录下,但是依旧可执行/bin目录下的ls,就是因为PATH中存在/bin默认路径):
2、环境变量的操作:
(1)、对于环境变量的基本操作命令如下:
echo //显示某个环境变量值 export //设置一个新的环境变量 env //显示所有环境变量 set //显示本地定义的shell变量 unset //清除环境变量 readonly //设置只读环境变量
echo我们在上面用过了,而export则是为一个环境变量修改新的内容,我们经常在动态库制作时会这样写:export LD_LIBRARY_PATH=.
,就是将当前路径设置为动态库的搜索路径的环境变量中。注意:export只能在当前shell下生效,登出重新启动shell就失效了。
举例如下:
当我们编写一个“Hello PATH!”的打印程序时,编译完成,在运行时需要加上./path_test,而不是直接像ls那样不带路径运行path_test,因为当前目录不在PATH中,而当我们将当前目录加到PATH变量中export PATH=.
时再运行path_test就可以执行了。
但是当我们CTRL+D退出,再重新登录时,修改已经不再生效了,如下:
并且,export有个缺点:export为修改,而不是增加。它会将原有的路径完全删除,使得当前shell下不能使用基本命令,如下:
(2)、如何使得修改长期有效,并且不会覆盖原有路径?
方法如下(修改配置文件.bashrc):
①回到当前用户家目录/*cd或者cd ~都可以*/
②ls -a/*显示所有文件,.bashrc为隐藏文件*/
③vim .bashrc/*编辑.bashrc,在文件最后加上一行"export PATH=$PATH:.",保存退出*/
④重启shell后生效
注意:“export PATH=$PATH:.”千万不能写错,写错有可能导致基本的ls等命令不能使用,而且你的vim、vi都不能使用(其实是可以用的,下面再说)!!但是,只有出错,才会使得记忆更加深刻,在我第一次修改时,我就写错了(←_←)。那怎样解决呢?
方法一:重新设置PATH
PATH=/bin:/usr/bin /*vim在/usr/bin下,而vi在/bin下*/ cd vim .bashrc /*修改.bashrc文件即可*/
方法二:
既然明白方法一,那么方法二就自然而然容易明白了:
操作如下:
cd /usr/bin/vim .bashrc/*或者/bin/vi .bashrc*/ 修改.bashrc文件即可
3、环境变量与环境表:
所有的环境变量在程序中通过环境表获取;环境表是一个全局变量,类型为字符串数组指针(二级指针),以NULL结束,获取方式为:
extern char ** environ;//envioron存储环境表的首地址
举例说明:
/*在主函数中通过extern char ** environ;来获取环境表的首地址,由于环境表是一个指针数组,所以可以通过每个环境变量的首地址(数组的每个人元素)遍历该变量内容*/ # include<stdio.h> # include<string.h> int main(void) { extern char ** environ; char ** p = environ; while(*p){ printf("%s\n",*p); p++; } return 0; }
那么如何取得某一个特定的环境变量,如PATH呢?
# include<stdio.h> # include<string.h> int main(void) { extern char ** environ; char ** p = environ; while(*p){ if(strncmp(*p,"PATH=",5) == 0){/*环境变量的格式是:变量名=具体内容*/ printf("%s\n",*p); break; } p++; } }
我们还有一种方式来获取环境表:
#include<stdio.h> #include<stdlib.h> /*第三个参数就是环境表的首地址*/ int main(int argc, char ** argv, char ** env) { /*两种方法基本相同,只不过char ** env这种方法只能在main函数中使用;而extern char ** environ这种方法可以再任何一个函数中使用*/ extern char ** environ; printf("env=%p\nenviron=%p\n",env,environ);/*输出结果显示,两个首地址为同一个地址,即都是环境表首地址*/ return 0; }
这几个程序就不测试了,编译运行即可观察
4、如何用函数来对环境变量修改?
函数如下:
#include<stdlib.h> char * getenv(const char * name); /*返回值为获取的环境变量首地址,name为需要匹配的字符串,只会去除“name=”的内容*/ int putenv(char * string); /*string为创建的名字及内容创建环境变量,存在就替换*/ int setenv(const char * name,const char *value,int overwrite); /*设置一个环境变量,第一个参数是变量名,第二个是变量值(内容),第三个参数,新建或替换覆盖(overwrite为0,不替换;非零替换)*/ int unsetenv(const char * name);/*取消设置*/ int clearenv(void);/*清空*/
基本测试:
#include<stdio.h> #include<stdlib.h> int main(void) { extern char ** environ; char * path_value = getenv("PATH");/*获取PATH的内容,返回值为PATH字符串的首地址,也就是环境表数组中的PATH这个元素的首地址*/ printf("PATH=%s\n",path_value); /*创建一个自定义环境变量*/ putenv("KANGRUOJIN=123456789");/*等号左边是变量名,等号右边是内容(变量值),二者与等号共同组成这个字符串参数*/ printf("KANGRUOJIN=%s\n",getenv("KANGRUOJIN")); putenv("KANGRUOJIN=987654321");/*覆盖原有内容*/ printf("KANGRUOJIN=%s\n",getenv("KANGRUOJIN")); setenv("KANGRUOJIN","ABCDEFG",0);/*ovwrite为0不会覆盖*/ printf("KANGRUOJIN=%s\n",getenv("KANGRUOJIN")); setenv("KANGRUOJIN","GFEDCBA",1);/*ovwrite为1会覆盖*/ printf("KANGRUOJIN=%s\n",getenv("KANGRUOJIN")); return 0; }
结果如下: