当前位置: 首页 > news >正文

深入了解Linux中的环境变量

在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 和编写脚本的效率和灵活性。

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

 

相关文章:

深入了解Linux中的环境变量

在Linux系统中&#xff0c;环境变量&#xff08;Environment Variables&#xff09;是用于配置操作系统和应用程序运行环境的一种机制。它们储存在键值对中&#xff0c;可以控制程序的行为、路径查找和系统配置。本文将深入探讨环境变量的基本概念、常见类型、设置和管理方法&a…...

雷军-2022.8小米创业思考-8-和用户交朋友,非粉丝经济;性价比是最大的诚意;新媒体,直播离用户更近;用真诚打动朋友,脸皮厚点!

第八章 和用户交朋友 2005年&#xff0c;为了进一步推动金山的互联网转型&#xff0c;让金山的同事更好地理解互联网的精髓&#xff0c;我推动了一场向谷歌学习的运动&#xff0c;其中一个小要求就是要能背诵“谷歌十诫”。 十诫的第一条就令人印象深刻&#xff1a;以用户为中…...

【Vue2.x】props技术详解

1.什么是prop&#xff1f; 定义&#xff1a;组件标签上注册的一些自定义属性作用&#xff1a;向子组件传递数据特点 可以传递任意数量的prop可以传递任意类型的prop 2.prop校验 为了避免乱传数据&#xff0c;需要进行校验 完整写法 将之前props数组的写法&#xff0c;改为对象…...

C语言例题46、根据公式π/4=1-1/3+1/5-1/7+1/9-1/11+…,计算π的近似值,当最后一项的绝对值小于0.000001为止

#include <stdio.h> #include <math.h>int main() {int fm 1;//分母double sign 1;//正负号double fzs 1;//分子式double sum 0;while (fabs(fzs) > 0.000001) {sum fzs;sign * -1; //变换正负号fm 2; //分母3、5、7、9...增长fzs sign / fm;//分子式…...

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

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

大白话DC3算法

DC3算法是什么 DC3算法&#xff08;也称为Skew算法&#xff09;是一种高效的构建后缀数组的算法&#xff0c;全称为Difference Cover Modulo 3算法。 该算法于2002年被提出&#xff0c;论文参考&#xff1a; https://www.cs.cmu.edu/~guyb/paralg/papers/KarkkainenSanders0…...

力扣HOT100 - 75. 颜色分类

解题思路&#xff1a; 单指针&#xff0c;对数组进行两次遍历。 class Solution {public void sortColors(int[] nums) {int p 0;int n nums.length;for (int i 0; i < n; i) {if (nums[i] 0) {int tmp nums[i];nums[i] nums[p];nums[p] tmp;p;}}for (int i p; i …...

Vue.js - 计算属性与侦听器 【0基础向 Vue 基础学习】

文章目录 计算属性 computedcomputed 的使用方法computed 与 method 的区别计算属性完整写法 watch 侦听器&#xff08;监视器&#xff09;简单写法 → 简单类型数据&#xff0c;直接监视完整写法 → 添加额外配置项 计算属性 computed computed 的使用方法 **概念&#xff1…...

技术速递|使用 C# 集合表达式重构代码

作者&#xff1a;David Pine 排版&#xff1a;Alan Wang 本文是系列文章的第二篇&#xff0c;该系列文章涵盖了探索 C# 12功能的各种重构场景。在这篇文章中&#xff0c;我们将了解如何使用集合表达式重构代码&#xff0c;我们将学习集合初始化器、各种表达式用法、支持的集合目…...

我的世界开服保姆级教程

前言 Minecraft开服教程 如果你要和朋友联机时&#xff0c;可以选择的方法有这样几种&#xff1a; 局域网联机&#xff1a;优点&#xff1a;简单方便&#xff0c;在MC客户端里自带。缺点&#xff1a;必须在同一局域网内。 有些工具会带有联机功能&#xff1a;优点&#xff1a;一…...

[转载]同一台电脑同时使用GitHub和GitLab

原文地址&#xff1a;https://developer.aliyun.com/article/893801 简介&#xff1a; 工作中我们有时可能会在同一台电脑上使用多个git账号&#xff0c;例如&#xff1a;公司的gitLab账号&#xff0c;个人的gitHub账号。怎样才能在使用gitlab与github时&#xff0c;切换成对应…...

【网络协议】【OSI】一次HTTP请求OSI工作过程详细解析

目录 1. 一次HTTP请求OSI工作过程 1.1 应用层(第7层) 1.2 表示层(第6层) 1.3 会话层(第5层) 1.4 传输层(第4层)...

springboot vue 开源 会员收银系统 (2) 搭建基础框架

前言 完整版演示 前面我们对会员系统https://blog.csdn.net/qq_35238367/article/details/126174288进行了分析 确定了技术选型 和基本的模块 下面我们将从 springboot脚手架开发一套收银系统 使用脚手架的好处 不用编写基础的rabc权限系统将工作量回归业务本身生成代码 便于…...

Java进阶学习笔记26——包装类

包装类&#xff1a; 包装类就是把基本类型的数据包装成对象。 看下API文档&#xff1a; deprecated&#xff1a;极力反对、不赞成的意思。 marked for removal&#xff1a;标识为去除的意思。 自动装箱&#xff1a;基本数据类型可以自动转换成包装类。 自动拆箱&#xff1a;…...

【JavaEE进阶】——要想代码不写死,必须得有spring配置(properties和yml配置文件)

目录 本章目标&#xff1a; &#x1f6a9;配置文件 &#x1f6a9;SpringBoot配置文件 &#x1f388;配置⽂件的格式 &#x1f388; properties 配置⽂件说明 &#x1f4dd;properties语法格式 &#x1f4dd;读取配置文件 &#x1f4dd;properties 缺点分析 &#x1f3…...

第十四 Elasticsearch介绍和安装

docker-compose安装 kibana: image: docker.elastic.co/kibana/kibana:7.5.1 container_name: kibana ports: - "5601:5601" environment: ELASTICSEARCH_HOSTS: http://elasticsearch:9200 depends_on: - elasticsearch…...

YOLOv10介绍与推理--图片和视频演示(附源码)

导 读 本文主要对YOLOv10做简单介绍并给出推理图片和视频的步骤演示。 YOLOv10简介 YOLOv10是清华大学的研究人员在Ultralytics Python包的基础上&#xff0c;引入了一种新的实时目标检测方法&#xff0c;解决了YOLO 以前版本在后处理和模型架构方面的不足。通过消除非最大抑…...

Java实验08

实验一 demo.java package q8.demo02;public class demo{public static void main(String[] args) {WindowMenu win new WindowMenu("Hello World",20,30,600,290);} }WindowMenu.java package q8.demo02; import javax.swing.*;public class WindowMenu extends…...

MyBatis复习笔记

3.Mybatis复习 3.1 xml配置 properties&#xff1a;加载配置文件 settings&#xff1a;设置驼峰映射 <settings><setting name"mapUnderscoreToCamelCase" value"true"/> </settings>typeAliases&#xff1a;类型别名设置 #这样在映射…...

HTML的基石:区块标签与小语义标签的深度解析

&#x1f4da; HTML的基石&#xff1a;区块标签与小语义标签的深度解析 &#x1f310; 区块标签&#xff1a;构建网页的框架&#x1f3e0; <div>&#xff1a;万能的容器&#x1f4da; <section>、<article>、<aside>&#xff1a;语义化的布局 &#x1…...

从一次应急响应说起:深澜计费管理系统文件读取漏洞的修复与加固指南

深澜计费管理系统安全事件响应实战&#xff1a;从告警分析到系统加固全流程 那天凌晨2点15分&#xff0c;安全设备的告警声划破了运维中心的宁静。作为系统安全负责人&#xff0c;我立刻从值班室的折叠床上弹起来&#xff0c;屏幕上赫然显示着"深澜计费管理系统异常文件访…...

从蓝图到代码:UE5项目C++化实战指南

1. 为什么需要将UE5蓝图项目转为C项目 很多刚开始接触Unreal Engine 5的开发者都会从蓝图开始学习。确实&#xff0c;蓝图的可视化编程方式非常直观&#xff0c;不需要写代码就能实现复杂功能。但是随着项目规模扩大&#xff0c;你会发现纯蓝图项目开始暴露出一些明显问题。 首…...

kmp算法:我们所忽略的字符串匹配本质

一、先捅破窗户纸&#xff1a;前后缀在匹配里到底起什么作用&#xff1f;在讲next数组的计算之前&#xff0c;我们必须先把“为什么有前后缀&#xff0c;就能不回退主串”这个核心逻辑彻底讲透&#xff0c;这是字符串匹配的本质核心。我们用一个有前后缀的经典案例&#xff0c;…...

实战:Java 日志中打印服务器 IP,快速区分多服务器日志归属

一、核心需求与背景当多台服务器&#xff08;如两台应用服务器&#xff09;运行相同代码时&#xff0c;日志文件 / 日志平台中无法直接区分日志来自哪台机器&#xff0c;排查问题时效率极低。解决思路是&#xff1a;在日志中固定输出当前服务器的 IPv4 地址&#xff0c;通过 IP…...

DS1307实时时钟芯片驱动开发与工程实践指南

1. DS1307实时时钟芯片驱动技术深度解析DS1307是由Maxim Integrated&#xff08;现为Analog Devices&#xff09;推出的经典IC接口实时时钟&#xff08;RTC&#xff09;芯片&#xff0c;采用SOIC-8封装&#xff0c;工作电压范围2.0V–5.5V&#xff0c;支持-40C至85C工业级温度范…...

终极SocketRocket发布指南:从打包到CocoaPods推送的完整流程

终极SocketRocket发布指南&#xff1a;从打包到CocoaPods推送的完整流程 【免费下载链接】SocketRocket A conforming Objective-C WebSocket client library. 项目地址: https://gitcode.com/gh_mirrors/so/SocketRocket SocketRocket是一个符合标准的Objective-C WebS…...

如何用 Splinter 在 5 分钟内完成第一个 Web 自动化测试

如何用 Splinter 在 5 分钟内完成第一个 Web 自动化测试 【免费下载链接】splinter splinter - python test framework for web applications 项目地址: https://gitcode.com/gh_mirrors/sp/splinter Splinter 是一款强大的 Python Web 应用测试框架&#xff0c;能帮助…...

解锁学术新境界:书匠策AI——你的期刊论文智能导航员

在学术探索的浩瀚海洋中&#xff0c;每一位研究者都渴望拥有一盏明灯&#xff0c;照亮前行的道路&#xff0c;让复杂的论文写作之旅变得轻松而高效。今天&#xff0c;就让我们一同揭开书匠策AI的神秘面纱&#xff0c;探索它如何成为你撰写期刊论文时的得力助手与智能导航员。&a…...

从SIMPLIS到Matlab:开关电源开环传递函数的建模与验证

1. 从仿真到验证&#xff1a;为什么需要跨平台协作 作为一名电源工程师&#xff0c;我经常遇到这样的困境&#xff1a;在电路仿真软件中得到了漂亮的波形和曲线&#xff0c;但想要深入分析系统特性时却无从下手。这就是为什么我们需要掌握从SIMPLIS到Matlab的完整工作流程。SI…...

避坑指南:RcisTarget转录因子分析中常见的5个错误及解决方案(附数据库选择建议)

RcisTarget转录因子分析实战避坑指南&#xff1a;从参数优化到结果验证 在基因调控网络研究中&#xff0c;RcisTarget作为一款强大的R包&#xff0c;能够通过motif富集分析预测调控基因集的转录因子。然而&#xff0c;即使是经验丰富的研究者&#xff0c;在实际分析过程中也常会…...