【Linux学习】(12)环境变量

前言

在前面我们学习了进程状态、创建进程、进程调度等等,本文我们继续学习进程概念——环境变量。

一、 常见环境变量

  1. PATH:指定命令的搜索路径
  2. HOME:指定用户的主工作目录(即用户登录到Linux系统中时,默认所处的目录)
  3. USER:当前用户是谁
  4. LOGNAME:当前登录用户是谁
  5. PWD:当前进程所处路径
  6. OLDPWD:上一次进程所处路径
  7. HOSTNAME:当前机器的主机名
  8. HISTSIZE:历史命令保存的条数(history指令可以查看历史上的所有指令)
  9. LS_COLORS:ls配色方案
  10. SHELL:当前shell,它的值通常是/bin/bash
  11. SSH_TTY:当前终端设备文件

1. PATH

问题1:我们自己写的程序编译成为可执行程序后也是指令,为什么自己可执行程序在运行的时候要带【./】,而系统指令不需要?

  • 首先我们都知道要执行任何一个程序,都必须要找到这个程序对应的二进程文件!
  • 系统指令不需要指定其对应的二进程文件就可以运行,是因为Linux系统帮系统指令提供了一个PATH环境变量,PATH中存着系统指令的搜索路径。在执行指令的时候如果没有指定搜索路径,系统会自动帮我们去PATH中一个路径一个路径的搜索。
  • 我们自己的程序不在系统默认的搜索路径上,所以我们需要指定路径【./】

问题2:怎么查看(读取)PATH中的搜索路径?

echo $环境变量
  • 注意:不能echo直接打印,因为我们要查看的是PATH的内容
  • PATH的内容是一堆路径,使用【:】为分隔符在这里插入图片描述

问题3:PATH中可以再添加路径吗?如何添加?

  • 注意:PATH=路径(等号两侧不能有空格),直接添加路径,会将之前的PATH内容覆盖。(如何恢复?——》关掉Shell,重新登录)
  • PATH=$PATH:路径,新增,不覆盖。在这里插入图片描述

小结:

  1. 执行任何一个程序,都必须要找到这个程序对应的二进程文件!
  2. 为什么在执行系统指令的时候可以不用带路径?Shell怎么知道我要执行的指令在哪呢?——》因为在系统中,Shell会维护一个PATH环境变量,PATH指定了系统指令的搜索路径
  3. which在搜索搜索指令路径时,在哪搜索?——》根据PATH环境变量来搜索指令路径的

2. HOME

问题:为什么首次登录shell时,默认所处目录是在自己的家目录

  • HOME:指定用户的主工作目录(即用户登录到Linux系统时,默认所处的目录)
  • 登录shell时,shell会识别你这个用户是谁,给你填充$HOME环境变量,并默认帮你cd $HOME在这里插入图片描述

3. SHELL

问题:我们系统中,我怎么知道我当前用的是哪一个shell呢?

  • SHELL:当前shell,它的值通常是/bin/bash。在这里插入图片描述

4. 查看环境变量

使用指令查看环境变量,有两种方式:

  1. 使用echo指令,指定查看某一个环境变量
echo $环境变量名
  1. 使用env指令,查看所有的环境变量
env

使用系统调用接口:getenv

  • 头文件:stdlib.h
  • 函数声明:cher* getenv(const char *name);
  • 作用:在环境变量列表中搜索指定的 name,并返回对应值的字符串指针,即获取指定一个环境变量。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
   char who[32];
   strcpy(who, getenv("USER"));

   if(strcmp(who, "root") == 0)
   {
       printf("让他做任何事情\n");
   }
   else 
   {
       printf("你就是一个普通用户,受权限约束!\n");
   }
   
//   printf("PATH: %s\n", getenv("PATH"));
//   printf("whoami: %s\n", getenv("USER"));
   return 0;
}
  • 有环境变量USER系统就可以认识你是谁,认识你是谁就可以和文件属性中的拥有者,所属组权限作对比,就可以判断你的权限

二、什么是环境变量

1. 概念

环境变量是系统提供的一组name=value形式的变量,不同的环境变量有不同的用途,通常具有全局属性

2. 环境变量的组织方式

每一个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以‘\0’结尾的环境字符串。
在这里插入图片描述

3. main的三个参数

main函数其实是有三个参数,以前因为我们写代码时没用命令行,所以不用带参。

main函数的三个参数:

int main(int agrc, char* argv[], char* env[])
{
	return 0;
}
  • argc:表示argv指针数组的大小
  • argv:指向命令行参数表
  • env:指向环境变量表

3.1 命令行参数表

argv:指向命令行参数表

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

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

   int i = 0;
   for(; i < argc; i++)
   {
       printf("argv[%d]->%s\n", i , argv[i]);
   }

   return 0;
}

在这里插入图片描述

  • 我们在bash输入的指令,就是命令行参数
  • 命令行参数在bash看来你输入的是一个字符串,在做命令行解释的时候,它会将这个大字符串以空格作为分隔符打散为一个一个子串,然后有几个子串就初始化argc为几,每个子串的起始地址按照顺序保存到argv,最后传给main函数——》将命令行参数打散并传给main的工作是bash做的,这是指令的解析工作
    在这里插入图片描述
  • 命令行参数第一个是命令,其他的都是选项
  • 命令行参数表的最后指向NULL
  • 为什么bash要做指令的解析工作呢?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, char *argv[])
{
   if(argc != 2)
   {
       printf("Usage: %s -[a|b|c]\n", argv[0]);
       return 0;
   }
   
   if(strcmp(argv[1], "-a") == 0)
   {
       printf("功能1\n");
   }
   else if(strcmp(argv[1], "-b") == 0)
   {
       printf("功能2\n");
   }
   else if(strcmp(argv[1], "-c") == 0)
   {
       printf("功能3\n");
   }
   else 
   {
       printf("default功能\n");
   }

   return 0;
}

在这里插入图片描述

  • 因为命令行参数为指令、工具、软件等提供命令行选项的支持!!!(不同的选项,提供不同的功能)

3.2 环境变量表

env:指向环境变量表

  • 环境变量表的结构与命令行参数表的结构一模一样,最后也指向NULL。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, char *argv[], char *env[])
{
   int i = 0;
   for(; env[i]; i++)
   {
       printf("env[%d]->%s\n", i , env[i]);
   }

   return 0;
}

在这里插入图片描述

  • C/C++程序,有两张核心向量表:一、命令行参数表;二、环境变量表。
  • 所以我们一个进程在运行时,不要简单认为进程启动就是把程序加载到内存,而是在程序变成进程启动时,bash调用main函数,给main传了两张核心向量表。
  • 如上图我们发现打印的环境变量表和shell的一样,为什么?
    • 我们自己的程序本身是没有环境变量的,但是当它启动之后,变成进程就有了环境变量。
    • 这是因为我们的进程是bash的子进程,子进程可以继承父进程环境变量的信息
    • 我们所运行的进程,都是bash的子进程,bash本身在启动的时候,会从操作系统的配置文件中读取环境变量信息,子进程会继承父进程的环境变量!
    • 子进程会继承父进程的环境变量——》环境变量具有全局性

验证:子进程会继承父进程的环境变量

  • 给bash新增一个环境变量,看是否会被继承

注意:在命令行直接定义的变量,不是环境变量,是本地变量

  • 本地变量,我们在环境变量表中是查不到的
    在这里插入图片描述

如何设置一个环境变量?

  • export:设置一个新的环境变量在这里插入图片描述

重新运行我们刚才打印环境变量的程序,确实子进程会继承父进程的环境变量

在这里插入图片描述

如何清除环境变量*

  • unset:清除环境变量
    在这里插入图片描述

我们除了通过main函数的参数获取环境变量,还可以通过第三方变量environ获取

#include<stdio.h>

int main()
{
   extern char **environ;

  int i = 0;
  for(; environ[i]; i++)
  {
      printf("environ[%d]->%s\n", i , environ[i]);
  }

   return 0;
}
  • libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明。

4. 和环境变量相关的命令

  1. echo: 显示某个环境变量值
  2. export: 设置一个新的环境变量
  3. env: 显示所有环境变量
  4. unset: 清除环境变量
  5. set: 显示本地定义的shell变量和环境变量

5. 本地变量 && 内建命令

5.1 本地变量

本地变量:在命令行直接定义的变量就是本地变量

注意:本地变量不是环境变量,在环境变量表中是查不到的!

本地变量的查看有两种方式:

  • 使用echo查看
echo $本地变量名
  • 使用set查看
# set查看所有系统变量,包括本地变量和环境变量
set
# 使用管道和grep过滤,查看指定变量
set | grep 指定变量名

在这里插入图片描述

  • 注意:本地变量是不会被子进程继承的,他只会在本bash内部有效!
  • 本地变量的使用,例如:命令行的前缀,root是#,普通用户是$。
  • export:可以将本地变量导成环境变量

5.2 内建命令

在之前的学习中,我们说命令行当中执行的所有指令,都是bash的子进程。那现在就有一个问题,我们定义了一个本地变量MY_VALUE,使用指令echo可以查看,但不是说本地变量不继承吗?

echo要不要创建子进程?——》命令行所运行的指令,不一定都要创建子进程——》命令行中的命令,分为两批命令

两批命令:

  • 常规命令:通过创建子进程完成的
  • 内建命令:bash不创建子进程,而是由自己亲自执行,类似于bash调用自己写的或者系统提供的函数。例如echo,cd(bash调用chdir系统接口实现)等
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值