【Linux】进程6——环境变量

news2024/7/6 17:43:01

1.什么是环境变量

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

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

windows里也有环境变量

 2.认识几个环境变量

2.1.PATH

  1. PATH : 指定命令的搜索路径

        为什么我们使用指令时不用加./,而我们使用自己编译的可执行程序就需要加./?

        这个是因为使用指令的时候,系统默认在/usr/bin/里去查找,那我们自己的可执行程序为什么没有这个待遇?
        原因在于linux会给指令搜索提供一个环境变量PATH

我们可以把它显示出来

查看环境变量指令:
echo $NAME //NAME:你的环境变量名称 

        上图是我Linux用户下的PATH变量,这些路径都由:进行分隔。

        当我们输入我平时的ls、pwd等等指令时直接就可以使用,就是因为他们都是在/user/bin目录下,操作系统可以自动寻找。

        但是我们运行一个陌生路径下的可执行程序时就得声明为当前路径下,这就是因为我们在PATH环境变量中没有定义此路径。操作系统不能自动寻找。

        我们可以将一个程序放到PATH有的路径下,或者将当前的绝对路径加入到PATH变量中去,我们就可以直接使用此指令。

        

        我们可以往PATH添加路径

        这样子这个目录下

面的所有可执行程序都能当成指令来运行了

实际上,我们刚刚修改的PATH环境变量是一种在内存中的环境变量,所以无需担心。

如果不小心改错了,只需关闭Xshell并重新登录即可。这个PATH环境变量是在shell中保存的。

然而,当shell尚未存在时,即在系统启动时,环境变量是从哪里来的呢?

        实际上,这些环境变量预先存储在我们系统的一些配置文件中。当系统启动时,它们会被加载到内存中。因此,现在你不必担心你的环境变量被错误修改,只需重新启动一下,我们的环境就会恢复

2.2.HOME

  1. HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)

        在我们平是登录xshell的时候普通用户就会直接进入自己的家目录/home/xxx而root用户会进入自己家目录/root ,那么系统是怎么知道我们的工作目录的呢?
       主要原因就是因为当我们在登录时,shell就会直接识别到当前登陆账户是谁,然后给当前用户填充$HOME环境变量,当我们登录时,此时默认就直接cd到了$HOME目录下。这就是我们每次登录之后都会处于自己对应的家目录的原因。

2.3.获取环境变量env&&getenv

bash中我们可以使用env命令来获取bash从系统中继承下来的所有环境变量

我们可以通过下面这个来查询其他环境变量

也可以使用getenv来获取某一个环境变量。 

#include <iostream>
#include <unistd.h>
using namespace std;
int main()
{
    cout<<"PATH="<<getenv("PATH")<<endl;
    return 0;  
}

2.4环境变量USER

  USER环境变量用来标识当前登录的用户。在终端中输入命令echo $USER,可以查看当前登录用户的用户名。这个环境变量是bash/shell在启动时自动加载的,它记录了当前登录的用户。
        我们再来写一段demo代码:

#include <iostream>
#include <unistd.h>
using namespace std;

int main()
{
    cout<<"USER="<<getenv("USER")<<endl;
    return 0;  
}

了解了上面内容,我们就可以模拟一下系统权限对普通用户和root用户的判定方式:

#include <iostream>
#include <unistd.h>
#include <cstring>
using namespace std;

int main()
{
    char who[32];
    strcpy(who,getenv("USER"));
    if(strcmp(who,"root")==0)
        cout<<"root用户不受条件约束"<<endl;
    else 
        cout<<"普通用户受权限约束"<<endl;
    cout<<"USER:"<<getenv("USER")<<endl;

    
    return 0;  
}

 

 因为有环境变量的存在,我们的系统就已经具备了能够认识你这个人是谁的能力,只要能认识你是谁,就可以和文件属性当中文件的拥有者所属组和文件所对的权限所对比,进而判定出你有没读写权限

3.命令行参数

我们C/C++中的main函数其实是可以传参的,这两个参数我们称之为命令行参数:

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

其中argv是一个指针数组,里面保存了字符串的地址,argc决定了argv中的元素个数,我们来尝试打印一下argv中的内容:

#include<stdio.h>
#include<unistd.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;
}

我们在命令行输入几个数后,打印出来就有几个。

3.1.命令行参数的作用

那命令行参数有什么用呢?看代码:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char* argv[])
{
	if (argc != 4)
	{
		printf("Usage: \n\t%s -[add|sub|mul|div] x y \n\n", argv[0]);
	}
	int x = atoi(argv[2]);
	int y = atoi(argv[3]);

	if (strcmp("-add", argv[1]) == 0)
	{
		printf("%d + %d = %d\n", x, y, x + y);
	}
	else if (strcmp("-sub", argv[1]) == 0)
	{
		printf("%d - %d = %d\n", x, y, x - y);
	}

	else if (strcmp("-mul", argv[1]) == 0)
	{
		printf("%d * %d = %d\n", x, y, x * y);
	}
	else
	{
		printf("%d / %d = %d\n", x, y, x / y);
	}
	return 0;
			
}

命令行参数可以通过输入不同的选项,来控制程序执行不同的功能代码。
命令行参数为指令,工具,软件等提供命令行选项的支持! 

命令行参数是Linux指令的基础,从上面的程序我们可以联想出我们在Linux中使用的指令后面跟的就是命令行参数:

我们使用的ls -al 、ll -al等等都是命令行参数。

我们使用的环境变量不是一两个而是一堆,并且彼此之间没有关系,一般是系统内置的具有特殊用途的变量。而定义变量的本质就是开辟空间,操作系统就是在运行中开辟空间的。

3.2.main函数的第三个参数

main函数除了上面那两个参数,还有一个叫做char *env[]的参数;

int main(int argc,char *argv[],char *env[])
{
	return 0;
}

 我们也可以来打印一下env中的内容:

#include <iostream>
#include <unistd.h>
#include <cstring>
using namespace std;
int main(int argc,char *argv[],char* env[])
{
	for(int i = 0;env[i];i++)
    {
        printf("env[%d]->%s\n",i,env[i]);
    }
	return 0;
}

还可以通过第三方变量environ获取

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

argv和env的结构一模一样,所以我们的C/C++代码一共会有两张核心向量表,一张叫做命令行参数表,一张叫做环境变量表。环境变量表会从父进程中继承下来。

我们所运行的进程,都是bash的子进程, bash本身在启动的时候,会从操作系统的配置文件中读取环境变量信息,子进程会继承父进程交给我的环境变量!

3.3.验证环境变量的继承

我们可以自己定义一个环境变量导入系统中的环境变量表当中,我们想要增加一个环境变量可以使用下面命令:

export MY_VALUE=666666666666

 

可以看到我们自己定义的环境变量已经被导入到环境变量表当中。
我们接下来再去执行我们刚刚的代码:

看到env[17]了嘛!!!可以发现它里面也有 MY_VALUE 这个环境变量,说明子进程test继承了父进程 bash 的环境变量。

删除一个环境变量可以使用unset 环境变量命令。

unset MY_VALUE

4..环境变量通常是具有全局属性的

环境变量通常具有全局属性,可以被子进程继承下去

#include <stdio.h>
#include <stdlib.h>
int main()
{
char * env = getenv("MYENV");
if(env){
printf("%s\n", env);
}
return 0;
}

 直接查看,发现没有结果,说明该环境变量根本不存在

导出环境变量
export MYENV="hello world"
再次运行程序,发现结果有了!说明:环境变量是可以被子进程继承下去的!

5.常规命令&&内建命令

我们再来看这个图中,我们定义了本地变量MY_VALUE,我们的可执行程序(bash的子进程)都读不到这个变量,为什么echo可以读取到呢

我们使用可执行程序myproc去读取我们的本地变量

 其实我们命令行上执行的指令不一定都要创建子进程,就好比王婆说媒一样,一些有任务特别难的或者风险的,王婆就会找别人去帮忙说媒。如果是一些很有把握的事情,那王婆还是愿意自己去做的。

由此可以推出我们指令是有区别的:

  • 常规命令:通过创建子进程完成的
  • 内建命令:bash不创建子进程,而是有自己亲自执行,类似于bash调用了自己写,或者系统提供的函数。

所以echo是一个内建命令,它是由bash自己执行的,与此同时我们的cd命令也是一个内建命令,我们可以通过调用chdir来改变当前工作目录。

#include <iostream>
#include <unistd.h>
#include <cstring>
using namespace std;
int main(int argc,char *argv[])
{
    sleep(30);
    printf("change begin\n");
    if(argc==2)
    {
        chdir(argv[1]);
    }
    printf("change end\n");
    sleep(30);
    return 0;
}

在命令行中输入 cd 命令的时候,bash 并不会创建子进程,而是去判断命令行参数是否为 cd,如果是就直接去调用 chdir 系统接口来切换bash的工作目录 

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

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

相关文章

TalkingData 是一家专注于提供数据统计和分析解决方案的独立第三方数据智能服务平台

TalkingData 是一家专注于提供数据统计和分析解决方案的独立第三方数据智能服务平台。通过搜索结果&#xff0c;我们可以了解到 TalkingData 的一些关键特性和市场情况&#xff0c;并将其与同类型产品进行比较。 TalkingData 产品特性 数据统计与分析&#xff1a;提供专业的数…

Pulsar 社区周报 | No.2024-06-07 | Apache Pulsar 新分支 3.3 版本发布

“ 各位热爱 Pulsar 的小伙伴们&#xff0c;Pulsar 社区周报更新啦&#xff01;这里将记录 Pulsar 社区每周的重要更新&#xff0c;每周发布。 ” 本期主题&#xff1a;Apache Pulsar 新分支 3.3 版本发布 Apache Pulsar 新分支 3.3 版本发布&#xff1a;Apache Pulsar 3.3.0[1…

野花野草80种 ,依然是农村小时候的印象

【野花野草】 小时候&#xff0c;不论在山上、在田里、还是在路边&#xff0c;总能看到各种各样的小花小草&#xff0c;或外表相似&#xff0c;或独具特色&#xff0c;而它们的名字似乎总是一个谜。今天我们就盘点一下这些叫不出名字的植物吧&#xff0c;或许&#xff0c;还能…

USB (3)

USB 流控 USB是polled bus,这和PCIe不一样,所有的transfer都是由host发起的。 对于IN(从device到host)。 如果device没有数据,那么只能回复NAK。 Token received corrupted

MySQL之查询性能优化(八)

查询性能优化 MySQL查询优化器的局限性 MySQL的万能"嵌套循环"并不是对每种查询都是最优的。不过还好&#xff0c;MySQL查询优化器只对少部分查询不适用&#xff0c;而且我们往往可以通过改写查询让MySQL高效地完成工作。还有一个好消息&#xff0c;MySQL5.6版本正…

GEE训练教程——如何确定几何形状的中心点坐标和相交的坐标

简介 在GEE中&#xff0c;可以使用.geometry()方法来获取几何形状的中心点坐标和相交的坐标。 首先&#xff0c;使用.geometry()方法获取几何形状的几何信息&#xff0c;然后使用.centroid()方法获取几何形状的中心点坐标。示例代码如下&#xff1a; // 获取几何形状的中心点…

ChatGP和kimi对比

使用关于歌手李健的一些问答&#xff0c;进行对比。整体感觉CharGPT更严谨。 ChatGPT kimi [ { “role”: “system”, “content”: “你是 Kimi&#xff0c;由 Moonshot AI 提供的人工智能助手&#xff0c;你更擅长中文和英文的对话。你会为用户提供安全&#xff0c;有帮助…

深度学习与人工智能

深度学习&#xff0c;是一种特殊的人工智能&#xff0c;他与人工智能及机器学习的关系如下&#xff1a; 近些年来&#xff0c;基于人工神经网络的机器学习算法日益盛行起来&#xff0c;逐渐呈现出取代其他机器学习算法的态势&#xff0c;这主要的原因是因为人工神经网络中有一中…

【面试干货】 B 树与 B+ 树的区别

【面试干货】 B 树与 B 树的区别 1、B 树2、 B 树3、 区别与优缺点比较4、 总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在数据库系统中&#xff0c;B 树和 B 树是常见的索引结构&#xff0c;它们在存储和组织数据方面有着不同的设计…

Nginx之正向代理配置示例和说明

一、NGINX正向代理功能简介 Nginx的正向代理功能允许局域网中的客户端通过代理服务器访问Internet资源。具体来说&#xff0c;Nginx作为一种流行的Web服务器和反向代理服务器&#xff0c;在正向代理方面的应用也相当实用。以下是其正向代理功能的几个关键点&#xff1a; 访问外…

【Linux】匿名管道的应用场景 --- 进程池

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

Makefile:从零开始入门Makefile

目录 1.前言 2.Makefile的简单介绍 3.Makefile中的指令规则 4.Makefile的执行流程 5.Makefile中的变量类型 6.Makefile中的模式匹配 7.Makefile中的函数 8.Makefile补充知识 前言 在Linux中编译CPP文件&#xff0c;我们能够使用GCC命令进行编译&#xff0c;但当项目文件多且繁杂…

OpenGauss数据库-5.数据更新

第1关&#xff1a;插入数据 gsql -d postgres -U gaussdb -W "passwd123123" create table student (id integer primary key,name char(20),age integer ); insert into student values(1,"lily",20),(2,lily,21),(3,marry,19); 第2关&#xff1a;删除数…

C51学习归纳9 --- I2C通讯学习(重点)

首先&#xff0c;我自己学习过以后的直观感觉&#xff0c;通信协议是单片机的灵魂之一&#xff0c;只有规定好了通信协议我们才能够正确的接收到信息&#xff0c;才能实现更加深入的研究。所以这一部分是需要好好学习的。 本节借助一个可存储的芯片AT24C02&#xff0c;进行在I2…

仿饿了么的谁去拿外卖游戏源码

源码介绍 喝酒 没有游戏玩&#xff1f; 懒得下床 不想出去 那么好 这个游戏会 满足你! 玩法 每人都选择一个序号 4 个人为例 张三选第 ① 李四选第 ② 王五选第 ③ 赵前选第 ④ 然后就按 4 下 其中最小的数对应的序号就是他输了就去拿外卖&#xff01; 源码下载 仿饿了么…

快速开始一个go程序(极简-快速入门)

一、 实验介绍 1.1 实验简介 为了能更高效地使用语言进行编码&#xff0c;Go 语言有自己的哲学和编程习惯。Go 语言的设计者们从编程效率出发设计了这门语言&#xff0c;但又不会丢掉访问底层程序结构的能力。设计者们通过一组最少的关键字、内置的方法和语法&#xff0c;最终…

IDEA创建SpringBoot项目的时候,如何使用Java8,怎么办?

在创建springboot项目的时候,IDEA提示&#xff0c;最低Java版本要求17&#xff0c;但是实际上我们可能不需要这么高的版本&#xff0c;怎么使用Java8呢&#xff1f; 解决办法 修改Server URL地址即可&#xff1a;https://start.aliyun.com

【PHP【实战训练】系统性学习】——最经典的web端头像上传,数据库内容安全精简

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

SpringBoot个人网盘系统-计算机毕业设计源码92922

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势或改善自身的缺点&#xff0c;互联网的发展文件管理带来了福音。个人网盘系统是以实际运用为开发背景&#xff0c;运用软件工程原理和…

算法——Floyd判圈算法

介绍 Floyd判圈算法用于判断一个链表中是否有环。 思想 使用快慢指针fast, slow&#xff0c;快指针每次走两步fast fast.next.next&#xff0c;慢指针每次走一步slow slow.next。当出现fast null || fast.next null时&#xff0c;说明链表不存在环&#xff0c;如果存在环…