Linux环境变量

        本篇将进入到 Linux 中的环境变量。首先我们将会联系 main 函数中的参数来讲解命令行参数,首先先讲解了 main 函数中的两个参数 argc 和 argv,接着介绍了本篇的核心——环境变量,详细的讲解了如何使执行程序的时候,不带路径的方法,介绍了获取环境变量的三种方法,同时得出了 main 函数中的第三个参数:env,最后介绍了 Linux 中的内建命令。最后介绍了 shell 程序中的内建命令。

        目录如下:

目录

1. 命令行参数

1.1 bash的子进程

2. 环境变量

2.1 不带路径运行程序

2.2 其他环境变量/导入环境变量

2.3 在代码中获取环境变量

2.4 获取环境变量的方式

2.5 本地变量

3. 内建命令

1. 命令行参数

        我们先来探讨我们常用的 main 函数,通常我们的 main 函数都是不带参数的,但是我们可以给 main 函数带上参数吗,答案是可以的,main 函数的参数如下:

int main(int argc, char* argv[]) {

    return 0;
}

        那么关于这两个参数有什么意义呢?(argv 是一个指针数组,argc 则是这个指针数组中包含的元素个数)

        我们通过如下代码来观察 argv 指针数组中包含的元素,如下:

  1 #include <stdio.h>                                                         
  2 #include <unistd.h>  
  3                      
  4 int main(int argc, char* argv[]){  
  5     int i = 0;                     
  6     for(; i < argc; i++){  
  7         printf("argv[%d]->%s\n",i ,argv[i]);  
  8     }                                         
  9     return 0;  
 10 }  

        运行结果如下:

        通过如上的运行结果,我们可知:argv 指针数组可以获取我们命令行输入的字符串数组,并且还是一个变长数组,我们输入多少个字符串,就可以吸收多少个字符串。

        那么为什么会这么做呢?如上的操作,运行一个程序,然后使用在运行程序后面加一个 -a / -b / -c / -d 指令,其实和其他我们常用的指令非常相似,比如 ls -l,ls -n,ls -a,所以命令行参数的本质是:交给我们程序不同的选项,用来定制不同的程序功能,命令行中会携带很多的选项

1.1 bash的子进程

        bash 作为 Linux 中的一个 shell 程序,我们输入的命令都需要由他进行解释。我们先通过如下代码,来观察一些现象:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 const int g_val = 1000;
  5 
  6 int main(){
  7     printf("I am a father process, pid: %d, ppid: %d, g_val: %d\n",getpid(), getppid(), g_val);
  8     pid_t id = fork();
  9     if(id == 0){                                                                                                                                         
 10         while(1){
 11             printf("I am a child process, pid: %d, ppid: %d, g_val: %d\n",getpid(), getppid(), g_val);
 12             sleep(1);
 13         }
 14     }else{
 15 
 16         while(1){
 17             printf("I am a fathe process, pid: %d, ppid: %d, g_val: %d\n",getpid(), getppid(), g_val);
 18             sleep(1);
 19         }
 20     }
 21     return 0;
 22 }

        如上所示,当我们运行如上代码之后,子进程和父进程的 g_val 的值是一样的,说明父进程的数据,默认能被子进程看到并访问,也就是子进程可以继承父进程的数据。另一个现象是,每一次父进程的 ppid 都是2659,当我们查看的时候,发现2659为 bash 的pid。所以命令行中启动的进程,都是 bash 的子进程

        所以通过以上的连接,我们其实可以得出,我们在命令行中输入的命令行字符串,其实是被 bash 所读取,然后由 bash 把输入的字符串变为 agrv 中的参数,然后在传递给子进程(因为子进程可以继承父进程的数据),所以子进程可以根据得到的字符串,执行对应的功能

2. 环境变量

        平时我们在运行常用指令的时候,我们可以直接的运行我们的指令(或者加上一些运行参数),但是当我们运行我们自己写的程序的时候,我们就要在前面加上一个 ./ ,表示当前路径呢?

        其主要原因是在 Linux 中,存在一些全局的设置,这些设置可以告诉命令行解释器(bash)去哪些路径下执行可执行程序(命令)。如下:

        如上所示,PATH 就属于一种全局设置,这种设置在我们登陆 Linux 系统的时候,已经被加载到了 bash 进程中了(内存)。其实这种设置为环境变量,打印环境变量的内容:$PATH。最后我们获取到了 PATH 中的数据,为一串的路径,不同的路径之间使用冒号分隔开,当我们在命令行输入指令的时候,bash 就会到这些路径中去寻找指令,找到就加载运行,没找打就输出未找到。

2.1 不带路径运行程序

        通过上文已经得知,我们运行某些指令不需要带路径,可以直接的运行指令,是因为环境变量中存在进程的路径,那么假若我们想要让我们自己写的进程运行时,不需要带路径,我们可以:

        1. 将我们的程序拷贝到环境变量路径中;

        2. 将此进程的路径加入到环境变量中。

        如下:

        如上所示,我们将我们的进程加入到环境变量的路径中,我们运行程序的时候,就不需要带路径运行自己写的程序了。(加入到环境变量的路径中需要 root 权限,通常不建议将自己写的程序写入到环境变量路径中,这里只是做演示)

        如下:

        当我们在 环境变量PATH后加入当前路径之后,当前路径运行的程序也不需要加路径了。注:当我们想要修改环境变量的时候,格式为:PATH=$PATH:新路径,不能直接对 PATH 进行赋值,因为会将 PATH 的原有路径给覆盖掉,导致原来的程序也不能运行了。

        当我们想要将环境变量修改为初始状态的时候,我们只需要重新登陆我们的 Linux ,PATH 环境变量就变为初始状态了,说明对于环境变量来说,并不是存放在内存中的,而是存储在系统的对应配置文件中的,重新加载 Linux,就会重新加载对应的配置文件。

2.2 其他环境变量/导入环境变量

        上文中我们只介绍了一个环境变量,在 Linux 中还存在其他环境变量,我们可以使用指令 env 查看所有环境变量:

        如上所示,我们的 Linux 中存在很多的环境变量,在下文中我们将介绍几个常见的环境变量。

HOME:家目录,会记录每一个用户的家目录
PWD:记录当前的目录路径
SHELL:记录启动时需要使用的shell程序
HISTSIZE:记录近1000条历史命令
USER:当前使用的用户

        那么我们如何导入自己的环境变量呢?使用命令:export NAME=value,如下:

        但是这样的环境变量仅仅只在这次登陆中管用,下一次登陆 Linux 的时候,这个环境变量就不管用了,因为只是将这个环境变量写入到 bash 中,并不是写入到配置文件中,若想要永久生效,可以将其写入到配置文件中。若我们想要取消环境变量,只需要使用指令:unset NAME 即可。

2.3 在代码中获取环境变量

        上文中讲了这么多环境变量,但都是在指令行获取,我们如何在代码中获取到我们的环境变量呢?如下代码:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main(){
  5     extern char** environ;
  6     int i = 0;                                                                            
  7     for(; environ[i]; i++){
  8         printf("env[%d]->%s\n", i, environ[i]);
  9     }
 10     return 0;
 11 }

        如上所示,通过代码我们也可以获取到我们的环境变量,而我们写出的可执行文件是 bash 的子进程,上文中也提到,子进程可以获取到父进程的数据,说明我们的环境变量是在 bash 内部的。

        那么关于环境变量是如何在 bash 中组织起来的呢?在 bash 中会维护一个名为 env 的表,里面的每个元素的类型都是 char*,也就是对应的环境变量,末尾以 NULL 结尾,若想要加入一个环境变量,就是在这个表的末尾加入。在结合上文的命令行参数的内容,我们得出,bash 会默认给子进程形成两张表:argv[](命令行参数),env[](环境变量表),bash 可以通过各种方式交给子进程。那么和以上类似,在 main 函数的参数中,不仅仅可以有 argc argv,还可以有 env,如下:

        所以,在 main 中可以存在三个参数。

2.4 获取环境变量的方式

        在上文中已经提到我们可以使用 main 函数中参数 env ,也可以使用 extern char** environ 获取环境变量,我们获取环境变量的方式还有一种,通过函数 getenv("NAME"),如下:

2.5 本地变量

        在 Linux 中不仅仅有环境变量,还存在本地变量,本地变量和环境变量非常相似,但是本地变量和环境变量的区别在于:环境变量具有全局属性,而本地变量只具有局部变量。如下:

        我们设置了一个环境变量 HOOO,然后使用 echo 命令确实可以将其打印出来,但是当我们在 env 中查找时,却找不到,说明这样设置的一个变量其实是一个本地变量,并没有被放入到 env 表中。(本地变量只在本 bash 中有效,无法被子进程继承,只有将本地变量转化为环境变量,才可以被子进程继承

        当我们想要将一个本地变量变成环境变量的时候,我们只需要使用 export 修饰一下该本地变量,就可以了。如下:

3. 内建命令

        在上文中我们提到使用 export NAME 指令可以增加环境变量,同时我们也提到环境变量是在 bash 内部的,那么 export NAME 命令作为作为一个指令,一个有 bash 生成的子进程,子进程写入的数据,怎么能被父进程发现呢?上文中只提到子进程可以继承父进程的数据,并没有提到父进程可以继承子进程的数据。        

        其实在 Linux 中,大概有 80% 的命令都是 bash 生成子进程进行执行的,剩下的 20% 是由 bash 亲自执行,也就是内建命令(可以将内建命令理解为 bash 中的函数),这种命令即使修改了换件变量也还可以使用,除了 export,还有 echo 指令如下:

        如上所示,我们先将环境变量 PATH 置空,然后在运行指令 export echo 都可以运行,当我们运行指令 ls mkdir 时却不可以运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值