【Linux学习】深入理解Linux环境变量与本地变量

文章目录

  • 环境变量的引入
  • 环境变量
    • 环境变量概念
    • 环境变量的特性以及命令行操作
    • 本地变量

环境变量的引入

main参数(命令行参数)
先来看看这样的代码以及运行结果:

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

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

原理:
在Linux中," [root@iZ2vcb2izu72dt7ghpv46fZ Test]# " 这个字符串是bash进程输出的,后面我们跟的 字符串 ./myprocess a b c d (结合上图)相当于我们在做输入, 如下图代码所示,bash首先输出一个字符串,然后等着用户做输入,将输入的 ./myprocess a b c d 这个长的字符串放入到buffer里面,输入过后被命令行解释器bash读取到了,命令行解释器会帮我们做一件工作,将这个大字符串以空格为分隔,将大字符串分隔开,放到一个char* 类型的数组,这里叫做char* argv[ ] (如下图),bash除了会维护一个char*数组,还会维护一个int类型的数据,记录该数组里面的字符串个数,这里用int argc表示;这样,就可以拿到了命令行输入的5个参数(字符串) 了;

printf("[root@iZ2vcb2izu72dt7ghpv46fZ Test]#");
char buffer[1024];
scanf("%s",buffer);   //fgets();

在这里插入图片描述
总结:
在命令行上输入的以空格作为分割符的字符串,会被bash解析成对应的一个一个的小子串,然后维护成一个指针数组,再通过一定的方式,将参数传下去;

为什么要这么做呢?
我们可以通过不同的选项,让我们的同一个程序执行它内部不同的功能。就比如Linux向命令行解释器输入不同的指令,例如ls -a ls -l等等。
命令行参数是命令行选项的基础。
看一个demo代码进行解释:

     #include<stdio.h>
     #include<stdlib.h>
     #include<unistd.h>
     //实现一个版本控制  实现三个版本  输入可执行程序+版本号
     int main(int argc,char *argv[])
     {
       if(argc!=2)  //如果参数不是两个
       {
         printf("Usage\n\t%s -number[1-3]\n",argv[0]);//提示输入
        return 1;
      }
      if(strcmp("-1",argv[1])==0) //版本一
      {
        printf("function 1\n");
      }
      else if(strcmp("-2",argv[1])==0)//版本二
      {
        printf("function 2\n");
      }
      else if(strcmp("-3",argv[1])==0)   //版本三                               
      {
        printf("function 3\n");
      }
      else{
        printf("Unkown\n");
      }
       return 0;
      }

运行结果:
在这里插入图片描述
基于上面的代码实现一个命令行计算器:

     #include<stdio.h>
     #include<stdlib.h>
     #include<unistd.h> 
     
     // ./myprocess -[ADD|Mul|Sub|Div]  x  y
     int main(int argc,char *argv[])
     {
       if(argc!=4){
         printf("Usage\n\t%s -[Add|Mul|Sub|Div] x y\n",argv[0]);
        return 1;
      }
      int x = atoi(argv[2]);
      int y = atoi(argv[3]);
      if(strcmp("-Add",argv[1])==0)
      {
        printf("%d\n",x+y);
      }
      else if(strcmp("-Mul",argv[1])==0)
      {
        printf("%d\n",x*y);
     }
      else if(strcmp("-Sub",argv[1])==0)
      {                                                                 
        printf("%d\n",x-y);
      }
      else if(strcmp("-Div",argv[1])==0)
      {
        if(y==0)
          printf("除0错误\n");
        else
          printf("%d\n",x/y);
      }
      else{
        printf("Unkown\n");
      }
      return 0;
    }

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

环境变量

环境变量概念

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

思考为什么我们要运行我们所写的可执行程序的时候需要带./ ?而在执行系统指令的时候却不需要./ ?
因为在系统当中存在一个全局的环境变量,名字叫PATH。可以echo $PATH查看环境该环境变量(如下图):
在这里插入图片描述

  • 在我们的系统里面,有一块内存空间,里面保存了一个字符串(就是对应上图的路径),名字叫PATH,然后我们在执行任何命令的时候,都会在这个路径下展开搜索,这个路径时由很多个子路径构成,冒号分隔,其中系统命令都在这个路径中的某个子路径下面,而我们所写的程序没有在上面字符串中,所以不加./系统找不到该二进制可执行程序,所以需要./告诉系统在当前路径。

如果想要自己写的程序不带./就能运行。

  • 第一种方法:将我们的可执行程序拷贝到上面的目录里面
    在这里插入图片描述
  • 第二种方法:可以将该二进制程序文件路径加上去
    指令:
# PATH=路径:$PATH   //路径是你要加的路径

注意:当shell退出后,会自动将这个路径从PATH中移除。
在这里插入图片描述

查看系统中的所有环境变量,env+回车:

示例:
在这里插入图片描述

思考:为什么在使用操作系统的时候,操作系统一直认识你?

因为当启动xshell的时候,已经把你这个用户在登录时所需要维护的相关数据暂时都给你保存起来了,当需要访问时,系统想要知道你是谁,用户名等信息可以通过环境变量去找,在每一次登录系统都会在内存中开一个空间,将你这个用户的环境变量存储起来。

环境变量的特性以及命令行操作

  • 查看环境变量
# env

在这里插入图片描述

  • 查看单个环境变量
# echo $PATH
  • 定义一个环境变量
# export NAME=XXJ  //export后面+需要定义的环境变量

在这里插入图片描述

  • 获取环境变量
    上面我们看到了main函数可以又两个参数,其实main函数最多可以有三个参数,第三个参数也是一个char*的数组,也是以NULL结尾的,

测试代码:

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

运行结果:根据运行结果可以看出:env里面存储的是指向环境变量的指针。
在这里插入图片描述

  • bash进程会维护两张表,一张是命令行参数那张表(char* argv[]),另一张为环境变量(char* env[]),当bash在调用main函数的时候,会将下面表的起始地址传给main函数的第三个参数,这时对应的进程也就拿到了父进程的环境变量。所以得出结论:环境变量默认是被子进程继承下去的。
    在这里插入图片描述

测试代码:

     #include<stdio.h>
     #include<stdlib.h>
     #include<unistd.h>
     #include<sys/types.h>
     
     int main(int argc,char* argv[],char* env[])                                                                                                                       
     {
       printf("-----------------------------------------------\n");
       printf("i am father  pid:%d  ppid:%d\n",getpid(),getppid());
      for(int i = 0;env[i];i++)
      {
        printf("env[%d]:%s\n",i,env[i]);
      }
      pid_t id = fork();
      if(id==0)
      {
        printf("-----------------------------------------------\n");
        printf("i am child  pid:%d  ppid:%d\n",getpid(),getppid());
        for(int i = 0;env[i];i++)
        {
          printf("env[%d]:%s\n",i,env[i]);
        }
      }
      sleep(1);
      return 0;
    
    }

运行结果:

  1. 环境变量具有全局属性。
  2. 环境变量会被子进程,包括孙子进程所继承。

在这里插入图片描述

如果不写参数,怎么获取环境变量呢,也就是不用继承的方式,怎么获取环境变量?

函数getenv获取函数变量里面的内容(根据环境变量的名字)
用法:getenv(环境变量名)
如下图:
在这里插入图片描述
测试代码:

   int main()
   {
     char* username = getenv("USER");
     if(username!=NULL)
      printf("username:%s\n",username);
     else
      printf("None\n");
                                                                                                                                                                      
     return 0;
    }

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

     #include<stdio.h>
     #include<stdlib.h>
     #include<unistd.h>
     #include<sys/types.h>
     
     
     
     int main()
     {
      	char* username = getenv("USER");
    
      	if(strcmp("root",username)==0)                                            
      	{
       	 	printf("this is my process core function\n");
      	}
      	else{
        	printf("you don't have authotity\n");
      	}
    
      	return 0;
     }

运行结果:可以写身份识别的代码,只有特定身份才能执行对应的代码,其他身份不能执行。
在这里插入图片描述

通过environ获取环境变量

environ是一个二级指针,指向的就是环境变量的那张表(char* env[ ])。
在这里插入图片描述
测试代码:

   #include<stdio.h>
   #include<stdlib.h>
   #include<unistd.h>
   #include<sys/types.h>
   
   
   
   int main()
   {
    	extern char** environ;
    	for(int i = 0;environ[i];i++)                                                                                                                                     
    	{
      		printf("environ[%d]:%s\n",i,environ[i]);
    	}
    	return 0;
  }

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

本地变量

当我们在命令行直接输入NAME=XXJ,我们就定义了一个本地变量;
变量名为NAME,变量的内容就是XXJ;

示例:
在这里插入图片描述

set命令

set命令可以把几乎所有的变量都显示出来,包含环境变量与本地变量。
在这里插入图片描述

注意:本地变量不是环境变量,本地变量只在bash进程有效,不能被继承。

示例:

测试代码:
提示:上面的测试过程中,NAME=XXJ是一个环境变量;

   #include<stdio.h>
   #include<stdlib.h>
   #include<unistd.h>
   #include<sys/types.h>
                                                                                                                                                                       
   int main()
   {
      const char* str = getenv("NAME");
      if(str==NULL)
      {
         printf("get None\n");
      }
      else{
         printf("%s\n",str);
      }
  
    return 0;
  }

运行结果分析:因为NAME=XXJ是环境变量,所以会被继承下去,所以str能拿到NAME的内容。

在这里插入图片描述

测试代码二:
提示:HELLO=LLLLLLLLLL是本地变量

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<sys/types.h>
  5 
  6 int main()
  7 {
  8   const char* str = getenv("HELLO");                                                                                                                                
  9   if(str==NULL)
 10     printf("get None\n");
 11   else{
 12     printf("%s\n",str);
 13   }
 14 
 15   return 0;
 16 }

运行结果分析:HELLO是一个本地变量,本地变量不会被继承,所以在子进程中获取不到。
在这里插入图片描述

注意:删除掉本地变量与环境变量unset指令

# unset 变量名

问题:bash的子进程的环境变量从bash继承的,那bash没有父进程,那它的环境变量在哪里拿的呢?

bash登陆后,环境变量都是内存级的,都是从磁盘文件读来的,当bash进程退出了,环境变量(进程中的)自然而然就没有了(磁盘的还在)。
每一个用户在登录是都有自己的一套环境变量,在家目录里面的一个.bash_profile文件中。(如图)
在这里插入图片描述

可以用这个配置欢迎语哦:
步骤:打开家目录下的.bash_profile文件,加一个字符串,如下图所示:
在这里插入图片描述
效果展示:
在这里插入图片描述


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据库】MySQL

文章目录 概述DDL数据库操作查询使用创建删除 表操作创建约束MySqL数据类型数值类型字符串类型日期类型 查询修改删除 DMLinsertupdatedelete DQL基本查询条件查询分组查询分组查询排序查询分页查询 多表设计一对多一对一多对多设计步骤 多表查询概述内连接外连接 子查询标量子…

【加密与解密(第四版)】第十七章笔记

第十八章 反跟踪技术 18.1 由BeginDebugged引发的蝴蝶效应 IsDebuggerPresent()函数读取当前进程PEB中的BeginDebugged标志 CheckRemoteDebuggerPresent() 反调试总结&#xff1a;https://bbs.kanxue.com/thread-225740.htm https://www.freebuf.com/articles/others-articl…

在生产试验铁地板有许多不足之处,是如何对不足来进行补救的?(北重厂家制造)

北重试验铁地板热处理&#xff1a;这个试验铁地板热处理的过程主要也分为三个步骤&#xff1a;正退火、退火、正火等&#xff0c;热处理主要的作用是为了改变铸件的原始组织&#xff0c;去掉铸件的内应力﹐使得产品的使用性能得到保证&#xff0c;以防铸件产生变形和破坏。 试验…

[数据结构1.0]计数排序

读者老爷好&#xff0c;本鼠鼠最近学了计数排序&#xff0c;浅浅介绍一下&#xff01; 目录 1.统计相同元素出现次数 2.根据统计的结果将序列回填到原来的序列中 3.相对映射计数排序 计数排序又称为鸽巢原理&#xff0c;是对哈希直接定址法的变形应用&#xff0c;是非比较排…

【MySQL】MySQL的安装和基本概念

MySQL的安装和基本概念 一、环境安装1、环境及配置2、下载安装 二、基本概念1、主流数据库2、mysql和mysqld的区别和概念&#xff08;1&#xff09;概念1&#xff1a;了解CS结构&#xff08;2&#xff09;概念2&#xff1a;数据库指的是什么&#xff08;3&#xff09;概念3&…

Vue——开发前的准备和创建一个vue的工程

文章目录 前言安装 Node js1、下载node.js2、安装node.js3、查看是否安装成功 创建 vue 工程Visual Studio Code 配置目录结构 前言 本篇博客主要讲解Vue开发前的环境配置与一些说明。 安装 Node js 环境需要安装配置一个nodejs 的环境。 vue3 最低nodejs 版本要求为 15.0 1…

Golang | Leetcode Golang题解之第107题二叉树的层序遍历II

题目&#xff1a; 题解&#xff1a; func levelOrderBottom(root *TreeNode) [][]int {levelOrder : [][]int{}if root nil {return levelOrder}queue : []*TreeNode{}queue append(queue, root)for len(queue) > 0 {level : []int{}size : len(queue)for i : 0; i < …

Springboot 开发 -- Thymeleaf页面嵌入帆软报表

一、后端代码 Slf4j Controller RequestMapping("/reprot") public class FineReportController {//帆软地址&#xff1a;finereport.urlhttp://localhost:8075/WebReport/ReportServer?reportletValue("${finereport.url}")private String finereportUr…

视频监控管理平台LntonCVS安防管理平台指挥交通应用方案

地铁作为城市交通的关键组成部分&#xff0c;承担着大量乘客流量&#xff0c;因此地铁视频监控系统的建设至关重要。这一系统不仅能够提升地铁运营的安全性&#xff0c;还能有效预防和处理突发事件&#xff0c;保障乘客的出行安全。 首先&#xff0c;地铁视频监控系统实现了对地…

vue3+ts实战

目录 一、ts语法练习 1.1、安装 1.2、语法 二、vue3ts 2.1、项目创建 2.1.1、项目创建(建议node版本在16.及以上) 2.1.2、下载路由、axios 2.1.3、引入element-plus 2.1.4、报错解决 (1)文件路径下有红色波浪 (2)组件名称下有红色波浪 (3)引入模块下有红色波浪 2.…

使用docker完整搭建前后端分离项目

1、docker的优势&#xff0c;为啥用docker 2、docker的核心概念 镜像【Image】- 只读模板 容器【Container】- 运行镜像的一个外壳&#xff0c;相当于一个独立的虚拟机 仓库【repository】- 镜像的管理工具&#xff0c;可公开&#xff0c;可私有&#xff1b;类似git仓库 3、c…

【字典树(前缀树) 位运算】1803. 统计异或值在范围内的数对有多少

本文涉及知识点 字典树&#xff08;前缀树&#xff09; 位运算 LeetCode1803. 统计异或值在范围内的数对有多少 给你一个整数数组 nums &#xff08;下标 从 0 开始 计数&#xff09;以及两个整数&#xff1a;low 和 high &#xff0c;请返回 漂亮数对 的数目。 漂亮数对 是…

勒索病毒的策略与建议

随着网络技术的快速发展&#xff0c;勒索病毒攻击成为全球范围内日益严重的网络安全威胁。勒索病毒通过加密用户文件或锁定系统来勒索赎金&#xff0c;给个人和企业带来了巨大的损失。因此&#xff0c;了解如何应对勒索病毒攻击至关重要。本文将概述一些有效的防范措施和应对策…

【01】GeoScene Enterprise(Linux)许可更新

如果在Linux环境下部署了GeoScene Enterprise基础环境&#xff0c;也就是部署了server、portal、datastore、web adaptor四大组件&#xff0c;当试用许可到期后&#xff0c;拿到新的许可想要更新许可&#xff0c;从而使得软件能够正常工作&#xff0c;下述步骤是更新GeoScene E…

pytorch-20 lstm实践

一、LSTM预测类型 数据类型&#xff1a;单变量、多变量与面板数据数据处理&#xff08;滑窗方式&#xff09;&#xff1a;单变量有seq2seq&#xff0c;seq2point&#xff1b;多变量&#xff1a;特征滑窗&#xff0c;带标签滑窗 1. 数据类型&#xff1a;单变量、多变量与面板数…

Windows安全应急--反隐身术

NO.1 dir命令 首先做个演示&#xff0c;把演示01这个文件夹隐藏起来&#xff0c; 在文件夹上是看不到了&#xff0c; 我们可以使用dir命令查看&#xff0c; NO.2 文件夹选项–显示隐藏 这个是非常常规的了&#xff0c; 这里不做过多介绍 有些隐藏文件很顽固&#xff0c;上面…

第一周:参照与变迁

这是我于2020年10月参加的一个为期10周的管理课程培训的作业集。当时要求每周都需提交一篇课后作业。现在打算重温并整理这些作业&#xff0c;以验证自己在这几年间是否真正有所长进。 事物一旦向相反方向发生改变&#xff0c;那么会相对程度的改变&#xff0c;并且会下意识的以…

【机器学习与大模型】驱动下的电子商务应用

摘要&#xff1a; 随着信息技术的飞速发展&#xff0c;电子商务已经成为当今商业领域中最为活跃和重要的部分之一。而机器学习和大模型的出现&#xff0c;为电子商务带来了新的机遇和挑战。本文深入探讨了机器学习与大模型在电子商务中的应用&#xff0c;包括个性化推荐、精准营…

MyBatisPlus标准分页功能制作,以及设置分页拦截器,selectPage(new Page<>(current,size),null)

目录 1、设置分页拦截器 2、创建数据库及表 3、pom.xml 4、添加MP的相关配置信息 application.yml 5、根据数据库表创建实体类 User 6、创建 UserDao 接口 7、编写引导类 8、编写测试类 9、Run的运行结果 1、设置分页拦截器 package com.example.config; import com.baomidou.m…

文章解读与仿真程序复现思路——电力系统保护与控制EI\CSCD\北大核心《基于改进Q学习算法和组合模型的超短期电力负荷预测》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…