Linux命令行参数与环境变量

news2025/1/11 16:45:22

目录

命令行参数与环境变量

命令行参数

环境变量及其相关概念

环境变量的相关操作

环境变量的本质


命令行参数与环境变量

命令行参数

我们在使用一些Linux的一些指令时,会有意或无意的使用一些指令参数,例如:

ls -al
ps -ajx
gcc -o test.c proc -g
……

从本质上讲,Linux是用C语言写的,而Linux下的指令其实就是操作系统内置的一个个可执行程序,即Linux下的指令本质上都是用C语言写的可执行程序。那么这些指令参数的功能是如何实现的呢?我们在当时好像并没有想过。其实,这一切都与main函数的命令行参数有关。

在初学C语言时,我们有时会看到这种带参数main函数的写法:

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

但那时我们并不知道这些参数有什么用,表示什么含义,于是久而久之习惯了main函数不带参数的写法。但其实,argc和argv是当前进程的命令行参数,argc是一个int类型的变量,表示命令行终端传入的参数的个数,argv是一个指针数组,以char*的形式保存每一个命令终端传入的参数。其中,命令行参数的第一个内容默认是当前可执行程序的名称。下面就来证明上述内容:

首先我们有一个可执行程序 myproc,其源代码的main函数内容如下:

int main(int argc, char* argv[])                                                      
{                                                                                                                                                                                      
    for(int i = 0; i < argc; i++)                                      
    {                                                                  
        printf("argv[%d] = %s\n",i ,argv[i]);                                                                                                            
    }                                                                                 
    return 0;                                                                                    
}  

那么当我们以如下形式执行我们的可执行程序myproc

./myproc -l -x -s

那么对应的输出内容为:

argv[0] = ./myproc
argv[1] = -l
argv[2] = -x
argv[3] = -s

由此可见,我们是可以通过main函数的参数实现将外部参数传到可执行程序内部的。所以,Linux内置的指令参数(如ls -l等)就是通过命令行参数来实现的,即指令参数的本质就是命令行参数,这也就很好的呼应了"Linux下的指令本质上都是用C语言写的可执行程序"这句话了。

需要注意的是,main函数的三个命令行参数所在的位置是不能颠倒的,只能严格以

命令终端参数的个数(int argc) 
命令终端的参数内容(char* argv[]) 
环境变量的内容(char* env[])

的顺序书写。不过虽然命令行参数的顺序有严格规定,但是命令行参数的参数名是可以自定义修改的,不过为了统一性和规范性,一般不会选择修改。而至于main函数的第三个命令行参数是什么,后面的环境变量部分会讲到。

环境变量及其相关概念

环境变量的概念引入

大多数情况下,我们在运行自己编写的可执行程序的时候都要在前面加一个 "./" 以表明可执行程序的位置(不加会出现"command not found"之类的内容),那么我们为什么要加这个 "./" 呢?原因很简单,因为操作系统如果想要运行一个可执行程序就要找到这个可执行程序的位置,因此我们一般使用比较方便的相对地址 ".\"来指明我们可执行程序的位置。

值得一提的是,其实进程的相对地址本质上就是绝对地址,只不过Linux操作系统将当前目录的地址以链接文件的形式将其保存起来了:

详见 "进程标识符 - PID" 部分

可是,Linux内置的指令本质上也是可执行程序,那么为什么执行这些指令的时候不需要指定具体的路径位置呢?这就与一个叫做环境变量的东西有关了。

那么何为环境变量呢?环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。换言之,环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。例如Windows下的path环境变量,当要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还会到path中指定的路径去寻找。

那么Linux也是如此,我们的Linux内置指令确实是一个个的可执行程序,但至于为什么可以不用手动指定其路径位置,是因为Linux中有一个PATH环境变量,里面存储存着一个个路径(用冒号":"隔开),然后Linux每次在执行某些需要寻找某些内容的操作时(例如找一些可执行程序的位置),就会在逐个从这些路径中寻找对应的可执行程序文件,PATH变量的内容示例如下:

因为我们自定义的可执行程序基本上都不会在这些文件中,所以我们自定义的可执行程序一般需要手动指定文件路径的位置,而系统内置的指令对应的可执行程序肯定是设计好的,它们是一定会出现在PATH环境变量中的某个路径中的。

所以我们能知道,操作系统一般都会有一些环境变量,使用环境变量的目的在于执行某些操作时能够借助某些环境变量很便捷的完成(类似于用空间换时间)


包括上面提到的PATH环境变量,Linux中常见的环境变量有:

  • PATH : 命令的可搜索路径(一般是多个)。
  • HOME : 用户的主工作目录地址,即家目录的地址。
  • SHELL : 当前系统的shell是哪个,例如centos下的SHELL变量的通常为"/bin/bash"。
  • HOSTNAME:当前的主机名。
  • LOGNAME:当前的用户名。
  • HISTSIZE:可记录的历史命令的最大数量。
  • PWD:当前所在路径(pwd指令就是依赖的这个环境变量)。

本地变量和环境变量

  • 本地变量:本地变量是一种临时的变量,仅针对当前用户的当前进程生效,不会被子进程继承下去,定义格式为:"变量名=变量值",例如
local_val=local
  • 环境变量:环境变量是一种持续存在的变量,会对当前进程以及子进程生效。可以通过export将本地变量提升为环境变量,或者直接定义一个环境变量。

外部命令和内建命令

  • 外部命令:外部命令是一个独立的外部可执行程序,因为实用程序的功能通常都比较强大,程序量也相对较大,所以在系统加载时并不随系统一起被加载到内存中,而是保存在磁盘中,通常放在/bin,/usr/bin,/sbin,/usr/sbin……等目录下。当外部命令被调用时,本质就是调用了一个进程,此时Shell会创建一个子进程,这个子进程就是这个命令对应的进程。常见外部命令有:/bin/ls、vi、tee、tar等。
  • 内建命令:内部命令实际上是Shell程序的一部分,由 Shell 软件内部进行实现的命令,其中包含的是一些比较简单的linux系统命令,由shell程序识别并在shell程序内部完成运行,通常在linux系统加载运行时shell就被加载并驻留在系统内存中。内部命令嵌入在Shell程序中,并不单独以磁盘文件的形式存在于磁盘上,其执行速度比外部命令快。常见的内建命令有:exit,history,cd,echo,fg,cd、source、export、time等。

内容参考:Linux Shell 内部命令与外部命令 - 知乎 (zhihu.com)

环境变量的相关操作

首先,在编写C\C++时,可以通过如下三种方式来获取环境变量

  1. getenv函数,用于获取指定的环境变量内容

    用法示例:
    char* path = getenv("PATH");
    printf("PATH : %s\n",path);
    
    /* 运行结果如下
    PATH : /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/xiaoming/.local/bin:/home/xiaoming/bin
    */
  2. putenv函数,导入环境变量。参数只有一个char*,表示要导入的环境变量。默认放到环境变量表的最后。如果与系统环境变量冲突,那么就会发生覆盖,相对于修改操作。
    用法示例:
    putenv("MYENV=12345");
  3. 第三个命令行参数 —— char* env[]。env是一个指针数组,数组的最后一个元素是NULL。

    而数组中的内容为每一个环境变量和对应的内容,格式为"环境变量=环境变量的内容",例如:
    PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/xiaoming/.local/bin:/home/xiaoming/bin
    用法示例如下:
    int main(int argc, char* argv[], char* env[])
    {
        for(int i = 0; env[i] != NULL; i++)
        {
            printf("%s\n",env[i]);
        }
    
        return 0;
    }
    
  4. unistd.h头文件中的一个外部链接属性的全局变量char** environ,envrion本质上就是指向的env数组的内容,需要显示的用extern声明才能使用。需要注意的是,由于env数组中存储的是char*的内容,因此char** environ群殴事件哦就相当于(char*)*envrion,所以这里不使用数组指针而是二级指针并没错。用法示例如下:
    int main()
    {  
        extern char** environ;
        for(int i = 0; environ[i] != NULL; i++)
        {
             printf("%s\n",environ[i]);
        }
    
        return 0;
    }
    

其次,还可以在控制台下通过一些指令来获取环境变量

  1. echo直接打印环境变量。环境变量本质上就是bash下的一个变量,因此可以直接用echo指令输出环境变量的内容。用法示例如下:
    echo $PATH
    echo ${PATH}
  2. env指令,列出所有的环境变量。env指令可以列出当前环境下的所有环境变量,通常也配合gerp检索单个环境变量,用法示例如下:
    env
    env | grep PATH

最后,还有一些其它的相关指令

  1. export,修改环境变量或增加环境变量。export的使用格式如下:
    # 将VAR环境变量的值设为val,如果VAR存在就是修改环境变量,不存在就是新增环境变量
    export VAR=val #注意,没有空格
    
    # 将VAR变量提升为环境变量(前提是VAR已存在)
    export VAR

    参考:export命令 - Linux命令大全(手册) (linuxcool.com)

  2. set,查看所有变量,包括本地变量和环境变量,至于何为本地变量,后面会说。

  3. unset,删除本地变量或环境变量。用法示例:

    # 删除myval变量
    unset myval
    

环境变量的本质

书接上回,Linux内置的指令所对应的可执行程序不用指定路径位置,是因为PATH环境变量中存储了它们所在的目录地址。那么如果我们想要运行自定义的可执行文件时,通常有两种解决方案:一是把我们的可执行文件放在PATH环境变量中的某个目录下,二是将可执行文件所在的目录地址添加到PATH环境变量中。

因为环境变量本质上就是bash下的一个变量,因此可以直接使用bash脚本的语法对其进行读写操作,例如:

# 在PATH中新增一个路径,$PATH表示之前的变量值
# 之后的 ":new_path" 就是按照PATH环境变量的格式新增的路径
PATH=$PATH:new_path   

但是这种方式修改的环境变量只能在当前登录时使用,修改的是内存中的环境变量,一旦重新登入Linux时,环境变量都会被重置,即我们对其做的所有操作都会消失,环境变量又会回到原处。这是因为,操作系统创建的环境变量是根据一些配置文件创建的,所以如果想要永久增添或者删除某些环境变量,就需要对这些配置文件进行操作,其中Linux下和环境变量相关的配置文件有:

1、系统位置,/etc目录下的:bashrc、profile、environment,三个文件。

2、用户目录下的:.bashrc、.bash_profile,两个文件。

内容参考:Linux环境变量到底配置到那里?-CSDN博客

那么这是为什么呢?首先,在命令行下直接修改PATH变量时只适用于本次登录,这是因为此时修改的PATH是bash进程内部的环境变量(bash本质上也是一个进程),之后重新登陆操作系统时,都会给我们形成新的bash解释器,并且新的bash解释器会自动重新形成自己的环境变量信息,那么自然之前修改的就消失了。

也就是说,每次登陆操作系统时,操作系统都会根据环境变量的相关文件中的信息,来为我们的bash进程生成一张环境变量表信息。那么为什么bash下启动的进程也可以正常使用环境变量呢?这是因为环境变量是可以继承给子进程的。子进程在创建时会自动继承(复制与父进程相同的环境变量)父进程的环境变量等信息,而我们前面知道,bash进程可以说是所有命令行下启动的进程的父进程,所以在bash下启动的进程都会继承bash进程的这个环境变量表。

那么bash进程的环境变量表又是怎么来的呢?那肯定是继承自它的父进程,那么它父进程的环境变量也是继承自其父进程的(爷爷进程)……,那么我们能知道,其实这个环境变量表的信息最开始就是一个操作系统启动初期的一个进程读取了这个配置文件中的信息,此后的子进程等都会直接继承这个环境变量的信息表,所以其实环境变量的信息传递,就类似是一个树状的结构。也就是说,包括bash在内的操作系统中的所有进程,都会存储一张环境变量表。

所以其实系统在启动我们的程序时,都会为这个新的进程提供两张表:命令行参数表和环境变量表,它们都能被子进程所继承。那么命令行参数和环境变量是如何做到被子进程所继承的呢?这就涉及到的虚拟地址空间的内容了。大致原因就是,每个进程创建时,都会有命令行参数表和环境变量表,而子进程在创建时,会拷贝父进程大部分数据,包括进程PCB、页表等内容,这其中也包含了命令行参数表和环境变量表(内容参考:为什么子进程能继承父进程的环境变量)。

所以回过头来看,其实命令行参数和环境变量并不是因为可以通过main函数传参、系统调用等方式获取,而是本来就有命令行参数表和环境变量表,使得我们可以通过这些方式获取对应的命令行参数或者环境变量的内容。

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

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

相关文章

CVE-2024-38077 微软 RDP 漏洞修复 报错 不适用于你的计算机 解决方法

这一漏洞存在于Windows远程桌面许可管理服务&#xff08;RDL&#xff09;中&#xff0c;该服务被广泛部署于开启Windows远程桌面&#xff08;3389端口&#xff09;的服务器&#xff0c;用于管理远程桌面连接许可&#xff0c;也有文章认为该漏洞实际利用的是135端口。攻击者无需…

【大模型】多模态的原理简述

多模态的原理 多模态模型目前基本就是文生图、图生图、图生视频、文生视频这些&#xff0c;其底层逻辑其实还是先从生图片这一源头。因为毕竟视频也是若干帧的图片组成。 所以在生图片的这个环节上&#xff0c;我们把比较火的这个stablediffusion用的这个diffusion扩散模型理…

企业大数据治理管理平台解决方案(33页PPT)

方案介绍&#xff1a; 本解决方案旨在为企业提供一套从数据采集、存储、处理、分析到应用的全链条大数据治理管理平台。该平台通过集成先进的数据技术和管理理念&#xff0c;帮助企业实现数据的全生命周期管理&#xff0c;提升数据质量&#xff0c;降低数据风险&#xff0c;促…

PX4-Autopolite linux环境下源码编译中遇到的一些问题及相应解决办法

最近在做一个PX4飞控移植的项目&#xff0c;第一次接触到PX4源码&#xff0c;真的是感觉编译起来非常的麻烦&#xff0c;下面我将介绍几个新手比较容易踩坑的点。 &#xff08;我都踩了ㄒ-ㄒ&#xff09; 1.PX4源码要用git clone 从github上克隆来&#xff0c;千万不要直接在g…

谷粒商城实战笔记-170~172-缓存-SpringCache

文章目录 一&#xff0c;170-缓存-SpringCache-自定义缓存配置二&#xff0c;171-缓存-SpringCache-CacheEvict1&#xff0c;删除多个缓存2&#xff0c;删除一个缓存 三&#xff0c;172-缓存-SpringCache-原理与不足 一&#xff0c;170-缓存-SpringCache-自定义缓存配置 上一节…

中国对世界各国的进出口面板数据(2000-2022年)

中国作为全球最大的贸易国之一&#xff0c;其对各国的进出口数据不仅量级庞大&#xff0c;而且蕴含着丰富的经济信息与趋势动向&#xff0c;对于研究全球经济互动、国际贸易格局、产业链分布以及中国自身经济的发展策略具有一定价值。例如&#xff0c;近年来的数据表明&#xf…

对接的广告平台越多,APP广告变现的收益越高?

无论是游戏、社交、工具应用类APP还是泛娱乐类APP&#xff0c;流量变现的方式主要有广告、内购、订阅三种方式。其中&#xff0c;广告变现是门槛最低、适用最广的变现方式。 只要APP有流量&#xff0c;就可以进行广告变现&#xff0c;让APP的流量快速转化为商业价值。作为最常…

什么是张量

张量的基础概念 学习使用pytorc库进行深度学习网络搭建时&#xff0c;张量这个词总是不定时会出现。其实&#xff0c;Pytorch中的所有操作都是在张量的基础上进行的&#xff0c;今天就来了解张量到底是什么 由PyTorch官网官网介绍可知&#xff0c;一个Tensor是一个包含单一数据…

软件测试自学三个月,进了一家自研薪资11k,面试总结分享给大家

功能方面&#xff1a;问得最多的就是测试流程&#xff0c;测试计划包含哪些内容&#xff0c;公司人员配置&#xff0c;有bug开发认为不是 bug怎么处理&#xff0c;怎样才算是好的用例&#xff0c;测试用例设计方法&#xff08;等价类&#xff0c;边界值等概念方法&#xff09;&…

DVWA靶场配置相关问题解决

本文主要提到鄙人在DVWA配置过程中所遇到的问题&#xff0c;以及我的解决方式&#xff0c;希望会帮到大家&#xff01; 首先&#xff0c;我使用的是windows版本&#xff0c;运用的是小皮搭建&#xff0c;前期准备可参考&#xff1a;【靶场搭建】超级详细——DVWA靶场搭建&…

springboot美术馆管理系统--论文源码调试讲解

第2章 开发环境与技术 本章节对开发美术馆管理系统管理系统需要搭建的开发环境&#xff0c;还有美术馆管理系统管理系统开发中使用的编程技术等进行阐述。 2.1 技术路线 在美术馆管理系统中常用的技术方案如下所展示&#xff1a; 针对已有的购物中心&#xff0c;系统结构为B…

ChatGPT:智能聊天机器人微信开发实战

简介 ChatGPT近期以强大的对话和信息整合能力风靡全网&#xff0c;可以写代码、改论文、讲故事&#xff0c;几乎无所不能&#xff0c;这让人不禁有个大胆的想法&#xff0c;能否用他的对话模型把我们的微信打造成一个智能机器人&#xff0c;可以在与好友对话中给出意想不到的回…

微信分享朋友圈单页面设置

需求:用户在朋友圈打开分享的小程序页面&#xff0c;并不会真正打开小程序&#xff0c;而是进入一个“小程序单页模式”的页面,需要自定义单页面样式 第一步:先读官方文档 分享到朋友圈 | 微信开放文档 由官方文档可知,当进入单页面会返回一个场景值1154,判断如果是1154就展示…

利用腾讯云AI代码助手优化图书馆管理系统

引言 在当今信息爆炸的时代&#xff0c;软件开发已成为推动社会进步和科技发展的重要力量。随着项目规模的扩大和复杂性的提升&#xff0c;我们开发者在编程过程中面临着越来越多的挑战。代码编写的效率、准确性和规范性&#xff0c;直接关系到项目的成功与否。为了应对这些挑…

开机就能打?没那么玄乎!客观分析 “狂躁许可”漏洞(CVE-2024-38077)及其影响范围

一、事件背景 2024年7月9日&#xff0c;微软官方发布了一个针对“windows远程桌面授权服务远程代码执行漏洞”&#xff08;CVE-2024-38077&#xff09;的修复补丁包&#xff0c;起初并没有引起大家的警觉。今日在国外某网站上疑似漏洞的作者公开了该漏洞的“POC验证代码”。一…

无法判断编程器固件类型

按照简书上指导把小米路由器4C刷机了OpenWrt&#xff0c;玩个新鲜&#xff0c;看看都有什么功能&#xff0c;确实挺强大&#xff0c;能做很多事&#xff0c;但是不稳定&#xff0c;又想刷回去&#xff0c;结果卡在上传步骤&#xff0c;报错&#xff0c;提示“无法判断编程器固件…

解决 Kibana 中的 “Invalid character in header content” 错误

在使用 Kibana 进行数据可视化和分析的过程中&#xff0c;我们可能会遇到一些配置相关的问题。本文将介绍一个常见的错误&#xff1a;“Invalid character in header content”&#xff0c;并提供详细的解决步骤。 问题背景 当启动 Kibana 服务时&#xff0c;如果遇到以下错误…

【三维重建】Pixel-GS:三维高斯泼溅的像素感知的梯度密度控制(去除浮点,提升精度)

项目&#xff1a;https://pixelgs.github.io/ 标题&#xff1a;Pixel-GS: Density Control with Pixel-aware Gradient for 3D Gaussian Splatting 来源&#xff1a;香港大学&#xff1b;腾讯AI Lab 文章目录 摘要一、前言二、相关工作1.新视图合成2.基于点的辐射场3.Floater 的…

MFC系列-改变控件字体和颜色

【1】在资源管理器中&#xff0c;选择对话框&#xff0c;右键选择类向导&#xff0c;消息中选择WM_CTLCOLOR HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) {HBRUSH hbr CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);//if (nCtlColor CTLCOLOR_STATIC) …

Postgres 超时 (Timeout) 详解

原文地址 https://www.bytebase.com/blog/postgres-timeout/ PostgreSQL 提供各种超时 (Timeout) 设置&#xff0c;通过控制某些进程的持续时间来帮助管理和优化数据库操作。这些超时对于确保系统的稳定性和性能至关重要&#xff0c;尤其是在高流量或复杂查询的环境中。让我们…