Linux系统编程:详解环境变量

news2024/11/16 4:28:37

目录

一. 环境变量的基本概念

1.1 什么是环境变量

1.2 环境变量的功能测试

二. 与环境变量相关的操作 

三. 环境变量的组织方式

四. 通过代码获取环境变量的值

五. 总结


一. 环境变量的基本概念

1.1 什么是环境变量

环境变量是用于指定操作系统相关参数的、全局的变量。通过env指令,可以查看系统中全部的环境变量。

下面是几个常见的环境变量:

  • PATH:指令的搜索路径
  • HOME:特定用户的家目录,即:用户登录时默认所在的路径。
  • SHELL:当前的shell外壳,一般为/bin/bash

查看环境变量值的方法:echo $环境变量名

环境变量有如下几点特性:

  • 某个进程环境变量是从它的父进程中继承下来的。
  • 默认所有的环境变量都会被子进程继承。
  • 环境变量具有全局属性。

1.2 环境变量的功能测试

  • 测试PATH

PATH表示指令的默认搜索路径,我们首先通过echo $PATH,获取当前的PATH值,如图1.1所示,我们看到所有的路径被:分割,OS会依次从PATH的路径中搜索用户输入的指令,直到找到指令为止,如果到了最后一个路径还没有找到,那么OS就认为指令不存在,无法执行。

图1.1 环境变量PATH的值

我们创建编译下面的代码,生成可执行程序mytest.exe,分别在命令行中输入./mytest.exe和mytest.exe,前者成功运行,后者运行失败,详见图1.2。这是因为mytest.exe并不是一条指令,mytest.exe文件所在的路径不包含在PATH值内。

结论:Linux系统内置的指令不需要路径,输入指令名称就可以运行。用户自主编译生成的可执行程序,需要加上路径./XXX才可以运行。

图1.2 加路径和直接输入可执行程序名称时的运行结果

接下来,通过指令 export PATH=$PATH:(pwd)  修改修改环境变量PATH的值,然后再次在命令行中直接输入mytest.exe,可见这次程序运行成功了(详见图1.3)!此时通过echo $PATH查看PATH的值,可见当前路径被加入到了PATH中,因此直接输入mytest.exe可以成功运行程序。

图1.3 改变环境变量PATH的值
  • 测试HOME 

在两个终端下,分别使用普通用户zhangHHH和root用户登录,分别使用echo $HOME指令在不同用户登录的情况下查看环境变量HOME的值,可以看到HOME就是用户的家目录。

图1.4 在普通用户和root用户下测试HOME的值

二. 与环境变量相关的操作 

  • echo $ -- 获取环境变量值 

语法:echo $val_name,可以输出环境变量的值。这里的$不能省略,如果省略,那么输出的就是环境变量本身了,如echo PATH输出PATH。

  • export -- 定义环境变量 

语法:export 环境变量名称=值,如:export VAL=1234,就定义了一个名称为Val,值为1234的环境变量,这个变量具有全局属性。 

  • env -- 获取系统中的所有环境变量

如果我们通过export设定了环境变量,那么使用env同样能够查到。

  • unset -- 清楚环境变量

语法:unset [环境变量名称]

图2.1 环境变量相关操作

三. 环境变量的组织方式

一个main函数,最多可以有三个形参。即:main(int argc, char* argv[], char* env[]),其中argc为运行可执行程序时命令行参数的个数,argv为指向命令行参数列表的指针数组,env为指向环境变量列表的指针数组。

env指向一个存有若干char*类型变量的指针数组,数组以NULL结尾,数组中的每个数据指向一个环境变量的值,见图3.1。argv的组织方式与env基本完全相同,只不过不会以NULL结尾,但会有argc来获取记录选项的个数。

图3.1 环境变量的组织

四. 通过代码获取环境变量的值

  • 方法1:通过main函数的第三个参数获取

main(int argc, char* argv[], char* env[]))函数的第三个参数为指向环境变量列表的指针数组,通过evn[i],可以依次获取每个环境变量。代码4.1通过for循环,以env[i] != NULL为循环条件,依次打印每个环境变量的值。程序运行结果见图4.1。

代码4.1:通过main函数第三个参数获取环境变量

#include<iostream>    
      
main(int argc, char* argv[], char* env[])    
{    
    for(int i = 0; env[i]; ++i)    
    {    
        printf("env[%d] = %s\n", i, env[i]);                                                                                       
    }   
 
    return 0;    
}   
图4.1 通过代码4.1的运行结果
  •  方法2:通过第三方变量char **environ获取

变量char **environ被包含在头文件<unistd.h>中,在使用时,需要显示的包含头文件<unistd.h>或者在程序中声明外部变量extern char **environ。代码4.2展示了environ的用法。

代码4.2:通过第三方变量environ获取环境变量  

#include<iostream>    
#include<unistd.h>    
    
int main()                                                                                                                           
{                                                         
    for(int i = 0; environ[i]; ++i)                       
    {                                                     
        printf("environ[%d] = %s\n", i, environ[i]);      
    }                                                     
    return 0;                                             
} 
  • 方法三:通过函数getenv获取

语法:char* env_name = getenv("环境变量名称")

如果企图获取不存在的环境变量,那么程序会在运行期间报错Segmentation fault。

代码4.3:通过getenv函数获取环境变量值

#include<iostream>    
int main()                                                                                                                           
{             
    char* path = getenv("PATH");    
    char* home = getenv("HOME");    
    printf("PATH:%s\n", path);      
    printf("home:%s\n", home);    
    return 0;                     
} 
图4.2 代码4.3的运行结果

补充知识:

我们可以直接在命令行中使用  val_name=val 类似的指令来定义局部变量的值,但是,这并不属于全局变量,如果我们企图使用getenv获取它们的值,会在运行期间报错Segmentation fault。

这里由于提到了main函数的三个参数,因此也顺便对int argc和char* argv[]进行解读。argv表示可执行程序运行时命令行参数的个数,如果仅输入./XXX运行,那么命令行参数的个数就为1。

命令行参数的主要功能是让同一个函数,根据输入的选项,执行不同的代码。如代码4.4所示,我们要求至少有两个命令行参数,如果只输入一个(argc < 2),那么程序报错退出,如果输入选项-a,那么就执行function1,如果输入选择-b,那么就执行function2。

结论:选项 + 命令行参数可以实现同一份代码执行不同工作。

代码4.4:通过命令行参数让同一份代码执行不同工作

  #include<iostream>    
  #include<string.h>    
      
  int main(int argc, char *argv[], char *env[])    
  {    
      //至少有两个命令行参数(一个选项)    
      if(argc < 2)    
      {    
          std::cout << "至少两个命令行参数" << std::endl;    
      }    
      
      if(strcmp(argv[1], "-a") == 0)    
      {    
          std::cout << "function1" << std::endl;    
      }    
      else if(strcmp(argv[1], "-b") == 0)                                                                                                                                                                                                                                     
      {    
          std::cout << "function2" << std::endl;    
      }    
      
      return 0;    
  }  
图4.3 代码4.4的运行结果

五. 总结

  • 环境变量是用于定义操作系统相关参数的全局变量,主要有PATH、HOME、SHELL等,每个进程的环境变量从它的父进程中继承。
  • 通过echo $、export、unset、env等指令,可以实现对环境变量的增删查改。
  • 环境变量是通过指针数组来组织的,char* env[]可作为main函数的第三个参数。
  • 有三种方法可以实现在代码中获取环境变量的值:通过main函数的第三个参数char* env[]、通过第三方变量extern char **environ、通过getenv函数。
  • main函数的第一个参数argc表示命令行参数的个数,第二个参数为指向命令行参数存储地址的指针数组,通过 命令行参数+选项 的组合使用,可让一份代码根据用户需要实现不同的功能。

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

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

相关文章

大语言模型 -- 部署LaWGPT模型记录

模型介绍&#xff1a; 该系列模型在通用中文基座模型&#xff08;如 Chinese-LLaMA、ChatGLM 等&#xff09;的基础上扩充法律领域专有词表、大规模中文法律语料预训练&#xff0c;增强了大模型在法律领域的基础语义理解能力。在此基础上&#xff0c;构造法律领域对话问答数据…

SpringBoot——2.7.3版本整合Swagger3

前言 Swagger2&#xff08;基于openApi3&#xff09;已经在17年停止维护了&#xff0c;取而代之的是 sagger3&#xff08;基于openApi3&#xff09;&#xff0c;而国内几乎没有 sagger3使用的文档&#xff0c;百度搜出来的大部分都是swagger2的使用&#xff0c;这篇文章将介绍…

存量时代,CRM系统如何赋能企业客户关系管理

如何发掘和吸引新客户、如何维系现有客户、如何推动业务增长&#xff0c;一直是众多公司运营管理中时常要面对的关键问题。尤其在数字化时代&#xff0c;用户获取信息的渠道越来越丰富&#xff0c;企业的获客渠道也在日益增多&#xff0c;面对每天的海量数据&#xff0c;企业该…

【无线传感器】使用 MATLAB和 XBee连续监控温度传感器无线网络研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【MOOC 测验】第3章 运输层

1​、在 ISO/OSI 参考模型中&#xff0c;对于运输层描述正确的有&#xff08; &#xff09; A. 为传输数据选择数据链路层所提供的最合适的服务B. 为系统之间提供面向连接的数据传输服务C. 可以提供端到端的差错恢复和流量控制&#xff0c;实现可靠的数据传输D. 提供路由选择…

TP composer 新创建一个vendor2,作为新库下载目录

站点目录新建一个vendor2文件夹&#xff1a; 在里面新建一个 composer.json 文件&#xff1a;(只写一个花括号就行) {} 然后这个vendor2目录里&#xff0c;使用宝塔终端执行&#xff1a; composer require zoujingli/ip2region 这样&#xff0c;vendor2目录里就会再多出 v…

AI大模型应用时代,如何通过数据“造好品,卖好品”?

在数字化时代的浪潮中&#xff0c;品牌营销正面临着前所未有的挑战和机遇。随着技术的迅猛发展&#xff0c;消费者的行为和期望也在不断演变。 新的市场环境下&#xff0c;消费者的需求和购买行为发生了哪些变化&#xff1f; 数码家电转战社媒平台&#xff0c;竞争白热化如…

HAL库记录--外部中断

1.STM32CubaMX配置 2.分析生成代码 /*Configure GPIO pin : PtPin */GPIO_InitStruct.Pin GPIO_PIN_12;GPIO_InitStruct.Mode GPIO_MODE_IT_FALLING;GPIO_InitStruct.Pull GPIO_PULLUP;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* EXTI interrupt init*/HAL_NVIC_SetPri…

leetcode:191. 位1的个数(python3解法)

难度&#xff1a;简单 编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回其二进制表达式中数字位数为 1 的个数&#xff08;也被称为汉明重量&#xff09;。 提示&#xff1a; 请注意&#xff0c;在某些语言&#xff08;…

经纬恒润OTA仿真测试解决方案为汽车智能化发展保驾护航

OTA技术是汽车实现完整网联化、智能化体验的基础&#xff0c;自被引用汽车以来&#xff0c;广受研发人员、市场用户的关注。近来&#xff0c;国家有关部门也陆续出台了相应政策&#xff0c;对汽车企业OTA技术的应用进行了约束和规范。因此&#xff0c;OTA技术在量产车型的应用落…

el-date-picker 前者选择日期 后者禁用 (包括时分)

<template><el-form><el-form-item prop"pullinDateTime" label"进站时间"><el-date-picker v-model"form.pullinDateTime" type"datetime" value-format"yyyy-MM-dd HH:mm:ss"placeholder"选择日…

【无标题】看IT小白花15分钟安装TitanIDE

作为大学刚毕业没多久的IT小白&#xff0c;入职了行云创新&#xff08;www.cloudtogo.cn&#xff09;的市场部&#xff0c;我的老大让我学习并熟悉公司的产品——TitanIDE&#xff0c;不只是局限于它的文字叙述&#xff0c;最好是能够动手实操一下&#xff0c;学会安装和使用的…

11--Gradle进阶 - Gradle任务的定义方式、指定任务的属性

11--Gradle进阶 - Gradle任务的定义方式、指定任务的属性 前言 在前面的篇章中&#xff0c;我们写了不少 task 任务&#xff0c;但是任务完整的定义方式&#xff0c;指定哪些任务属性 没有一个归纳的总结。 本篇章我们来熟悉一下。 任务定义方式 任务定义方式&#xff0c;总体分…

【机器学习】【期末复习】有关机器学习的计算题可供期末复习参考(带本人手写解答与思考)

本文为学校课程《机器学习》的期末复习材料&#xff0c;主要是关于一些机器学习模型的计算题的解答过程。 题目 构造平衡 KD 树ID3 与 C4.5 算法构建决策树模型朴素贝叶斯SVM求最大间隔分离超平面和分类决策函数EM算法K-means聚类adaboost计算概率图模型反向传播 构造平衡 KD 树…

学习adaboost(四,最后一次迭代,c#实现)

犯错3的3个弱分类就剩一个了&#xff0c;即x<8.5,标签1&#xff0c;else&#xff0c;标签-1。如果还搞不定&#xff0c;就得启用犯错4的分类器了&#xff0c;我们这一次是第三次迭代&#xff0c;和第二次没差别&#xff0c;我们看一下数据更新情况&#xff0c;希望是最后一次…

【Rust日报】2023-06-26 Rust 编写的 ChatGPT桌面应用

Rust 编写的 ChatGPT桌面应用 这是一个非官方的免费 ChatGPT 桌面应用, Rust 编写. 支持 Windows, Mac 和 Linux. 目前 38.3k ⭐️. github地址: https://github.com/lencx/ChatGPT 使用 github action 发布多平台的 rust 二进制程序 这篇文章是关于如何使用 GitHub Actions 进…

深蓝学院C++基础与深度解析笔记 第 7 章 深入 IO

1. IOStream 概述&#xff08;I&#xff1a;输入&#xff0c;O&#xff1a;输出&#xff09; ●IOStream 采用流式 I/O 而非记录 I/O (类似于数据库)&#xff0c;但可以在此基础上引入结构信息 ● 所处理的两个主要问题&#xff1a; – 表示形式的变化&#xff1a;使用格式化…

机器学习笔记 - 基于TensorRT或CUDA推理第一次速度慢的解决方案参考

一、简述 不管是基于CUDA还是基于TensorRT进行模型推理,都是分三个阶段,将数据从内存拷贝到显存,进行推理,将推理结果从显存拷贝到内存。 关于TensorRT推理,可以参考之前的博客。 机器学习笔记 - windows基于TensorRT的UNet推理部署_坐望云起的博客-CSDN博客NVIDIA Tenso…

linux sshd 病毒清理

原因&#xff1a;开启了flink web submit 具体原因不清楚&#xff0c;三个flink集群&#xff0c;只要开了这个就中毒 参考&#xff1a;解决linux中挖矿病毒 Linux系统常见的病毒介绍&#xff08;附解决方案&#xff09; 1、清理定时任务 修改cron 文件时 可能会存在被锁不允…

Cartographer自定义lua参数的方法

Cartographer中, 配置参数大多数都是从lua文件中得到的, 不是像其他的开源框架大多使用xml等文件进行参数配置. 假如我们要配置一个名字是rotation_condition的配置参数在pose_graph_2d.cc中, 想要使用方法为 options_.translation_condition()配置步骤如下: 1. 修改proto文件…