深入了解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[])
这个签名表明程序可以接受命令行参数,并通过argc和argv这两个参数来访问这些输入。接下来,我们详细讲解这两个参数的作用和使用方法。
一、argc 和 argv 的含义
argc(argument count):表示命令行参数的数量,包括程序名本身。argv(argument vector):是一个指向字符数组的指针数组,每个元素指向一个命令行参数的字符串。
二、argc 和 argv 的详细说明
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程序,它演示了如何使用argc和argv来处理命令行参数:
#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:系统的语言和区域设置。
二、查看环境变量
可以使用printenv或env和echo命令来查看当前的环境变量:
echo + $PATH/HOME

Linux中存在一些全局的设置,告诉命令行解释器应该去哪些路径下去寻找可执行程序
而系统中的很多配置,在我们刚刚登录到Linux中,就已经被加载到了bash进程(内存)中了,
所以我们默认查到的环境变量是内存级别的也就是说不会改变磁盘中的环境变量,当我们再次登录这个环境变量还是会重置!
所以最开始的环境变量不在内存中,而在对应的配置文件中
例如
- .bash_profile
- .bashrc
- /etc/bashrc
- 1. echo: 显示某个环境变量值
- 2. export: 设置一个新的环境变量
- 3. env: 显示所有环境变量
- 4. unset: 清除环境变量
- 5. set: 显示本地定义的shell变量和环境变量
当执行当前目录下的外部命令时,需要使用 ./ 进行路径指定。这是因为:
- 安全性考虑:为了避免安全隐患,默认情况下,当前目录
.并不包含在PATH环境变量中。这防止了恶意可执行文件以常用命令名命名并被误执行。 - 明确路径:通过使用
./明确指定当前目录,用户告诉 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 功能和控制结构,例如:
- 环境管理:
export、set、unset等命令用于设置和管理环境变量。 - 目录操作:
cd用于改变当前工作目录。 - Shell 控制:
exit退出 Shell 会话,exec替换当前 Shell 进程。 - 条件和循环:
if、for、while等控制结构实现了脚本中的条件和循环逻辑。
3. 处理 Shell 内部状态
一些内建命令可以直接操作和修改 Shell 的内部状态,例如设置选项、启用或禁用特性等:
- 选项设置:
set命令可以打开或关闭 Shell 的各种选项,例如调试模式、命令别名等。 - 历史记录管理:
history命令用于查看和操作命令历史记录。
4. 实现复杂的命令组合和脚本
内建命令在脚本编写中起着至关重要的作用。它们提供了丰富的编程构造,使得复杂的命令组合和脚本实现成为可能:
- 函数定义:
function用于定义 Shell 函数。 - 输入输出重定向:
read命令用于从标准输入读取数据。
二、内建命令的实现原理
内建命令是 Shell 内部实现的一部分,通常用 C 语言编写,直接集成在 Shell 的源代码中。当用户输入一个命令时,Shell 按照以下顺序进行处理:
- 检查内建命令:首先检查输入的命令是否为内建命令。如果是,则直接在当前进程中执行该命令。
- 检查别名:如果不是内建命令,Shell 接下来检查是否有定义的别名。
- 检查函数:然后,Shell 检查是否有定义的 Shell 函数。
- 搜索外部命令:最后,如果上述都不是,Shell 在
PATH环境变量指定的目录中搜索外部命令。
这种查找顺序确保了内建命令的高效执行和优先处理。
四、总结
内建命令在 Shell 中发挥着重要作用。它们提高了命令执行的效率,提供了许多关键功能和控制结构,并且能够直接操作 Shell 的内部状态。了解和熟练使用内建命令,可以显著提升使用 Shell 和编写脚本的效率和灵活性。
如果你有任何进一步的问题或需要详细解释的内容,欢迎在评论区留言讨论。
相关文章:
深入了解Linux中的环境变量
在Linux系统中,环境变量(Environment Variables)是用于配置操作系统和应用程序运行环境的一种机制。它们储存在键值对中,可以控制程序的行为、路径查找和系统配置。本文将深入探讨环境变量的基本概念、常见类型、设置和管理方法&a…...
雷军-2022.8小米创业思考-8-和用户交朋友,非粉丝经济;性价比是最大的诚意;新媒体,直播离用户更近;用真诚打动朋友,脸皮厚点!
第八章 和用户交朋友 2005年,为了进一步推动金山的互联网转型,让金山的同事更好地理解互联网的精髓,我推动了一场向谷歌学习的运动,其中一个小要求就是要能背诵“谷歌十诫”。 十诫的第一条就令人印象深刻:以用户为中…...
【Vue2.x】props技术详解
1.什么是prop? 定义:组件标签上注册的一些自定义属性作用:向子组件传递数据特点 可以传递任意数量的prop可以传递任意类型的prop 2.prop校验 为了避免乱传数据,需要进行校验 完整写法 将之前props数组的写法,改为对象…...
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硬件描述语言(HDL)中,信号的赋值方式主要分为两种:连续赋值和过程赋值。每种赋值方式有其独特的用途和语法,并适用于不同类型的电路描述。 1. 连续赋值(Continuous Assignment,assign 和…...
大白话DC3算法
DC3算法是什么 DC3算法(也称为Skew算法)是一种高效的构建后缀数组的算法,全称为Difference Cover Modulo 3算法。 该算法于2002年被提出,论文参考: https://www.cs.cmu.edu/~guyb/paralg/papers/KarkkainenSanders0…...
力扣HOT100 - 75. 颜色分类
解题思路: 单指针,对数组进行两次遍历。 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 侦听器(监视器)简单写法 → 简单类型数据,直接监视完整写法 → 添加额外配置项 计算属性 computed computed 的使用方法 **概念࿱…...
技术速递|使用 C# 集合表达式重构代码
作者:David Pine 排版:Alan Wang 本文是系列文章的第二篇,该系列文章涵盖了探索 C# 12功能的各种重构场景。在这篇文章中,我们将了解如何使用集合表达式重构代码,我们将学习集合初始化器、各种表达式用法、支持的集合目…...
我的世界开服保姆级教程
前言 Minecraft开服教程 如果你要和朋友联机时,可以选择的方法有这样几种: 局域网联机:优点:简单方便,在MC客户端里自带。缺点:必须在同一局域网内。 有些工具会带有联机功能:优点:一…...
[转载]同一台电脑同时使用GitHub和GitLab
原文地址:https://developer.aliyun.com/article/893801 简介: 工作中我们有时可能会在同一台电脑上使用多个git账号,例如:公司的gitLab账号,个人的gitHub账号。怎样才能在使用gitlab与github时,切换成对应…...
【网络协议】【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——包装类
包装类: 包装类就是把基本类型的数据包装成对象。 看下API文档: deprecated:极力反对、不赞成的意思。 marked for removal:标识为去除的意思。 自动装箱:基本数据类型可以自动转换成包装类。 自动拆箱:…...
【JavaEE进阶】——要想代码不写死,必须得有spring配置(properties和yml配置文件)
目录 本章目标: 🚩配置文件 🚩SpringBoot配置文件 🎈配置⽂件的格式 🎈 properties 配置⽂件说明 📝properties语法格式 📝读取配置文件 📝properties 缺点分析 dz…...
第十四 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包的基础上,引入了一种新的实时目标检测方法,解决了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:加载配置文件 settings:设置驼峰映射 <settings><setting name"mapUnderscoreToCamelCase" value"true"/> </settings>typeAliases:类型别名设置 #这样在映射…...
HTML的基石:区块标签与小语义标签的深度解析
📚 HTML的基石:区块标签与小语义标签的深度解析 🌐 区块标签:构建网页的框架🏠 <div>:万能的容器📚 <section>、<article>、<aside>:语义化的布局 …...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
