环境变量【Linux】

news2025/1/16 2:45:35

在这里插入图片描述

文章目录:

  • Linux环境变量介绍
  • 常用的环境变量
  • 如何查看环境变量
  • 命令搜索路径PATH
  • 与环境变量相关的命令
  • 环境变量的组织方式
  • 通过代码的方式获取环境变量
  • 通过系统调用获取或设置环境变量
  • 环境变量的全局属性(继承)

Linux环境变量介绍

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

在 Linux 系统中,环境变量可以设置为用于执行 shell、bash 或 任何应用的全局变量或本地变量。即 Linux 环境变量只是一个名称,并且相同的名称包含一些值或路径。

例如:我们编写的 c/c++ 代码在链接的时候,是不知道所链接的动态静态库在哪里的,但是照样可以链接成功,生成可执行程序,因为相关的环境变量会帮助编译器进行查找。

环境变量通常具有某些特殊的用途,在系统中通常具有全局属性。

常用的环境变量

  • USER:显示当前用户的名称
  • PATH:指定命令的搜索路径
  • HOME:指定用户的主工作目录(即用户登录到 Linux 系统时,默认的目录)
  • SHELL:给出当前用户 shell 程序的位置,它的值通常是 /bin/bash
  • HOSTNAME:主机名
  • UID:显示当前用户的 ID
  • LANG:给出默认的系统语言

如下所示:

在这里插入图片描述

如何查看环境变量

可以通过 echo命令 来查看环境变量:

echo $NAME   // NAME代表需要查看的变量的名称

在这里插入图片描述

命令搜索路径PATH

❓这里有一个问题?在 Linux 下,为什么执行我们自己的可执行程序需要在前面加上 ./ ,而执行系统中的相关指令(如:ls、pwd等)就不用呢?

在这里插入图片描述
需要执行一个可执行程序,首先要找到该程序在哪里。系统能够执行 ls、pwd等 指令,说明操作系统能够找到这些命令的路径,而我们自己程序的路径,系统是不知道的,因此,我们需要加上 ./ 来告诉操作系统该可执行程序在当前目录下。

那么系统是怎么知道 ls 等指令的路径的呢?操作系统通过环境变量 PATH 来查找 ls 等指令的路径,我们可以查看环境变量 PATH 的内容,如下所示:
在这里插入图片描述

PATH 中存在很多的路径,每个路径由冒号分开。当在命令行中输入指令后,系统会在环境变量 PATH 中依次查看每个路径下是否有这个指令,若有便直接运行,否则报错(command not found)。

❓我们自己的程序是否能够不带路径直接执行呢?如何解决这个问题?

方法一:将我们的可执行程序拷贝到环境变量 PATH 的其中一个路径中

sudo cp 可执行程序名称 环境变量PATH中的其中一个路径

在这里插入图片描述
一般情况下,不推荐此方法。

在这里插入图片描述

方法二:将该可执行程序所在的路径添加到环境变量 PATH 中

export PATH=$PATH:当前可执行程序的路径

在这里插入图片描述

与环境变量相关的命令

环境变量是系统级别上可用的变量。相同的变量将用于 shell 或 应用程序作业。我们可以在 Linux 中使用环境变量,如:echo、export、env、unset、set等。

echo:显示某个环境变量的值

在这里插入图片描述

export:用于设置一个新的环境变量。这个变量是临时的,如果会话退出或关闭,那么这个变量的作用域将会消失。

在这里插入图片描述

env:使用不带参的 env 命令时,它会打印系统中所有的环境变量。

在这里插入图片描述

set :set 命令用于设置 Linux 的环境变量。当不带参数的使用 set 命令时,他将显示本地定义的 shell 变量和环境变量。
unset:清除环境变量。

在这里插入图片描述

环境变量的组织方式

在这里插入图片描述
以上是 Linux 中,环境变量的组织方式。每个程序都会有一张环境表,环境表是一个字符指针数组,每个指针指向一个以 ‘\0’ 结尾的环境字符串。

通过代码的方式获取环境变量

通过 main 函数的第三个参数获取

❓在这里,我们思考一个问题。main 函数可以带参数吗?最多能带几个参数?
main 函数是可以带三个参数的,在一般情况下,我们都没有用到。

首先,来看看 main 函数的前两个参数。

在 Linux 下,通过以下代码,测试 main 函数参数的作用及意义。

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

代码运行结果如下:

在这里插入图片描述
通过以上代码和运行结果可以看出,同一个程序,通过传递不同的参数,让同一个程序有不同的执行逻辑和执行结果。main 函数的第二个参数是一个字符指针数组,指针数组中的第一个字符指针存储的是可执行程序的地址,其余指针指向命令行中所给出的选项(每个选项以空格分开),最后以一个空指针结尾。main 函数的第一个参数 argc 代表字符指针数组中的有效元素个数。

✨理解 main 函数中两个参数的意义之后,下面尝试实现一个简单的命令行版 + -*/ 的计算器,加深对 main 函数参数的理解及应用:

要求:在命令行中输入 可执行程序 -选项 number1 number2
例如:./process -a 5 7,则运行程序后输出 5 + 7 = 12

// 写一个命令行版简易计算器
// ./process -a 10 20
// 10 + 20 = 30
// ./process -s 10 20
// 10 - 20 = -10
    
int main(int argc,char *argv[])
{
    // 判断指令是否输入正确,若输入不正确,则提示规则
    if(argc != 4)
    {
        printf("Usage:%s [-a][-s][-m][-d] num1 num2\n",argv[0]);
        return 0;
    }

    // 将输入的数据转换为整形
    int x=atoi(argv[2]);
    int y=atoi(argv[3]);

    if(strcmp("-a",argv[1])==0)
    {
        printf("%d + %d = %d\n",x,y,x+y);
    }
    else if(strcmp("-s",argv[1])==0)
    {
        printf("%d - %d = %d\n",x,y,x-y);
    }
    else if(strcmp("-m",argv[1])==0)
    {
        printf("%d * %d = %d\n",x,y,x*y);
    }
    else if(strcmp("-d",argv[1])==0)
    {
        if(y==0)
            printf("除0错误!\n");
        else 
            printf("%d / %d = %d\n",x,y,x/y);
    }
    else 
    {
        printf("Usage:%s [-a][-s][-m][-d] num1 num2\n",argv[0]);
    }
    return 0;
}

代码测试如下:

在这里插入图片描述

🧨通过上述的验证测试,我们了解了 main 函数前两个参数是干什么的。而 main 函数最多可以有三个参数,那么第三个参数是什么呢?存在的意义是什么?

main 函数的第三个参数实际上是一个环境变量列表,可以通过 main 函数的第三个参数来获取系统中的环境变量。所以,我们可以使用以下代码获取系统的环境变量:

int main(int argc,char *argv[],char *env[])
{
    // env字符指针数组中,最后一个指针为空
    for(int i=0;env[i];++i)
    {
        printf("env[%d]:%s\n",i,env[i]);
    }
    return 0;
}

通过第三方变量 environ 获取

Linux 中 environ 变量是一个 char** 类型,存储着系统的环境变量。

可以使用以下代码来遍历环境变量:

#include<stdio.h>

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

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

注意:libc 中定义的全局变量 environ 指向环境变量表,environ 没有包含在任何头文件中,所以使用时需要加上 extern 进行声明。

通过系统调用获取或设置环境变量

🎈 常用 getenv 和 putenv 函数来访问特定的环境变量。

C语言 getenv() 函数:获取环境变量

头文件:

#include<stdlib.h>

定义函数:

char *getenv(const char *name);

函数描述: getenv() 函数搜索环境变量列表以查找环境变量名,并返回指向相应字符串的指针。环境变量的格式为 name=value。

返回值: getenv() 函数返回一个指向环境中值的指针,找不到则返回 NULL。

示例:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 
  4 
  5 int main()
  6 {
  7     printf("%s\n",getenv("PATH"));                                                                                                                       
  8     return 0;
  9 }    

运行结果:

在这里插入图片描述

C语言 putenv() 函数:改变或增加环境变量

头文件:

#include<stdlib.h>

定义函数:

int putenv(const char *string);

函数描述: putenv() 函数的作用是增加或改变环境变量的值。参数字符串的形式是 name=value 。如果 name 在环境中不存在,则增加 name=value 到环境中。如果 name 存在,则环境中 name 的值被改为 value。由 string 指向的字符串成为环境的一部分,因此改变字符串将改变环境。

返回值: putenv() 函数成功时返回0,发生错误时返回非零。如果发生错误,则设置 errno 以指示原因。

错误: ENOMEM 分配新环境的空间不足。

示例:

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

int main()
{
    char *p;
    if((p = getenv("USER")))
        printf("USER = %s\n",p);
    
    putenv("USER=test");
    printf("USER+5s\n",getenv("USER"));
    return 0;
}

运行结果:
在这里插入图片描述

环境变量的全局属性(继承)

  • 环境变量通常具有全局属性,可以被子进程继承。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    char *env = getenv("MYVAL");

    pid_t id = fork();
    if(id == 0)
    {
        printf("%s\n",getenv("MYVAL"));
    }
    return 0;
}

运行结果:

在这里插入图片描述

如上所示,当导入环境变量后。fork() 创建的子进程依旧可以获取该环境变量的值,说明环境变量具有全局属性,被子进程继承了。

继承:当父进程创建子进程时,子进程继承父进程拥有的所有环境变量和值。


我们对环境变量进行了初步的了解。环境变量对于在 Linux 环境中导出路径或设置特定值非常重要。它将为第三方软件或应用程序导入,以访问 Linux 环境并执行作业。

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

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

相关文章

【王道数据结构】第五章(下) | 树 | 二叉树

目录 一、树的存储结构 1、双亲表示法(顺序存储)&#xff1a; 2、孩子表示法(顺序链式) 3、孩子兄弟表示法(链式存储&#xff09; 二、树、森林的遍历 1、树的先根遍历 2、树的后根遍历 3、层序遍历&#xff08;队列实现&#xff09; 4、森林的遍历 三、二叉排序树 …

电子技术——IC偏置-电流源、电流镜、电流舵

电子技术——IC偏置-电流源、电流镜、电流舵 IC偏置设计基于恒流源技术。在IC中的一个特定的区域&#xff0c;会生成一个精确的DC电流&#xff0c;这称为 参考电流 &#xff0c;之后通过电流镜复制到各个所需支路&#xff0c;并且通过电流舵进行电流转向。这项技术为IC的多级放…

知识图谱实战(01):从0-1搭建图片服务器

作者&#xff1a;艾文编程职业&#xff1a;程序员&#xff0c;BAT大厂资深工程师摘要&#xff1a;搜索/推荐场景下给用户展示大量的图片信息&#xff0c;那么这些数据是通过专门的图片服务器来访问的。 我们在基于知识图谱的智能搜索系统中&#xff0c;对搜索出来的每条记录都有…

支付系统核心架构设计思路(万能通用)

文章目录1. 支付系统总览核心系统交互业务图谱2. 核心系统解析交易核心交易核心基础交易类型抽象多表聚合 & 订单关联支付核心支付核心总览支付行为编排异常处理渠道网关资金核算3. 服务治理平台统一上下文数据一致性治理CAS校验幂等 & 异常补偿对账准实时对账DB拆分异…

fpga图像处理(sobel算子)

【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 关于sobel算子,前面已经讲过计算方法了。一种是上下的sobel算子,一种是左右的sobel算子,两者都相当于prewitt算子的进一步拓展。当然,之前的实现方法都是基于python和opencv实现…

【Leetcode】面试题 16.05. 阶乘尾数、HJ7 取近似值

作者&#xff1a;小卢 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 面试题 16.05. 阶乘尾数 HJ7 取近似值 面试题 16.05. 阶乘尾数 面试题 16.05. 阶乘尾数 …

这才是计算机科学_计算机大量应用

文章目录一、编译原理1.1 早期编译方式1.2 编程语言二、算法&数据结构2.1 Sort2.2 图搜索2.3 Array2.4 Node三、软件工程起源2.1分解打包三 、摩尔定律3.1 发展历3.1.1 电子管3.1.2 晶体管3.1.3 集成电路 IC3.2 刻蚀工艺3.2.2 光刻负责电路一、编译原理 之前讲的例子中 &am…

46 理论计算机科学基础-北京大学

P10 课程介绍05:46P21-1 预备知识07:43P31-2 确定型有穷自动机例子11:23P41-3 确定型有穷自动机的形式化定义17:51P51-4 设计确定型有穷自动机05:57P61-5 正则运算与封闭性28:16P71-6 非确定型有穷自动机37:43P81-7 DFA与NFA的等价性17:41P91-8 正则语言的封闭性10:30P102-1 正…

第九章(13):STL之常用排序算法

文章目录前情回顾常用排序算法sortrandom_shufflemergereverse下一座石碑&#x1f389;welcome&#x1f389; ✒️博主介绍&#xff1a;一名大一的智能制造专业学生&#xff0c;在学习C/C的路上会越走越远&#xff0c;后面不定期更新有关C/C语法&#xff0c;数据结构&#xff0…

Java 面向对象三大特性之三——接口(面试、学习、工作必备技能)

目录 一、接口概述(interface) 二、接口的成员 三、继承和实现 四、单继承和多实现 五、接口的优点 六、接口与抽象类 七、接口的思想 八、接口案例——运动员 ​​​​​​​ 接口概述(interface) 定义&#xff1a;是抽象方法和常量值的集合。 本质&#xff1a;从…

【C++修行之路】类和对象

面向对象编程详解目录前言面向对象和面向过程类和结构体构造函数和析构函数拷贝构造和赋值重载结语前言 好久不见&#xff0c;首先祝大家元宵节快乐&#xff0c;万家元夕宴&#xff0c;一路太平歌&#xff0c;今天执此佳节&#xff0c;一起来学习一下类和对象吧~ 面向对象和面…

系列分享 |《最强的 VLC 多媒体开发教程》

作者&#xff1a; 一去、二三里 个人微信号&#xff1a; iwaleon 微信公众号&#xff1a; 高效程序员 专栏介绍 《VLC 多媒体开发》&#xff0c;是一个专注于 libVLC 开发的专栏&#xff0c;里面共包含几十个章节&#xff0c;从 0 到 1&#xff0c;图文并茂&#xff0c;详细地…

【Linux】冯诺依曼体系与操作系统(OS)概念

文章目录冯诺依曼体系结构为什么是这样的结构局部性原理操作系统(Operator System)设计OS的目的定位如何理解管理 (精髓:先描述再组织)总结系统调用和库函数概念冯诺依曼体系结构 我们常见的计算机,如笔记本.我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系 为什么是这…

C++深入浅出(八)—— 继承

文章目录1. 继承的概念及定义&#x1f351; 继承的概念&#x1f351; 继承的定义&#x1f345; 定义格式&#x1f345; 继承关系和访问限定符&#x1f345; 继承基类成员访问方式的变化2. 基类和派生类对象赋值转换3. 继承中的作用域4. 派生类的默认成员函数5. 继承与友元6. 继…

jsp 校园网系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp 校园网系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统采用web模式开发&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数…

C#,入门教程(39)——C#语言的概念与知识点摘要

本文归纳整理C#的一些知识点&#xff0c;便于快速浏览与掌握C#语言的一些基本概念。本文并没有很好地层次与组织&#xff0c;抄了不少&#xff0c;写了不少&#xff0c;想到什么&#xff0c;就写什么。01 类 class类是C#等面向对象编程语言&#xff08;Object-oriented program…

常用API、Lambda、常见算法

目录 日期与时间 Date SimpleDateFormat Calendar JDK8新增日期类 概述、LocalTime/LocalDate/LocalDateTime Instant DateTimeFormatter Duration/Period ChronoUnit 包装类 包装类练习 正则表达式 正则表达式概述、初体验 正则表达式的匹配规则 正则表达式的…

Zookeeper注册中心

zookeeper的使用场景 分布式协调、分布式锁、元数据/配置信息管理、HA高可用性 分布式协调 A系统发送个请求到mq,然后B系统消息消费之后处理了,那A系统如何知道B系统的处理结果?A系统发送请求之后在zookeeper上对某个节点的值注册个监听器,一旦B系统处理完了就修改zooke…

C语言高级教程-C语言数组(七):数组综合实例之井字棋游戏问题

C语言高级教程-C语言数组&#xff08;七&#xff09;&#xff1a;数组综合实例之井字棋游戏问题一、本文的编译环境二、井字棋游戏的问题三、井字棋游戏的分析四、井字棋游戏的程序编写步骤4.1、添加主要的游戏循环和显示这个方格4.2、让玩家选择-一个方格&#xff0c; 并确定那…

Android 设置可抓包

在ren目录下新建xml文件夹&#xff0c;在xml下新建network_security_config.xml<?xml version"1.0" encoding"utf-8"?><!--<network-security-config>--><!-- <base-config cleartextTrafficPermitted"true" />--&…