【Linux修炼】9.环境变量

news2025/1/24 6:38:32

在这里插入图片描述每一个不曾起舞的日子,都是对生命的辜负。

环境变量

  • 本节目标
  • 1. 环境变量
    • 1.1 环境变量的概念
    • 1.2 环境变量PATH
    • 1.3 其他常见环境变量
  • 2. 和环境变量相关的命令
    • 2.1 env 命令
    • 2.2 export命令
    • 2.3 set命令
    • 2.4 unset命令
  • 3. 环境变量的意义
  • 4. 命令行参数
    • 4.1 什么是命令行参数?
    • 4.2 命令行参数的作用
  • 5. 总结环境变量

本节目标

掌握环境变量的相关知识。

1. 环境变量

1.1 环境变量的概念

1. 什么是环境变量?

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。

2. 为什么会有环境变量?

在Linux系统中,我们发现我们在执行一些指令时,比如ll等指令,直接就可以输入ll指令获得结果,而对于我们自己编译的程序,比如make之后的文件,就需要./文件才能执行。对于执行一个命令来说,我们知道,命令事实上也是一种文件,对于执行这个文件,我们就需要先找到这个文件,在将这个文件执行。而对于ll来说,其对应的文件事实上已经是Linux系统分配到全局的,也就是在默认路径(根目录),因此不需要指定路径搜索这个指令对应的文件,直接ll就代表从根目录查找从而执行。而对于make生成的程序,我们知道这个可执行程序是在当前路径下,并不在根目录中,因此我们也就无法直接输入文件名从而执行,而是需要找到这个文件对应的路径再去执行,因此./就代表着当前路径,而./此文件就代表找到这个文件的路径并且去执行它!

image-20221114184408610

command not found就意味着并没有从根目录找到这个命令对应的文件。

经过上面的描述,我们知道,如果我们将可执行程序也复制到根目录,那么就也可以直接输入文件名就可以执行该程序了。下面演示一下:

image-20221114184828927

但是这么做是不好的,因为我们在根目录下拷贝就相当于下载了一个文件,这样不经过测试的指令程序事实上会污染系统的指令池的,因此为了改善这种方式,就有了环境变量的方式去处理这种问题!

(在此之前,需要删除我们刚才已经拷贝的文件,指令:sudo rm /usr/bin/myprocessimage-20221114185337803删除成功。)

1.2 环境变量PATH

为什么能够在系统中找到对应的指令呢?事实上系统中存在一个环境变量PATH,它能够去检索对应的指令,找到了就会去执行,找不到就会像上面一样提示not found,因此我们如果想用另一种方式去直接执行文件,就可以将这个文件路径添加到环境变量PATH中。

image-20221114190020970

当我们查看PATH变量时,每一个:所间隔的就是一个检索的路径,因此只要把想直接执行的文件的路径也添加到这个里面,就能够检索到从而执行。

当然这里有一个小插曲,如果我们直接通过指令:export PATH=/home/cfy/sbl/lesson13,虽然可以添加到PATH中,但这样的话,PATH中的其他路径也就被覆盖了,这就导致一些系统的指令也用不了,当然这也是可以解决的,我们只需要重新登陆这个系统,就可以恢复过来,因为这些环境变量是保存在内存中的,属于内存中的环境变量。

通过指令 :export PATH=$PATH:/home/cfy/sbl/lesson13就可以将这个指令追加到PATH环境变量中。image-20221114191322290

1.3 其他常见环境变量

  • HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
  • HOSTNAME:主机名
  • USER:当前用户名
  • PWD:当前系统路径
  • HISTSIZE:shell 能记忆的最多历史命令的条数

image-20221114205809695

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

1.echo: 显示某个环境变量值

2.export: 设置一个新的环境变量

3.env: 显示所有环境变量

4.unset: 清除环境变量

5.set: 显示本地定义的shell变量和环境变量

对于echo和export我们已经知道其具体是如何操作的了,那么对于后几个,我们先来看看env

2.1 env 命令

env: 显示所有环境变量

1.观察内部:

image-20221114195501123

我们通过env命令,就可以显示这些所有的环境变量,事实上是可以通过代码来模拟的,我们拿其中的USER来演示。

2. getenv函数

即我们可以通过调用getenv来调用这里的变量,那我们先来看一下getenv的使用条件及内部参数。

通过man getenv指令:image-20221114200021918

我们发现返回值是char* ,即满足条件返回相应的值,不满足则返回NULL。

那我们可以利用getenv来编辑代码了:

#include<stdio.h>
#include<stdlib.h>
#define USER "USER"
int main()
{
    char* who = getenv(USER);
    printf("user: %s\n", who);
    return 0;
}

image-20221114200307118

即这样就可以获取到对应的身份。此外,如果我们su -到超级用户(root),我们同样执行这个mycmd,他就会出现user: root的结果。因此,在我们执行一些命令的时候,涉及到权限的问题,其中系统就会通过USER来判断你的身份,从而显示你能否调用一些需要权限的指令。

扩展:

image-20221114201620655

我们发现,bash可以直接给变量赋值,但是env并不能查到,因此这种变量只能称为shell当中的本地变量,即所谓的局部变量。我们同样通过代码验证:

 #include<stdio.h>
 #include<stdlib.h>
 #define MY_ENV "myval"
 #define USER "USER"
 int main()
 {
    char *myenv = getenv(MY_ENV);
    if(NULL == myenv)
    {
        printf("%s, not found\n", MY_ENV);
        return 1;
    }
    printf("%s=%s\n", MY_ENV, myenv);      
     return 0;                             
 }                                         

image-20221114202826390

即这样同样说明了在全局中找不到对应的myval。

2.2 export命令

export: 设置一个新的环境变量

在PATH中我们已经知道,export命令可以在PATH环境变量中添加相应的路径,即可以全局查找。但我们看看下面的这种格式的命令:

image-20221114204706710

与之前不同的是,这个指令里面没有=和:等符号格式,但是我们发现,仍然可以通过这种方式使得myval能够查找到。事实上,这并不是将myval添加到了环境变量中,而是因为如下原因:

我们知道,bash是一个系统进程,并且bash进程是所有创建进程的父进程,即我们./mycmd的mycmd在运行时,mycmd也会变成一个进程(fork),而bash就是mycmd的父进程。而环境变量具有全局属性,也就是说环境变量本来就是定义给bash的,但是bash的环境变量会被子进程继承下去(为什么要继承,为了不同的应用场景 ——让bash帮我找指令路径,身份认证),也就是说子进程能够使用bash的环境变量,因此mycmd能够使用bash的环境变量。而myval本地变量能够使用bash的环境变量的前提是只在当前的进程(bash)内有效。

2.3 set命令

set: 显示本地定义的shell变量和环境变量

image-20221114212622332

我们发现,我们所创建的本地变量(局部变量)不能被env找到,但是却可以被set找到,这也就说明了set能够找到shell本地的变量和环境变量,也就是局部变量和全局变量。

而对于set本身,因为里面既有环境变量又有本地变量,因此其内容远多于env,对于类似于续行符 \这样的符号,其内部也存在。

2.4 unset命令

unset: 清除环境变量

我们在上一部分中所创建的本地变量myval仍然存在,虽然是本地变量,但由于bash的存在也就是父进程的存在,可以将此myval看成是环境变量,因此我们才可以将其显示。此外,如果我们想删除环境变量,就可以通过unset的命令删除。(myval从理解上也可作为环境变量被删除,因为bash存在,myval就有bash所对应的属性)能否被删除,这个和本地或者环境变量无关,一个东西能被添加,就一定要能被删除

image-20221114214435557

即这样就将环境变量删除了。

注:对于export定义的本地变量,实际上是字符串类型,并且可以加双引号,也可以不加双引号,但是对于字符串来说,建议加上双引号,因为字符串可能会有空格这种字符。

3. 环境变量的意义

我们拿ls 指令举例:

image-20221115145025184

我们发现,ls 后的指令为什么不需要./,而是直接输入文件名就行了呢?也就是为什么ls就知道这个文件的当前路径在哪里呢?

实际上,这是因为我们有一个环境变量PWD,通过PWD就能够找到对应的路径:image-20221115145436026

我们发现,当我们cd ..到什么路径,PWD就会变成什么路径。因此,ls 就是通过这个环境变量找到了这个文件。

既然环境变量中有PWD,那我们也可以自己实现PWD指令:

#include<stdio.h>
#include<stdlib.h>
#define PWD "PWD"
int main()
{
    printf("PWD = %s",getenv(PWD));              
    return 0;                                
}                                            

image-20221115150058976

如果我们将mycmd拷贝到根目录,那么其就可以变成和pwd一样的功能。

image-20221115150157396

因此,环境变量的意义就在于其可以找到指定文件的路径。环境变量就相当于系统启动时加载到内部的全局变量。image-20221115150512719

最后别忘了将拷贝的文件删掉。

4. 命令行参数

4.1 什么是命令行参数?

在开始之前,大家回想一下,有的编译器中的main函数中存在着这样的参数:image-20221127155926598

比如上面的DevC++中,main()中有着整形的argc参数和指针数组的argv参数,事实上,这两个参数这就是我们这一节中的主角:命令行参数。

那这个所谓的命令行参数到底是个什么鬼东西?有什么作用?能用来做什么呢?有的编译器怎么就没有呢?接下来开始演示:

1. 预备工作:

在演示之前,我们要对其进行准备工作,也就是设置一下Makefile以及程序的代码:

Makefile:

image-20221127160440695

在这里,我们可以通过$脚本语言来改变之前的代码风格,即第一个$后的@代表生成的mycmd,第二个$后的^代表依赖项mycmd.c。而后面的std=c99就是我们演示此命令行参数的必须的指令,只有在c99环境下才能成功编译。

mycmd.c:

#include<stdio.h>
#include<stdlib.h>                                         
int main(int argc, char* argv[])
{
    for(int i=0; i < argc; i++)
    {
        printf("argv[%d]->%s\n",i,  argv[i]);
    }
    return 0;
}

2. 演示命令行参数:

在程序中加上命令行参数之后,我们以打印的方式看看究竟它对应的是什么东西。执行:image-20221127161200743

我们可以发现,所打印的结果,就是对应的命令行中的命令以及选项,因此我们也知道了为什么叫做命令行参数:

image-20221127161848339

但main函数是程序的入口,那么是谁调用了main函数呢?谁又将命令行参数传给了main函数呢?事实上这些都是shell和操作系统所做出的行为。因此有的编译器中没有并不是真的没有,而是隐藏在相关的位置,操作系统同样会通过命令行参数去通过命令调用这个程序。

4.2 命令行参数的作用

首先,对于我们上面所演示的两个命令行参数,具体有什么作用呢?那我们通过程序看一下:[mycmd.c]

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// ./mycmd /-a /-b /-c
// ./mycmd -ab/-ac/-bc

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        printf("Usage: \n\t%s [-a/-b/-c/-ab/-ac/-bc/-abc]\n", argv[0]);
    }
    if(strcmp("-a", argv[1]) == 0)
    {
        printf("功能a\n");
    }
    if(strcmp("-b", argv[1]) == 0)
    {
        printf("功能b\n");
    }
    if(strcmp("-c", argv[1]) == 0)  
    {  
        printf("功能c\n");
    }
    if(strcmp("-ab", argv[1]) == 0)
    {                                                                                                                                                                            
        printf("功能ab\n");
    }
    if(strcmp("-bc", argv[1]) == 0)
    {
        printf("功能bc\n");
    }
    
    return 0;
}

我们通过这样列出几个选项之后,我们就可以进行如下执行:

image-20221127165154501

我们发现,即通过命令行参数的加入,我们可以通过一个程序的不同选项去实现他不同的功能,那么这就是命令行参数的作用。我们也就知道了对于ls一类的程序是如何通过选项从而去执行不同命令的。

事实上,对于这种【通过不同选项执行一个程序的不同功能】的方式,在windows也可以去执行,当我们通过win+R快捷方式打卡windows的终端,我们输入shutdown /?就可以看到shutdown不同选项所对应的不同功能:image-20221127173810999

我们随便用两种选项举例:1.shutdown -s -t 360 : 电脑在360秒后自动关机:11.27_1

  1. 通过shutdown -a终止这个程序发生,阻止6分钟后关机。image-20221127174314709

    (自己也可以动手试一下)

1. 第三个命令行参数env

当我们明白前两个命令行参数的作用时,事实上还有第三个命令行参数:env。我们知道,env命令能够查看环境变量,在命令行参数中,env也是指针数组类型,因为环境变量实际上也都是一个个的字符串,而最后一个字符串实际上就是NULL,也就是0,因此我们在编辑代码时可以用这个作为截止条件:

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

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

那我们执行一下这个程序:

image-20221127170719857

我们发现所有的环境变量都通过这个程序显示出来,这也就代表着env这个命令行参数确实将环境变量传入了程序中。

2. 验证命令行参数env

那为了验证这个env会将环境变量都传入到程序中,我们就新建一个环境变量export myval=4444,观察运行结果:image-20221127171204243

我们在众多环境变量中发现了myval。

3. 其他显示环境变量的方法

我们知道,除了通过命令行参数显示之外,我们也可以通过getenv获取,但是我们需要明白一件事情,env命令行参数这个指针数组是从哪里传入的环境变量呢?

image-20221127174750156

事实上,env是通过C语言中第三方environ获取的,而environ本身作为二级指针保存,我们知道指针数组和二级指针可以通过解引用的方式相互转换,这也就恰恰对应了可以把environ中的内容一一传递给env,那么我们通过: man environ查看其需要的头文件并演示代码程序:image-20221127172150557

程序【mycmd.c】:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h> 
int main()
{
    extern char** environ;  //声明从文件中获取environ变量
    for(int i = 0; environ[i]; i++)  
    {  
        printf("environ[%d]: %s\n", i, environ[i]);
    }
    return 0;
}

结果:image-20221127172643391

我们同样也能通过这种方法获取到环境变量。

因此,我们知道在进程上下文中三种获取环境变量的方式:getenv函数获取、命令行参数char* env[]获取,第三方extern char** environ获取。其中推荐的是getenv获取,因为可以指定获取。

5. 总结环境变量

通过上面的描述,我们知道,环境变量就是操作系统启动之后将内部内容加载到内存中的变量,也就是全局变量。通过环境变量,我们可以对一些所需要的环境进行配置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/40201.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Array reduce() 如何计算元素内数值总合,计算总合

Array reduce() 如何计算元素内数值总合&#xff0c;计算总合 一、需求 有时候我们需要计算一个数组中所有元素的总合&#xff0c;这个数组可能是组 Number 类型&#xff0c;也可能是 Object 类型&#xff0c;像这样&#xff1a; const tempArray [2,3,4,6,456,89,24] // 或…

1.1MQ的基本概念,优劣势介绍及 RabbitMQ简介

1.MQ的基本概念 1.1 MQ概述 M Q 全称 Message Queue 消息队列&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间的通信。 1.2 MQ 的优势 1.2.1应用解耦 当订单系统强依赖库存系统&#xff0c;支付系统&#xff0c;物流系统等&#xff0c;若其中一个系…

Lambda求和函数在excel上的应用

目录 一、Lambda函数 二、Lambda求和函数 三 、实际表格运用 四、计算结果 一、Lambda函数 Lambda函数是使用lambda运算符创建的&#xff0c;其语法如下&#xff1a; 语法&#xff1a; lambda 参数&#xff1a;表达式 Python lambda函数可以包含任意多的参数&#xff0c;但…

Js逆向教程-16极验滑块 找到w加密位置

作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; Js逆向教程-16极验滑块 找到w加密位置 一、如何下第一个断点 https://www.geetest.com/demo/slide-float.html 接口有多个w参数&…

springboot+vue 任课教师考评评价系统 Java 前后端分离

随着我国教育改革的发展&#xff0c;各大高校的大学生数量也在不断的增加&#xff0c;相对应如何去评价教学的质量问题也是很多高校一直以来所关注的内容。只有有了一个好的教学评价制度才能够让各大高校的教学质量稳步提升&#xff0c;本系统就是这样一个根据各项指标对教学质…

day77:注解、自定义注解、元注解

一、注解 1.什么是注解 注解是对程序进行标注和解释 2.常用注解 Override 描述子类重写父类的方法Deprecated 描述此方法已过时SuppressWarnings 压制警告 3.图解 4.注解与注释的区别 注解&#xff1a;给编译器看的&#xff0c;让虚拟机知道程序的特殊功能注…

【吴恩达机器学习笔记】

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为学习吴恩达机器学习视频的同学提供的随堂笔记。 &#x1f4da;专栏简介&#xff1a;在这个专栏&#xff0c;我将整理吴恩达机器学习视频的所有内容的笔记&…

PostgreSQL 同步复制原理解析

背景 Postgresql 在主备架构的场景下&#xff0c;支持同步流复制功能。本文将以一主一备架构为例&#xff0c;介绍同步流复制&#xff08;同步备机&#xff09;的工作方式以及内核代码的相关原理。 配置同步备机 工欲善其事&#xff0c;必先利其器。我们现简单的配置一个同步…

微信小程序图书管理系统

目 录 摘 要 I Abstract II 目 录 V 1 绪论 1 1.1研究背景 1 1.2研究课题和意义 2 1.3研究内容和论文结构 3 2 移动网络环境下图书管理系统的现状分析 4 2.1移动网络环境下图书管理系统的特点 4 2.2当前国内外移动网络环境下图书管理系统的现状 7 2.3微信给移动网络环境下图书管…

遥感技术及高分遥感影像在地震中的应用及高分二号获取

长期以来&#xff0c;地震预报监测、灾害调查、灾情信息获取主要依靠实地勘测手段&#xff0c;其获取的数据精度和置信度虽然较高&#xff0c;但存在工作量大、效率低、费用高和信息不直观等缺点。遥感技术手段可在一定程度上克服传统实地勘测手段的缺点&#xff0c;并具有其他…

我参加第七届NVIDIA Sky Hackathon——训练ASR模型

如何从0开始训练自己的ASR模型 第一步 获取NGC密钥 第二步 配置Ubuntu22.04的运行环境 第三步 开始训练ASR模型 文章目录如何从0开始训练自己的ASR模型前言一、获取NGC密钥二、配置Ubuntu22.04的运行环境1.安装 NVIDIA 驱动 460 以上版本2.安装 docker 与 nvidia-docker23.安装…

iClient for Leaflet实现动态绘圆的几何查询

作者&#xff1a;ls 【目录】 背景前期准备呈现效果实现过程完整代码 【背景】 几何查询是WebGIS项目中一项比较常用的功能&#xff0c;SuperMap iClient 产品支持的几何对象类型众多&#xff0c;能够满足用户的许多需求。 近期遇到许多小伙伴反应&#xff0c;绘制圆形进行…

spring复习03,注解配置管理bean

spring复习03,注解配置管理bean注解的配置1.标识组件的常用注解&#xff1a;2.扫描组件&#xff1a;3.基于注解的自动装配&#xff1a;4.使用注解以后:基于注解自动装配的小例子1.dao层&#xff1a;2.service层&#xff1a;3.controller层&#xff1a;4.spring配置文件5.测试输…

Python控制程控电源

文章目录前言一、环境搭建二、使用步骤三、执行结果总结前言 本文章主要是记录汽车电子或嵌入式设备自动化测试中&#xff0c;部分场景需要控制被测设备的供电电源&#xff0c;以下就以常见的艾德克斯程控电源为例&#xff0c;分享如何通过Python来控制程控电源。 一、环境搭建…

Java字符串(String类)

目录 &#x1f6f4;一.认识String类 &#x1f6f4;二.String类的使用 &#x1f384;2.1构造字符串 &#x1f384;2.2字符串长度 &#x1f384;2.3String对象的比较 &#x1f384;2.4字符串查找 &#x1f45c;charAt方法 &#x1f45c;indexOf方法 &#x1f45c;lastI…

浅谈 Class.forName() 的用法

目录 什么是class对象 获得class对象的三种方法 class的作用和方法 Class.forName()用法 什么时候用Class.forName()&#xff1f; newInstance和new关键字的区别 应用问题解析 情景一&#xff1a;载入数据库驱动的时候 情景二&#xff1a;使用AIDL与电话管理Servic进行通…

[Spring Boot 5]安全管理

本文介绍了Spring Security 以及Shiro 在Spring Boot中的使用&#xff0c;对于Spring Security 有基于传统认证方式的Session认证&#xff0c;也有使用OAuth 协议的认证。一般来说&#xff0c;传统的Web架构中&#xff0c;使用Session 认证更加快速&#xff0c;但是&#xff0c…

2. 如何给在 SAP Business Application Studio 里开发的 OData 服务准备测试数据

在开始本步骤的学习之前,请大家务必完成前一步骤1. SAP Business Application Studio 里创建一个基于 CAP 模型的最简单的 OData 服务的学习。换言之,大家已经在 SAP Business Technology Platform 上的 Business Application Studio 里,创建好了 Dev Space,并且拥有一个能…

JVM 别和我说你还不知道这几种垃圾回收器?Serial |Parallel|ParNew|CMS|G1|ZGC

Serial / Serial Old 从单词翻译过来看 serial 串行&#xff0c;每次它就是一款单线程收集器。 Serial 工作在新生代垃圾回收&#xff0c;Serial Old在老年代进行垃圾回收&#xff0c;Serial Old一般作为CMS 并发收集失败后的备选回收方案。 在垃圾收集器面前&#xff0c;它…

《Flowable流程引擎从零到壹》引入日志框架和部署流程定义

14天学习训练营导师课程&#xff1a; 邓澎波《Flowable流程引擎-基础篇【2022版】》 邓澎波《Flowable流程引擎-高级篇【2022版】》 学习笔记《Flowable流程引擎从零到壹》回城传送 ❤️作者主页&#xff1a;小虚竹 ❤️作者简介&#xff1a;大家好,我是小虚竹。Java领域优质创…