Linux操作系统——进程(五)环境变量
环境变量
有了我们前面的命令行参数的理解基础呢,我们下面进入环境变量这一个部分的内容的学习。
一般在我们安装一些开发工具尤其是有解释器的开发工具的时候,我们呢一般都要配置环境变量,可能都不太清楚自己为什么要配置环境变量?
一般呢,大家稍微注意一下就能够知道一般我们都会给什么Java的JDK啊,python的解释器,或者eclipse,IDEA进行配置环境变量。
那么我们前面写了个我们自己的touch命令发现我们自己写的touch命令在运行的时候需要带上./mytouch才能运行,而系统命令是自己输入命令+选项就可以直接运行了。

其实这就是跟我们的环境变量有关系了。
首先要执行我们的命令,就必须要先找到命令所对应的可执行程序!
而之所以我们运行我们自己写的touch命令的时候需要带上./的原因就是告诉系统,我们要执行的可执行程序就在当前目录下,其实我们的系统命令为什么没有带上找到他的路径呢?其实系统命令也可以通过给出搜索路径来进行执行命令,那么不用带搜索路径说明系统就一定有它默认的搜索路径

我们发现系统命令也可以带路径执行,也可以不带路径执行,而我们自己的可执行程序不带./的话发现我们的bash找不到该命令。
所以呢,在Linux当中会有一个环境变量通过指令echo $PATH查看环境变量,可以记录我们的可执行程序的搜索路径。

打印出来了一长段的字符串,每一个子串其实就是可执行程序的搜索路径,这些可执行程序的路径都是以:作为分隔符,那么假设我们输入一条命令ls,系统会以:作为分隔符在这些搜索路径中进行查找是否有对应的可执行程序,如果找到了那么当然就可以直接运行了,如果没有找到那就会出现如下一条提示:
![]()
命令没有找到。
那么我们如何添加这里的环境变量呢?
通过输入命令:PATH=$PATH: 可执行程序的搜索路径
例如:

发现我们的可执行程序搜索路径配置好了环境变量,此时可以直接输入mytouch命令可以不用再带./,当然带上./也能正常运行,这样就可以理解为什么系统指令不用带路径执行了。

我们可以看到通过配置之后,指令可以正常运行了。
那么如果我们不想要该环境变量怎么办呢?
可以通过给PATH重新赋值:

此时我们的环境变量又改过来了,我们运行mytouch 可执行程序发现:

又只能用./方式运行了,因为我们没有给该可执行程序配置环境变量,也就是可执行程序的默认搜索路径。
在我们的xshell当中,默认更改环境变量只限于本次登录,重新登陆环境变量会被自动恢复。
下面我们修改代码为如下所示:

我们只对可执行程序进行打印就行了。
我现在呢不想把我们的可执行程序的路径添加到我们的环境变量里,我们就想把我们的可执行程序给拷贝到我们的系统路径下。下面通过执行如下操作就能够将该可执行程序拷贝到系统路径下:

这种操作需要提高你的权限所以前面我们需要加一个sudo,执行完之后我们which mytouch就可以看到我们的可执行程序就被成功的拷贝到系统目录下了:

然后我们执行mytouch命令:

这样呢跟我们所执行的ls系统命令就没有什么区别了,就不需要带./,可以用which来查看该命令所在的路径了。像这种操作我们可以把它称之为程序安装。
![]()

上面我们执行上述sudo rm /usr/bin/mytouch把该可执行程序从系统目录中删除就叫做程序卸载。
我们发现再去执行该命令就执行不了了。
现在呢我们改环境变量只是临时的去修改环境变量,那这些环境变量一开始是从哪里来的呢?我们还没开机呢?我们也会进行重启啊,那么PATH里为什么就默认有那些路径呢?那如果我想要让我们的环境变量永久有效呢?
所以,我们的环境变量并不是单纯的在内存中创建的,它一定是从某些配置文件中去读取的,其实我们的系统中呢会存在很多的配置文件,有一类配置文件是在我们命令行启动的时候会把我们预设的环境变量和变量的值给我们导入进来的,所以为什么我们改了之后会重启我们的xshell之后他又会失效,原因就在于重新登录之后系统是会重新从配置文件中去读取这些环境变量的。
下面我们再认识一个环境变量:PWD

系统他怎么知道我们在当前哪个路径呢?我们执行pwd能够将我们当前所在的路径打印出来,然后我们进入上一级目录之后再pwd发现打印的路径也随之改变了。
其实呢系统中有这么一个环境变量:PWD专门为bash内置的用来记录我们当前所处的路径的一个字段,而我们的pwd命令只需要读取PWD将其打印出来就可以了。

下面我们再说一个环境变量:HOME

为什么普通用户所处家目录默认是/home/XXX呢?
为什么root用户所处的家目录默认是/root呢?
原因就在于系统中一定有一个环境变量,这个环境变量比我们登录还要早,在我们登陆的时候呢可以识别出我们的用户,因为我们登录的时候是输入了用户名的,然后可以识别到我们是普通用户还是root用户。然后形成对应的环境变量。然后根据用户名初始化我们的环境变量。
登录的时候:
1.输入用户名和密码
2.认证
3.认证通过后会形成环境变量(肯定不止一个,PATH,PWD,HOME).
3.1根据用户名初始化HOME=/home/XXX,HOME=/root
4.cd $HOME
上面我们已经了解了三个环境变量PATH,PWD,HOME.
其实环境变量有很多,那么我们如果想要查看系统默认初始化的所有的环境变量我们该如何查看呢?
我们可以通过执行命令:env
可以看到很多的键值对的形式“=”左右两边分别为环境变量的键和值的形式显示。


目前呢我们当前是普通用户,我们可以看到目前USER是这个,那么当我们切换用户为root之后:

那么我们的环境变量就被初始化成了root.
我们的系统中会存在大量的环境变量,每一个环境变量都有它自己的特殊用途, 用来完成特定的系统功能!
通过代码如何获取环境变量?
我们可以通过man getenv查看这个系统调用接口来获取环境变量

我们编写如下代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>int main()
{printf("PATH:%s\n",getenv("PATH")); return 0;
}
运行结果:

当然我们也可以把PATH改成其他想要获取的环境变量名称:
比如说改成USER
运行结果:

其实呢,系统会自动的给我们创建一张环境变量表的东西:

下面我们写一段这样的程序来打印我们的环境变量:

运行之后:

发现我们运行的结果与我们前面用env命令获取的结果基本上是一样的。
我们命令行启动的进程都是shell/bash的子进程,子进程的命令行参数和环境变量,是父进程bash给我们传递的!
子进程的环境变量是父进程传递的,那么父进程的环境变量又是从哪里来的呢?
我们前面说到更改环境变量问题,其实我们直接更改的是bash 进程内部的环境变量信息!而我们用户的每一次登录,都会给我们形成的新的bash解释器,并且新的bash 解释器会自动从某个配置文件自己的环境变量 表信息!
这里所说的配置文件就是

我们家目录下的一个隐藏文件 .bash_profile
我们可以用vim打开这个文件:

所以呢我们就可以知道环境变量信息是以脚本配置文件的形式存在的!
每一次登录的时候,我们的bash进程都会读取.bash_profile配置文件中的内容,为我们的bash进程形成一张环境变量表信息!
如何证明上述结论呢?
下面我们通过自己定义一些环境变量,例如:

我们定义一个环境变量名为:MYENV_109 值为:hellolinux
当我们echo $MYENV_109的时候是有内容的,可是当我们用env命令查看该环境变量是否能够添加到环境变量表当中运行之后发现并没有添加,我们把这样定义的环境变量叫做本地变量。

当我们打印的时候环境变量是有值的,而当我们用我们上面写的代码形成的可执行程序来运行获取环境变量时发现获取不到。
那么如何把我们自己定义的该环境变量导入到环境变量表当中呢?
我们通过export+环境变量名将我们的环境变量导入到环境变量表当中,那么我们的env命令和我们的可执行程序就都能获取该变量的了。

虽然这样可行了,但是当我们把xshell退出之后重新登录之后,获取我们刚刚导入的环境变量发现又不见了,原因就在于我们刚刚导入的环境变量仅仅只是在当前bash进程中修改的,根据我们上面的结论,bash进程在我们重新登录之后又会重新在我们的配置文件中取读取我们的环境变量,所以我们先前添加的环境变量会失效。

当我们重新登录后发现果然这个环境变量不见了,那么我们应该如何永久的导入一个环境变量呢?
那当然是通过在配置文件.bash_profile文件中添加shell脚本了,我们可以通过编辑该配置文件为如下:
修改前:

修改后:

我们添加了上述代码,然后保存退出,然后呢要想让该环境变量生效我们还需要重新登录让bash再重新读取一次该配置文件,然后登录成功之后:
我们查看一下这个配置文件的内容:

在执行上述语句发现已经生效了。

我们上面谈到,子进程的环境变量是由父进程进行传递的,那么我们父进程的环境变量就会一直被传递下去,所以以该父进程为根节点,所有由该父进程创建的子进程,再由子进程继续创建子进程的子进程都能够共享到该父进程的环境变量,所以我们说系统环境变量具有全局属性!!!
除了上述获取环境变量的方式其实还有一种方式可以获取到环境变量,我们c语言给我们提供了一个全局变量名字叫 environ
下面我们可以通过修改我们之前的代码实现:

运行结果:

可以发现我们刚刚添加再配置文件中的环境变量也被获取了。
所以我们就知道三种获取环境变量的方式了:
1. env命令
2.main函数传参
3.C语言提供的全局变量:environ
我们上面又谈到过一个本地变量,那么本地变量和我们的全局变量有什么区别呢?
本地变量vs环境变量
本地变量只在bash进程内部有效,不会被子进程继承下去。
环境变量通过让所有的子进程继承的方式,实现自身的全局性!

我们发现当我们创建本地变量的时候,我们可以通过echo命令将本地变量的值给打印出来,但是我们的命令也是进程啊,按照这样的逻辑来说的话,当我们执行echo命令的时候是通过bash来创建子进程运行的,但是我们上面又说本地变量只在bash进程内有效,不会被子进程继承下去,那你这不是在跟我扯嘛?
其实啊,这里要跟大家说一下,我们的Linux中命令是由分类的,诸如我们上面用到的echo命令,export命令都是内建命令,而需要创建子进程的命令是我们的常规命令:
Linux命令分类:
1.常规命令:shell fork让子进程执行的命令
2.内建命令,shell命令行的一个函数,不会创建子进程,当然可以直接读取shell的本地变量喽。
和环境变量相关的命令
1. echo: 显示某个环境变量值
2. export: 设置一个新的环境变量
3. env: 显示所有环境变量
4. unset: 清除环境变量
5. set: 显示本地定义的shell变量和环境变量
环境变量的组织方式

每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串。
相关文章:
Linux操作系统——进程(五)环境变量
环境变量 有了我们前面的命令行参数的理解基础呢,我们下面进入环境变量这一个部分的内容的学习。 一般在我们安装一些开发工具尤其是有解释器的开发工具的时候,我们呢一般都要配置环境变量,可能都不太清楚自己为什么要配置环境变量…...
西门子博途怎么使用PID_Compact做pid调试
到目前为止,我已经在S7-1200中创建了一个可运行的PLC程序,并在Basic Panel中创建了一个HMI项目来操纵和操作该程序。 引文:博途工控人平时在哪里技术交流博途工控人社群 现在,我们该如何深入的让程序开始逐渐智能化呢,…...
结构型模式 | 适配器模式
一、适配器模式 1、原理 适配器模式(Adapter),将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式主要分为三类:类适配器模式、对象适配器模式、接口…...
基于Python的车牌识别系统实现
本文将以基于Python的车牌识别系统实现为方向,介绍车牌识别技术的基本原理、常用算法和方法,并详细讲解如何利用Python语言实现一个完整的车牌识别系统。 精彩专栏持续更新推荐订阅,收藏关注不迷路 微信小程序实战开发专栏 目录 引言车牌识别…...
时间序列预测模型介绍及使用经验总结
1. 时序预测背景 时序数据,就是序列随时间变化的数据。时间序列分析,一般有时域和频域两种分析方法。时序预测的本质是在时域和频域层面探索时间序列变化的内在规律。 下图描述的是时域(temporal domain),横坐标是时…...
Docker知识总结
文章目录 Docker1 Docker简介1.1 什么是虚拟化1.2 什么是Docker1.3 容器与虚拟机比较1.4 Docker 组件1.4.1 Docker服务器与客户端1.4.2 Docker镜像与容器1.4.3 Registry(注册中心) 2 Docker安装与启动2.1 安装Docker2.2 设置ustc的镜像2.3 Docker的启动与…...
算法训练营Day25
#Java #回溯 开源学习资料 Feeling and experiences: 复原IP地址:力扣题目链接 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 . 分隔。 例如࿱…...
docker笔记2-docker 容器
docker 容器的运行 docker run 镜像名:版本标签: 创建 启动容器 docker run 镜像名 ,如果镜像不存在,则会在线下载镜像。 注意事项: 容器内的进程必须处于前台运行状态,不能后台(守护进程运行…...
redis 从0到1完整学习 (七):ZipList 数据结构
文章目录 1. 引言2. redis 源码下载3. zipList 数据结构3.1 整体3.2 entry 数据结构分析3.3 连锁更新 4. 参考 1. 引言 前情提要: 《redis 从0到1完整学习 (一):安装&初识 redis》 《redis 从0到1完整学习 (二&am…...
2015年第四届数学建模国际赛小美赛C题科学能解决恐怖主义吗解题全过程文档及程序
2015年第四届数学建模国际赛小美赛 C题 科学能解决恐怖主义吗 原题再现: 为什么人们转向恐怖主义,特别是自杀性恐怖主义?主要原因是什么?这通常是大问题和小问题的结合,或者是一些人所说的“推拉”因素。更大的问题包…...
基于Java开发的微信约拍小程序
一、系统架构 前端:vue | element-ui 后端:springboot | mybatis 环境:jdk8 | mysql8 | maven | mysql 二、代码及数据库 三、功能说明 01. 首页 02. 授权登录 03. 我的 04. 我的-编辑个人资料 05. 我的-我的联系方式 06. …...
蓝桥杯的学习规划
c语言基础: Python语言基础 学习路径:画框的要着重学习...
EMC噪声的本质
01 频谱的含义 频谱是将电磁波分解为正弦波分量,并按波长顺序排列的波谱,就是将具有复杂组成的东西分解(频谱分析仪)为单纯成分,并把这些成分按其特征量的大小依序排列(部分不计),…...
Redis遇到过的问题 (Could not get a resource from the pool )
生产上通过scan命令,查询一个大key耗时40s后,报 Could not get a resource from the pool,初步报错是连接池的连接数不够,从网上搜了一些解决方案。 排查过程: 一、首先需要先尝试连接redis,如果连接不上那…...
Spring Boot 3.2 新特性之 HTTP Interface
SpringBoot 3.2引入了新的 HTTP interface 用于http接口调用,采用了类似 openfeign 的风格。 具体的代码参照 示例项目 https://github.com/qihaiyan/springcamp/tree/master/spring-http-interface 一、概述 HTTP Interface 是一个类似于 openfeign 的同步接口调…...
Flask+Mysql项目docker-compose部署(Pythondocker-compose详细步骤)
一、前言 环境: Linux、docker、docker-compose、python(Flask)、Mysql 简介: 简单使用Flask框架写的查询Mysql数据接口,使用docker部署,shell脚本启动 优势: 采用docker方式部署更加便于维护,更加简单快…...
DDOS攻击简介——什么是DDOS
DDoS是什么? DDoS是分布式拒绝服务攻击(Distributed denial of service attack)的简称。 分布式拒绝服务器攻击(以下均称作DDoS)是一种可以使很多计算机(或服务器)在同一时间遭受攻击,使被攻击的目标无法正常使用的一种网络攻击方式。DDoS攻击在互联网上已经出现过…...
龙蜥开源操作系统能解决CentOS 停服造成的空缺吗?
龙蜥开源操作系统能解决CentOS 停服造成的空缺吗? 本文图片来源于龙蜥,仅做介绍时引用用途,版权归属龙蜥和相关设计人员。 一、《国产服务器操作系统发展报告(2023)》称操作系统已步入 2.0 时代,服务器操作…...
『Linux升级路』基础开发工具——gdb篇
🔥博客主页:小王又困了 📚系列专栏:Linux 🌟人之为学,不日近则日退 ❤️感谢大家点赞👍收藏⭐评论✍️ 目录 一、背景知识介绍 二、gdb指令介绍 一、背景知识介绍 在软件开发中,…...
边缘计算云边端全览—边缘计算系统设计与实践【文末送书-10】
文章目录 一.边缘计算1.1边缘计算的典型应用 二.边缘计算 VS 云计算三.边缘计算系统设计与实践【文末送书-10】3.1 粉丝福利:文末推荐与福利免费包邮送书! 一.边缘计算 边缘计算是指在靠近物或数据源头的一侧,采用网络、计算、存储、应用核心…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...
篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...
Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...
