当前位置:   article > 正文

Linux中的环境变量_linux环境变量

linux环境变量

一.基本概念
 

  • 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
  • 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
  • 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性
     

二. 环境变量分类

1.按生命周期分类

  • 永久的:在环境变量脚本文件中配置,用户每次登录时会自动执行这些脚本,相当于永久生效。
  • 临时的:用户利用export命令,在当前终端下声明环境变量,关闭Shell终端失效。

2.按作用域分类

  • 系统环境变量:公共的,对全部的用户都生效。
  • 用户环境变量:用户私有的、自定义的个性化设置,只对该用户生效。

三. 环境变量相关命令

1.env

env:查看当前用户全部的环境变量

2.env|grep 环境变量名

env|grep 环境变量名:筛选包含的环境变量。

3.export

export:显示当前系统定义的所有环境变量。
 

4.printenv 环境变量名

printenv 环境变量名:查看指定环境变量的值。

5.unset 环境变量名

unset 环境变量名:清除指定环境变量。

四. 常用环境变量

可执行程序的搜索目录,可执行程序包括Linux系统命令和用户的应用程序。如果可执行程序的目录不在PATH指定的目录中,执行时需要指定目录。

​ PATH缺省包含Linux系统命令所在目录(/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin),如果不包含这些目录,Linux的常用命令也无法执行(要输入绝对路径才能执行)。

  PATH=$PATH:<PATH 1>:<PATH 2>:<PATH 3>:------:<PATH N>

  你可以自己加上指定的路径,中间用冒号隔开。环境变量更改后,在用户下次登陆时生效。

  如果想立刻生效,则可执行下面的语句:

  $source .bash_profile

  需要注意的是,最好不要把当前路径”./”放到PATH里,这样可能会受到意想不到的攻击。

  完成后,可以通过$ echo $PATH查看当前的搜索路径。这样定制后,就可以避免频繁的启动位于shell搜索的路径之外的程序了。

 设置变量的三种方法
1、在/etc/profile文件中添加变量【对所有用户生效(永久的)】

用vim在文件/etc/profile文件中增加变量,该变量将会对Linux下所有用户有效,并且是“永久的”。 例如:编辑/etc/profile文件,添加CLASSPATH变量

  1. # vim /etc/profile
  2. export CLASSPATH=./JAVA_HOME/lib;$JAVA_HOME/jre/lib
  3. 注:修改文件后要想马上生效还要运行# source /etc/profile不然只能在下次重进此用户时生效。

2、在用户目录下的.bash_profile文件中增加变量【对单一用户生效(永久的)】

用vim在用户目录下的.bash_profile文件中增加变量,改变量仅会对当前用户有效,并且是“永久的”。 例如:编辑abc用户目录(/home/abc)下的.bash_profile

  1. $ vim /home/abc/.bash.profile
  2. 添加如下内容:
  3. export CLASSPATH=./JAVA_HOME/lib;$JAVA_HOME/jre/lib
  4. 注:修改文件后要想马上生效还要运行$ source /home/abc/.bash_profile
  5. 不然只能在下次重进此用户时生效。

3、直接运行export命令定义变量【只对当前shell(BASH)有效(临时的)】

  1. 在shell的命令行下直接使用[export 变量名=变量值]
  2. 定义变量,该变量只在当前的shell(BASH)或其子shell(BASH)下是有效的,
  3. shell关闭了,变量也就失效了,再打开新shell时就没有这个变量,
  4. 需要使用的话还需要重新定义。

 五.main函数的参数个数

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. int main(int argc, char *argv[])
  4. {
  5. //char *argv[]: 什么类型?里面放什么?
  6. for(int i = 0; i < argc; i++)
  7. {
  8. printf("argv[%d]: %s\n", i, argv[i]);
  9. return 0;
  10. }
  11. }

  •  我们平时在使用指令的时候会添加很多的选项比如说ls指令,单独使用ls指令会将当前路径下的每个可见文件的文件名全部显示出来并且一行显示多个文件名
  • 如果给ls指令添加-a选项就可以显示隐藏文件的文件名并且也是一行显示多个
  • 如果给ls指令添加-l选项那么可以显示当前路径下的所有可见文件的详细信息,并且一行显示一个
  • ls -l指令还可以简化成为ll并且功能还是一样的
  • 有些选项还可以结合在一起使用比如说-a选项是显示所有文件,-l选项是显示可见文件的详细信息,那-al选项就是显示所有文件的详细信息

那么上述功能的原理就和整型变量argc数组argv有关,argv数组中存储着输入的指令和选项,那么根据数组中的内容和else if语句就可以实现不同的选项执行不同的功能,比如说下面的代码:
 

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. int main(int argc,char*argv[])
  5. {
  6. if(argc>=3)
  7. {
  8. printf("指令使用错误最多支持一个选项\n");
  9. return 0
  10. }
  11. if(argc==1)
  12. {
  13. printf("开始执行功能一\n");
  14. }
  15. else
  16. {
  17. if(strcmp(argv[1],"-a")==0)
  18. {
  19. printf("开始执行功能二\n");
  20. //对应的功能
  21. }
  22. else if(strcmp(argv[1],"-b")==0)
  23. {
  24. printf("开始执行功能三\n");
  25. //对应的功能
  26. }
  27. else if(strcmp(argv[1],"-c")==0)
  28. {
  29. printf("开始执行功能四\n");
  30. //对应的功能
  31. }
  32. else if(strcmp(argv[1],"-d")==0)
  33. {
  34. printf("开始执行功能五\n");
  35. //对应的功能
  36. }
  37. else if(strcmp(argv[1],"-ab")==0)
  38. {
  39. printf("开始执行功能六\n");
  40. //对应的功能
  41. }
  42. else if(strcmp(argv[1],"-ac")==0)
  43. {
  44. printf("开始执行功能七\n");
  45. //对应的功能
  46. }
  47. else if(strcmp(argv[1],"-ad")==0)
  48. {
  49. printf("开始执行功能八\n");
  50. //对应的功能
  51. }
  52. else
  53. {
  54. printf("选项输入有误\n");
  55. return 0;
  56. }
  57. }
  58. return 0;
  59. }

我们可以测试一下上面的代码,当一个选项都不带的时候就应该执行功能一:
添加-a选项的话就应该执行功能二
添加-ab选项的话就应该执行功能六
如果添加的选项过多或者选项不存在的话就会告诉使用者选项有误

那么这就是main函数中的前两个参数的使用场景,有了这两个参数我们写的程序就可以根据不同的执行指令来执行不同的功能,指令的设计就是使用这种方式,在函数中对输入指令进行判断,再执行对应指令。无非就是使用C语言对具体功能进行封装。

第三个参数 

  1. int main(int argc, char *argv[], char *env[])
  2. {
  3. return 0;
  4. }

通过代码如何获取环境变量

  • 命令行第三个参数
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. int main(int argc, char *argv[], char *env[])
    5. {
    6. int i = 0;
    7. while (env[i])
    8. {
    9. printf("%s\n", env[i]);
    10. ++i;
    11. }
    12. return 0;
    13. }

    编译运行:

    通过数组env也可以在程序内部打印出来环境变量的内容,但是main函数为什么要加第三个参数呢?getenv函数同样可以来获取环境变量的内容,如果想要获取某一个环境变量的内容的话应该使用getenv函数,而env数组是给子进程使用的子进程是一个笼统的概念,我们可能会在子进程中使用各种各样的功能,所以环境变量的每个值可能都要得到,所以就会有这个数组方便子进程使用环境变量,我们之前说环境变量具有全局属性在任意的进程中都能使用,它之所以有全局属性的原因是在创建子进程的时候会继承环境变量,那子进程是如何继承环境变量的呢?答案就是通过main函数的第三个参数来实现继承环境变量。我们把env数组看成一个表,表中的每个元素看成一个指针,指针指向的内容就是一个个的环境变量,linux还提供给我们一个二级指针,这个指针就指向的是表中的首元素

    每 个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串

  • 通过第三方变量environ获取

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. int main(int argc, char *argv[], char *env[])
    5. {
    6. extern char **environ;
    7. int i = 0;
    8. while (environ[i])
    9. {
    10. printf("environ[%d] : %s\n", i, environ[i]);
    11. ++i;
    12. }
    13. return 0;
    14. }

     子进程在继承父进程的环境变量的时候是通过main函数的第三个参数实现的,而第三个参数是一个字符指针数组,数组在传参的时候传的是首元素的地址,所以子进程在继承环境变量的时候,系统得传一个二级指针那么这个指针就是上面使用的char**environ。

六.本地变量和全局变量的区别

先创建一段本地变量:

对本地变量进行查找

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. char* val=getenv("myval");
  6. if(val==NULL)
  7. {
  8. printf("not find myval\n");
  9. }
  10. else
  11. {
  12. printf("%s\n",val);
  13. }
  14. return 0;
  15. }

 

可以发现这个程序是找不到本地变量的。
那我们使用export修改一下本地变量myval为全局变量


可执行程序便能找到myval这个全局变量了。

1、为什么该程序只能找到全局变量却找不到本地变量?

bash是一个系统进程,myproc会通过fork()变成bash的子进程。环境变量具有全局属性,可以被子进程继承。我们可以通过这些全局变量找指令路径,进行身份认证等。而本地变量仅当前进程(bash)有效,它的子进程无效。

2、为什么执行指令时默认是当前路径

因为有一个PWD的环境变量,它维护着用户当前所处的绝对路径,当用户所处的路径变化时,PWD环境变量会自动更新,我们在执行的指令,这些指令本质上是bash的子进程,它们可以拿到这个全局变量,这些指令也就知道了目前所处的绝对路径。

3.通过环境变量限制用户权限

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main()
  5. {
  6. char* name=getenv("USER");//通过"USER"环境变量可以对不同角色进行权限的限制。
  7. if(strcmp(name,"root")==0)
  8. {
  9. printf("%s\n",name);
  10. }
  11. else
  12. {
  13. printf("权限不足\n");
  14. }
  15. return 0;
  16. }

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号