深入了解Linux中的环境变量

news/2024/7/22 13:46:19/文章来源:https://blog.csdn.net/2301_77754590/article/details/139247711

在Linux系统中,环境变量(Environment Variables)是用于配置操作系统和应用程序运行环境的一种机制。它们储存在键值对中,可以控制程序的行为、路径查找和系统配置。本文将深入探讨环境变量的基本概念、常见类型、设置和管理方法,以及一些实用的技巧。

一、环境变量的基本概念

环境变量是在操作系统环境中定义的一些变量,用于存储信息,以便在系统中共享和使用。这些变量可以影响程序的行为和操作系统的功能。

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

 首先在介绍环境变量前我们先介绍以下 “命令行参数”这一概念。

我们平常在Linux中输入命令时通常是这么使用的   ls -l    copy  test.c   /home/user

为什么后面可以跟后缀使用呢,这其实就跟我们的命令行参数有关

在C和C++编程中,命令行参数通过main函数的参数传递给程序。标准的main函数签名如下:

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

这个签名表明程序可以接受命令行参数,并通过argcargv这两个参数来访问这些输入。接下来,我们详细讲解这两个参数的作用和使用方法。

一、argcargv 的含义
  • argc(argument count):表示命令行参数的数量,包括程序名本身。
  • argv(argument vector):是一个指向字符数组的指针数组,每个元素指向一个命令行参数的字符串。

 

二、argcargv 的详细说明
1. argc 的作用

argc是一个整数,表示命令行参数的数量。例如,如果我们运行一个名为my_program的程序,并传递两个参数:

./my_program arg1 arg2

此时,argc的值为3,因为包括程序名在内总共有三个参数 

2. argv 的作用

argv是一个指向字符串数组的指针数组。每个元素是一个char*,指向一个命令行参数。假设上面的程序命令行如下

./my_program arg1 arg2

 那么,argv的内容如下:

  • argv[0]:指向字符串"./my_program"(程序名)。
  • argv[1]:指向字符串"arg1"(第一个参数)。
  • argv[2]:指向字符串"arg2"(第二个参数)。

argv[argc]是一个空指针(NULL),用于标记数组的结束。

三、实例讲解

下面是一个简单的C程序,它演示了如何使用argcargv来处理命令行参数:

#include <stdio.h>int main(int argc, char *argv[]) {// 打印命令行参数的数量printf("Number of arguments: %d\n", argc);// 遍历并打印每一个参数for (int i = 0; i < argc; i++) {printf("Argument %d: %s\n", i, argv[i]);}return 0;
}

 假设我们编译并运行该程序,传递一些命令行参数

./my_program arg1 arg2 arg3

 输出将是:

Number of arguments: 4
Argument 0: ./my_program
Argument 1: arg1
Argument 2: arg2
Argument 3: arg3

 

./my_program arg1 arg2 arg3

所以以上命令本质就是 程序的路径 + 名称   后面跟 和该进程匹配的选项

默认是交给父进程bash处理的! 命令中启动的程序都会变成进程,其实都是bash的子进程

那么为什么要有命令行参数呢?

本质:命令行参数本质是交给我们程序的不同选项,用来定制不同的程序功能

 下面是一个简单的例子

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 打印帮助信息
void print_help(const char *program_name) {printf("Usage: %s <command> [options]\n", program_name);printf("Commands:\n");printf("  help              Show this help message\n");printf("  add <num1> <num2> Calculate the sum of num1 and num2\n");printf("  sub <num1> <num2> Calculate the difference of num1 and num2\n");printf("  mul <num1> <num2> Calculate the product of num1 and num2\n");printf("  div <num1> <num2> Calculate the quotient of num1 and num2\n");
}// 计算两个数的和
void calculate_sum(int num1, int num2) {printf("Sum: %d\n", num1 + num2);
}// 计算两个数的差
void calculate_difference(int num1, int num2) {printf("Difference: %d\n", num1 - num2);
}// 计算两个数的积
void calculate_product(int num1, int num2) {printf("Product: %d\n", num1 * num2);
}// 计算两个数的商
void calculate_quotient(int num1, int num2) {if (num2 == 0) {printf("Error: Division by zero is not allowed.\n");return;}printf("Quotient: %d\n", num1 / num2);
}int main(int argc, char *argv[]) {if (argc < 2) {fprintf(stderr, "Error: No command provided.\n");print_help(argv[0]);return 1;}if (strcmp(argv[1], "help") == 0) {print_help(argv[0]);} else if (strcmp(argv[1], "add") == 0 && argc == 4) {int num1 = atoi(argv[2]);int num2 = atoi(argv[3]);calculate_sum(num1, num2);} else if (strcmp(argv[1], "sub") == 0 && argc == 4) {int num1 = atoi(argv[2]);int num2 = atoi(argv[3]);calculate_difference(num1, num2);} else if (strcmp(argv[1], "mul") == 0 && argc == 4) {int num1 = atoi(argv[2]);int num2 = atoi(argv[3]);calculate_product(num1, num2);} else if (strcmp(argv[1], "div") == 0 && argc == 4) {int num1 = atoi(argv[2]);int num2 = atoi(argv[3]);calculate_quotient(num1, num2);} else {fprintf(stderr, "Error: Invalid command or arguments.\n");print_help(argv[0]);return 1;}return 0;
}

编译并运行上述程序后,可以通过传递不同的命令行参数来执行不同的功能。例如:

./my_program sub 10 5

 那为什么内建命令不需要./呢,所以接下来我们继续讲解环境变量 

常见的环境变量包括:

  • PATH:存储可执行文件的目录路径列表,当你在终端输入命令时,系统会在这些目录中搜索可执行文件。
  • HOME:当前用户的主目录路径。
  • USER:当前登录的用户名。
  • SHELL:用户默认的Shell解释器。
  • LANG:系统的语言和区域设置。

二、查看环境变量

可以使用printenvenv和echo命令来查看当前的环境变量:

echo + $PATH/HOME 

 

 Linux中存在一些全局的设置,告诉命令行解释器应该去哪些路径下去寻找可执行程序

而系统中的很多配置,在我们刚刚登录到Linux中,就已经被加载到了bash进程(内存)中了,

所以我们默认查到的环境变量是内存级别的也就是说不会改变磁盘中的环境变量,当我们再次登录这个环境变量还是会重置!

所以最开始的环境变量不在内存中,而在对应的配置文件中

例如

  • .bash_profile
  • .bashrc
  • /etc/bashrc
和环境变量相关的命令
  • 1. echo: 显示某个环境变量值
  • 2. export: 设置一个新的环境变量
  • 3. env: 显示所有环境变量
  • 4. unset: 清除环境变量
  • 5. set: 显示本地定义的shell变量和环境变量

当执行当前目录下的外部命令时,需要使用 ./ 进行路径指定。这是因为:

  1. 安全性考虑:为了避免安全隐患,默认情况下,当前目录 . 并不包含在 PATH 环境变量中。这防止了恶意可执行文件以常用命令名命名并被误执行。
  2. 明确路径:通过使用 ./ 明确指定当前目录,用户告诉 Shell 要在当前目录中查找并执行相应的可执行文件。

例如,当前目录下有一个名为 my_script.sh 的脚本:

./my_script.sh

如果没有 ./,Shell 会按照 PATH 中指定的目录查找 my_script.sh,而不是当前目录。

所以我们把这个可执行程序的路径加入到环境变量中以后就不需要带有路径了。 

 

 三、环境变量的组织方式

环境变量在 Bash 内部是以一个键值对(key-value pair)的形式存储的。这些键值对存储在一个全局变量中,该变量在 Bash 的整个生命周期内都可以访问。 

环境变量的存储实际上依赖于操作系统提供的环境表。每个进程都有一个环境表,这个环境表是一个字符串数组,其中每个字符串的形式为 KEY=VALUE。在 Bash 中,使用外部命令 printenv 或内建命令 export 可以查看和管理这些变量。

也就是说bash进程启动的时候会默认给子进程形成两张表,一个是argv[]命令行参数表,另一个是environ[]环境变量表。bash通过各种方式传递给子进程

 

 四、通过代码如何获取环境变量

命令行第三个参数 

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

 通过第三方变量来获取

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

五、内建命令 

内建命令(built-in commands)是由 Shell 自身实现和提供的一类命令。与外部命令(external commands)不同,内建命令不依赖于文件系统中的独立可执行文件,而是直接在 Shell 进程中执行。内建命令的设计和实现旨在提高效率、提供更紧密的 Shell 集成以及实现一些只有 Shell 可以处理的特殊功能。下面详细介绍内建命令的作用与用途。

一、内建命令的主要作用
1. 提高执行效率

由于内建命令直接由 Shell 处理,不需要创建新的进程,因此执行速度比外部命令更快。每次执行内建命令时,Shell 不需要通过文件系统查找命令或创建子进程,这减少了开销和延迟。

2. 提供关键的 Shell 功能

内建命令实现了许多核心的 Shell 功能和控制结构,例如:

  • 环境管理exportsetunset 等命令用于设置和管理环境变量。
  • 目录操作cd 用于改变当前工作目录。
  • Shell 控制exit 退出 Shell 会话,exec 替换当前 Shell 进程。
  • 条件和循环ifforwhile 等控制结构实现了脚本中的条件和循环逻辑。
3. 处理 Shell 内部状态

一些内建命令可以直接操作和修改 Shell 的内部状态,例如设置选项、启用或禁用特性等:

  • 选项设置set 命令可以打开或关闭 Shell 的各种选项,例如调试模式、命令别名等。
  • 历史记录管理history 命令用于查看和操作命令历史记录。
4. 实现复杂的命令组合和脚本

内建命令在脚本编写中起着至关重要的作用。它们提供了丰富的编程构造,使得复杂的命令组合和脚本实现成为可能:

  • 函数定义function 用于定义 Shell 函数。
  • 输入输出重定向read 命令用于从标准输入读取数据。
二、内建命令的实现原理

内建命令是 Shell 内部实现的一部分,通常用 C 语言编写,直接集成在 Shell 的源代码中。当用户输入一个命令时,Shell 按照以下顺序进行处理:

  1. 检查内建命令:首先检查输入的命令是否为内建命令。如果是,则直接在当前进程中执行该命令。
  2. 检查别名:如果不是内建命令,Shell 接下来检查是否有定义的别名。
  3. 检查函数:然后,Shell 检查是否有定义的 Shell 函数。
  4. 搜索外部命令:最后,如果上述都不是,Shell 在 PATH 环境变量指定的目录中搜索外部命令。

这种查找顺序确保了内建命令的高效执行和优先处理。

四、总结

内建命令在 Shell 中发挥着重要作用。它们提高了命令执行的效率,提供了许多关键功能和控制结构,并且能够直接操作 Shell 的内部状态。了解和熟练使用内建命令,可以显著提升使用 Shell 和编写脚本的效率和灵活性。

如果你有任何进一步的问题或需要详细解释的内容,欢迎在评论区留言讨论。

 

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

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

相关文章

洪师傅代驾系统开发 支持公众号H5小程序APP 后端Java源码

代驾流程图 业务流程图 管理端设置 1、首页装修 2、师傅奖励配置 师傅注册后,可享受后台设置的新师傅可得的额外奖励; 例:A注册了师傅,新人奖励可享受3天,第一天的第一笔订单完成后可得正常佣金佣金*奖励比例 完成第二笔/第三笔后依次可得正常佣金佣金*奖励比例 完成的第四…

vue中封装组件实例

本篇是一篇组件封装。因为要经常使用&#xff0c;特此封装并且记录下来&#xff0c;以供参考。 封装组件&#xff1a;封装组件是指将一段具有特定功能的Vue代码&#xff08;包括模板、脚本和样式&#xff09;封装成一个可复用的组件。这个组件可以作为一个独立的单元&#xff…

Jetpack架构组件_1.基本知识

1.什么是Jetpack&#xff1f; Jetpack 是一个由多个库组成的套件&#xff0c;可帮助开发者遵循最佳做法、减少样板代码并编写可在各种 Android 版本和设备中一致运行的代码&#xff0c;让开发者可将精力集中于真正重要的编码工作。Jetpack 包含一系列 Android 库&#xff0c;它…

免费,Python蓝桥杯等级考试真题--第13级(含答案解析和代码)

Python蓝桥杯等级考试真题–第13级 一、 选择题 答案&#xff1a;C 解析&#xff1a;正向下标由0开始&#xff0c;下标3代表第四个元素&#xff0c;故答案为C。 答案&#xff1a;A 解析&#xff1a;range&#xff08;0,4&#xff09;的取前不取后&#xff0c;元组的符号是小括…

Nvidia Orin/Jetson +GMSL/RLINC/VbyOne/FPDLink 同轴AI多相机同步车载视觉解决方案

在本次演讲中&#xff0c;介绍了多相机同步技术在自主机器中的应用情况&#xff0c;围绕无人配送小车、控制器视觉传感器方案升级、人形机器人三个典型案例中如何为客户提供高效的多相机同步解决方案进行了详细的讲解&#xff0c;并进一步介绍如何通过创新的多相机同步技术&…

学习编程对英语要求高吗?

学习编程并不一定需要高深的英语水平。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&#xff0c;我在后台发给你。 虽然一些编程资源和文档可能…

react-native 默认停用 flipper 通知

react-native 0.74 默认停用 flipper &#xff0c;但仍然可以手动安装 flipper 官方声明文档 英语好的可以直接阅读。 integration with React Native will no longer be enabled 原因 增加编译时间有时候会有连接问题升级会导致不能使用 之后调试推荐 我们建议团队使用 A…

力扣hot100学习记录(七)

240. 搜索二维矩阵 II 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 题意 在二维矩阵中搜索是否存在一个目标值&#xff0c;该矩阵每一行每一列都是升序…

【QT八股文】系列之篇章2 | QT的信号与槽机制及通讯流程

【QT八股文】系列之篇章2 | QT的信号与槽机制及通讯流程 前言2. 信号与槽信号与槽机制介绍/本质/原理&#xff0c;什么是Qt信号与槽机制&#xff1f;如何在Qt中使用&#xff1f;信号与槽机制原理&#xff0c;解析流程Qt信号槽的调用流程信号与槽机制的优缺点信号与槽机制需要注…

猜猜我是谁游戏

猜谜过程 在TabControl控件中&#xff0c;第一个tab中放了一个PictureBox&#xff0c;里面有一张黑色的图片。 玩家点击显示答案按钮&#xff0c;切换图片。 设计器 private void button1_Click(object sender, EventArgs e){this.pictureBox1.Image Image.FromFile(&qu…

web自动化的断言和日志封装

断言 UI自动化常见的断言条件包括&#xff1a; 通过当前页面的URL地址通过当前页面的标题通过当前页面的提示文本信息通过当前页面的某些元素变化/显示 一句话总结&#xff1a;通过肉眼观察页面的变化检查。 【用代码模仿人的识别页面】 一般断言写一条就够了&#xff0c;如…

【基础算法总结】前缀和二

前缀和二 1.和为 K 的子数组2.和可被 K 整除的子数组3.连续数组4. 矩阵区域和 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1f603; 1.和为 K 的子数…

WPS PPT学习笔记 2 结构页的制作

制作PPT结构页 制作封面页、目录页、封底页。它们都属于结构页。而时间轴页&#xff0c;流程图页&#xff0c;框架图页这些属于内容页。 做一份PPT 讲一个故事 封面页 开头&#xff0c; 目录页 脉络&#xff0c; 各式内容页 详情&#xff0c; 封底页 结尾。 所有的结构页…

华为CE6851-48S6Q-HI升级设备版本及补丁

文章目录 升级前准备工作笔记本和交换机设备配置互联地址启用FTP设备访问FTP设备升级系统版本及补丁 升级前准备工作 使用MobaXterm远程工具连接设备&#xff0c;并作为FTP服务器准备升级所需的版本文件及补丁文件 笔记本和交换机设备配置互联地址 在交换机接口配置IP&#…

Ubuntu24.04安装tabby-terminal-1.0.207并处理依赖

1 下载 tabby-terminal-1.0.207 地址&#xff1a; https://github.com/Eugeny/tabby/releases 点击show all 36 assets 选择 tabby-1.0.207-linux-x64.deb 并下载。 2 依赖下载 gconf2_3.2.6-3ubuntu6_amd64.deb gconf2-common_3.2.6-3ubuntu6_all.deb gconf-service_3.2.6-…

fpga系列 HDL: 05 阻塞赋值(=)与非阻塞赋值(<=)

在Verilog硬件描述语言&#xff08;HDL&#xff09;中&#xff0c;信号的赋值方式主要分为两种&#xff1a;连续赋值和过程赋值。每种赋值方式有其独特的用途和语法&#xff0c;并适用于不同类型的电路描述。 1. 连续赋值&#xff08;Continuous Assignment,assign 和&#xf…

【Matlab函数分析】绘图函数:colormap查看并设置当前颜色图

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f91…

云计算-基础云架构(Fundamental Cloud Architectures)

工作负载分配架构&#xff08;Workload Distribution Architecture&#xff09; 工作负载分配架构是一种基础架构&#xff0c;它在一组相同的IT资源之间分配负载。其结构如图7.1所示&#xff08;更好的图示在教材中&#xff09;。 图&#xff1a;工作负载分配架构 这个结构中的…

Elasticsearch之入门与安装

Elaticsearch&#xff0c;简称为es&#xff0c; es是一个开源的高扩展的分布式全文检索引擎&#xff0c;它可以近乎实时的存储、检索数据&#xff1b;本身扩展性很好&#xff0c;可以扩展到上百台服务器&#xff0c;处理PB级别的数据。es也使用Java开发并使用Lucene作为其核心来…

【源码】一站式Java云商城系统源码,无后门

一站式Java云商城系统源码&#xff0c;无后门&#xff0c;不是java源代码&#xff0c;是编译后的。 系统对接 手动发货 自动发货 兑 换 码 订单监控 商品监控 对象存储 邮箱提醒 加价模板 密价功能 三方支付 会员体系 财务明细 交易分析 售后服务 技术支持 服务器建议配置&a…