【操作系统】Linux操作系统中命令行参数与环境变量

news2024/11/28 8:32:38

本篇要分享的内容关于Linux新操作系统中命令行参数。

命令行参数本质上还是作为以后的环境变量的基础来学习的,所以在接触更高难度的内容之前先学习基础。

以下为本篇目录

目录

1.main函数的参数?

2.命令行解释器意义

3.环境变量

3.1.PATH环境变量 

3.2.PWD环境变量

3.3. root和普通用户的家目录

3.4更多环境变量

4.获取环境变量

5.环境变量的简单应用


1.main函数的参数?

我们学习的main函数是否能传参呢?

在我们之前学习C语言包括我们现在所学习的C++,main函数都是不传参的

#include<stdio.h>

int main()
{
        printf("hello world");
        return 0;
}

既然main函数也是函数,那么main函数也是要被调用的

被谁调用我们以后再说

今天这里要说的是main函数也可以是有参数的。

#include<stdio.h>

int main(int argc,char *argv[])
{
        printf("hello world\n");
        return 0;
}

可以看到上面代码中main函数增加了两个参数

int argc,char *agev[]

这在我们语言的参数中是很少用到的,是因为我们在之前的语言的学习中的代码较为简单,用不上mian函数中的参数。

现在我们要知道,这样的参数叫做命令行参数

第一个参数 int argc 虽然我们不明白它的意思,但是他是一个int类型的数据,和数字有关

第二个参数 char *argv[] 单纯站在我们不考虑函数时,他是一个单纯的指针数组,这个数组中存放的都是一个个char*

至于两个函数的意思我们观察下面C语言的代码

#include<stdio.h>

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

1.既然argc为int类型,我们不妨使用参数中的argc来作为for循环的上限;

2.并且我们知道在C语言中是没有字符串类型的数据的,C语言中的字符串类型的数据只能是char类型的字符数组,所以我们不妨使用通过遍历将argv中的元素内容打印出来

下面我们将代码运行起来

可以看到对应上面的代码,argc为0,argv对应输出的字符串为./myproc

下面我们继续在命令行中输入-a

可以看到输出多了一行,并且argc为1,argv数组中的字符串也变成了-a

那我们不妨继续在命令行输入命令并输出

可以看到他都可以统计出我我们在命令行中输入的内容并输出。

到现在为止,我们需要与之前的代码进行对比

不难看出main函数中的argc就是命令行中以空格结尾的,输入的多少串字符串。

可以看到在最后一次的输入中我们输入了五个字符串,并且以空格结尾,所以argc就为5。

在理解argv这个指针数组时,首先我们要先将我们在命令行中输入的数看作为一整个大的字符串

(大字符串)。

同时我们以空格作为分隔符,把小的字符串化作一小个区域

(每个黄色框是一小个区域)

这里一整个大字符串就被分为了5个子串。

那么在argc的指针数组中呢他会将每个地址都记录下每一个字符串串的首地址

(注意每个指针指向的时字符串的首地址)

但是这个指针数组最后必须要流出来一个空间来指向NULL,以NULL来结尾 。

在我们了解完这些参数的意义之后,就需要来研究这些代码是由谁来做的,怎么做的,因为我们在使用命令行时从来都没有做过这些工作。

因为这些工作都是操作系统,自动帮我们完成的。

也就是说我们在一命令行启动一个程序的时候,我们会以空格作为分隔符(或者理解为\0), shell或者操作系统会自动将我们输入的字符串打散,统计argc的个数,传参给我们的main函数,并且在系统中生成argv指针数组的表并传给我们,所以我们才能看到上面输出的内容。

2.命令行解释器意义

这里打算模拟实现一个计算器来理解命令行解释器的原理

我的设计思路是输入一行字符串,通过分隔符将字符串分为四个部分的内容

第一个被分割内容:./myproc表示我所要运行的程序的名称

第二个被分割内容:add表示我所要进行的是加法运算

第三个被分割内容:1表示加数

第四个被分割内容:2表示第二个加数

以上是我的测试输入,有四个部分的内容,那么我的模拟计算器的代码如下

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

        if(argc!=4)
        {
                printf("Use error\nUsage: %s op[add|sub|mul|div] d1 d2\n",argv[0]);
                return 1;
        }
        int x=atoi(argv[2]);
        int y=atoi(argv[3]);

        int result=0;
         if(strcmp(argv[1],"add")==0)
        {
                result=x+y;
                printf("%d+%d=%d\n",x,y,result);
        }

        else if(strcmp(argv[1],"sub")==0)
        {
                result=x-y;
                printf("%d+%d=%d\n",x,y,result);
        }

        else if(strcmp(argv[1],"sub")==0)
        {
                result=x-y;
                printf("%d-%d=%d\n",x,y,result);
        }

        else if(strcmp(argv[1],"mul")==0)
        {
                result=x*y;
                printf("%d*%d=%d\n",x,y,result);
        }

        else if(strcmp(argv[1],"div")==0)
        {
                if(0==y) printf("%d/%d=error! div zero\n");
                printf("%d/%d=%d\n",x,y,x/y);
        }
        else
        {

                printf("Use error\n");
        }
}

模拟计算器的代码逻辑也都非常简单这里就不细说了,还可以有更简单的写法,我们主要的问题放在命令行解释器中。

完成这样一个计算器之后我们就可以实现各种运算

包括我们之前讲到的 ls 命令 ,它后面也可以根很多的命令

我们的touch命令用来创建文件,后面也可以加上需要执行的内容

 

可以看到我们只执行了touch命令他告诉我们使用的方法不对,使用touch --help查看更多信息

我们使用touch --help就可以得到touch的使用方法 

 可以得出结论:我们第一个输入的总是我们想要执行的程序,再往后输入的都是字符串,通过分隔符分开,以命令行参数的形式传递给main函数中的两个参数,再通过系统内代码的识别来达到同一个程序实现不同的功能。

3.环境变量

3.1.PATH环境变量 

当我们再命令行输入指令的时候,指令就是程序的名称,命令行解释器会帮我们执行我们的程序,像我们平时都会使用的 ls、ll、pwd、who等等指令,他们都可以理解为程序。

但是这些程序都不需要我们额外的输入 ./ 去执行,我们在运行自己的代码时需要手动输入 ./ 才能运行我们的程序,那这些原因就和环境变量的配置有关。

在了解环境变量之前我们需要知道,需要执行一个命令,必须先要找到对应的可执行程序。

比如我想输ls展示我的当前文件的内容,但是我输成了la

命令行解释器找不到对应的可执行程序。

这也就是为什么我们执行我们自己编写的程序的时候需要加上 ./

因为 ./中的  .  符号代表着当前路径

我们之前所学的各种命令都存放在  /usr/bin目录中,所以我们根据程序的目录输入命令也是可以的

可以看到两种ls的 结果都是一样的。

 像这种可以直接执行的命令它们有默认的搜索路径。

在Linux系统当中存在环境变量,它会直接记录我们可执行程序的搜索路径,这个环境变量就叫做:PATH

环境变量名叫做PATH,其对应的内容我们可以根据echo $PATH指令来查看环境变量的内容

可以看到其中有很多的冒号(:),那么这些冒号在这里作用就是分隔符,将一个个搜索路径分成一个个字串,所以当我们执行命令时,会在上面图中的搜索路径中,以冒号作为分隔符,一个一个的按照顺序去搜索我们当前所要执行的命令。

所以和上面的ls连接起来

因为ls命令在上图中的文件路径中,所以我们输入ls回车键,它便可以直接运行。

它不能执行myproc指令,就是因为myproc没有存在系统的环境变量中,也就是搜索路径中,所以我们的程序时执行不了的。

那我们想要直接执行我们的程序应该怎么做呢?

首先pwd查看当前所在位置,只要把当前所在的位置,添加到环境变量的搜索目录中即可。

PATH=$PATH:  追加搜索路径

可以看到我们使用上面的方法将当前路径添加到了环境变量的搜索路径当中。

所以我们在执行我们自己写的代码时就可以直接运行。

所以我们学习java时安装的 java解释器、java编译器或者Python解释器等等在Windows系统中默认的环境变量是找不到的,所以我们需要将这些软件添加到环境变量即可。

同样的如果我们需要删除一些搜索路径我们只需先查看当前的路径,选择需要的路径复制,将之前的路径覆盖即可

PATH= 修改的路径

可以看到我们祛除了自己编写代码的文件路径,所以不能再直接运行我们的代码。

3.2.PWD环境变量

当我们使用pwd来查看自己当前所在的位置时,pwd是如何知道我们的位置呢?

在我们的系统当中也存在了一个环境变量叫做PWD

PWD是当前对应的bash专门记录当前目录的一个环境变量

也就是说pwd执行的命令就是打印环境变量PWD中的内容

3.3. root和普通用户的家目录

当我们使用自己的机器时和账号时,或者使用root的时候,我们pwd观察自己所在的位置,

你会发现root和我们自己所使用的目录是不同的。

我们每个用户对应的Linux系统中都有不同的家目录,root账号所对应的家目录就是/root,我们普通用户所对应的家目录就在/home下。

那为什么会root和普通用户所在家目录不同呢?

首先要说的是在我们的系统中有一个环境变量,它比我们使用用户登录之前准备的还要早。

这个环境变量会默认识别出我们登录的身份(root或普通用户)

识别之后会根据相应的身份配置环境变量     

可以看到这里的HOME同业也是环境变量名,echo $HOME可以查看对应的环境变量的内容。

 也就是说HOMO变量中存放的就是我们登录之前系统识别我们身份后的所配置的环境变量,也就是路径;

在登陆前,系统只需执行 

cd $HOME

用户即可达所以对应的配置的路径中。

所以按照登录的顺序我们可以分为以下几个部分

1.输入用户名和密码

2.认证

3.形成环境变量(包括PWD,PATH,HOME等)

4.根据用户名初始化root或普通用户

5.cd $HOME

3.4更多环境变量

像如上所说的环境变量在系统中还存在许多,我们在命令行中输入

env

即可查看更多系统中的环境变量

 例如HOSTNAME

,这个变量是指主机名。

,这里的HOME变量我们也验证过。

,这里的变量名指的是最多可以记录多少条指令。

,USER指的就是我们当前客户端使用的用户。

这里的LS _COLORS指的是使用ls输出的字体的颜色。

更多的环境变量不过多赘述。

通过以上内容呢,我们知道系统中有很多环境变量,他们都有自己的 特殊用途,用来完成特定的系统功能。 

4.获取环境变量

我们使用man getenv命令查看手册

可以看到getenv的使用方法,它的参数就是我上面所列举出来的环境变量名,返回值为char,无疑返回的是环境变量的内容。

我们使用getenv调用PATH就可以看到PATH的内容

getenv中只要是一个环境变量名,都可以得到其对应的内容。

比如上面讨论到的"USER"变量

我们对代码修改 

可以看到同样可以得到USER环境变量的内容

5.环境变量的简单应用

在环境变量的学习中我们可能会遇到如下情景:

如果我们只想将我们的代码交给root来运行,其他的普通用户没有资格和权限来运行我的程序

我们需要做身份认证,只允许root来执行

代码如下

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
        char *who=getenv("USER");
        if(strcmp(who,"root")!=0)
        {
                printf("%s,非法用户访问!\n",who);
                return 1;
        }

        printf("you can do");
        return 0;
}

 

首先查看我们的用户名

然后我们执行这个文件

可以看到我们无法执行。

我们将身份切换到root用户来执行我们的代码

可以看到代码顺利执行了

两者执行结果的不同.

以上就是对环境变量的简单理解和简单的使用场景的介绍,本人水平有限,有误之处请指出批评,如果对您有所帮助还请三连支持,感谢您的阅读。

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

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

相关文章

手把手教会你--渗透实战--Hack The Box-Starting Point-Meow--持续更新

有什么问题&#xff0c;请尽情问博主&#xff0c;QQ群796141573 前言 前言 请务必跟着博主复现一遍 参考&#xff1a; Hack The Box-Starting Point-Meow

工业级 S25HS01GTDPBHV030 NOR闪存,L9305EP汽车级驱动器IC,LMK03318RHSR时钟发生器,PLL(中文资料)

一、工业级 S25HS01GTDPBHV030 Semper™ NOR闪存 S25HS01GT SEMPER™ NOR Flash闪存系列是英飞凌高性能、安全而可靠的 NOR Flash解决方案。 它集成了适用于汽车、工业、通信等广泛应用的关键安全功能。 凭借 SEMPER™ NOR Flash闪存&#xff0c;英飞凌推出了业界首款符合 ASI…

设计模式—接口隔离原则(ISP)

1.背景 2002 年罗伯特C.马丁给“接口隔离原则”的定义是&#xff1a;客户端不应该被迫依赖于它不使用的方法&#xff08;Clients should not be forced to depend on methods they do not use&#xff09;。该原则还有另外一个定义&#xff1a;一个类对另一个类的依赖应该建立…

C#学习-9课时

P11 IF判断(上) P11 IF判断(中 ) bool→true or false&#xff1b; 为&#xff1a;变量赋值 为&#xff1a;等于(判断) !为&#xff1a;≠ 优先级&#xff1a;大于 using System; using System.Collections.Generic; using System.Linq; using System.Text; usin…

USB总线-Linux内核USB3.0 Hub驱动分析(十四)

1.概述 USB Hub提供了连接USB主机和USB设备的电气接口。USB Hub拥有一个上行口&#xff0c;至少一个下行口&#xff0c;上行口连接上一级的Hub的下行口或者USB主机&#xff0c;连接主机的为Root Hub&#xff0c;下行口连接下一级Hub的上行口或者USB设备。经过Hub的扩展&#x…

Linux7安装mysql数据库以及navicat远程连接mysql

1.下载地址&#xff1a;MySQL :: Download MySQL Community Server 2.创建mysql目录将压缩包上传到该目录 mkdir /opt/mysql cd /opt/mysql3.解压压缩包 gzip mysql-8.1.0-1.el7.x86_64.rpm-bundle.tar tar -zxvf mysql-8.1.0-1.el7.x86_64.rpm-bundle.tar.gz 4.前置检查 ch…

【算法】装备合成(二分)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 牛牛有x件材料a和y件材料b&#xff0c;用2件材料a和3件材料b可以合成一件装备&#xff0c;用4件材料a和1件材料b也可以合成一件装备。牛牛想要最大化合成的装备的数量&#xff0c;于是…

opencv-利用DeepLabV3+模型进行图像分割去除输入图像的背景

分离图像中的人物和背景通常需要一些先进的图像分割技术。GrabCut是一种常见的方法&#xff0c;但是对于更复杂的场景&#xff0c;可能需要使用深度学习模型。以下是使用深度学习模型&#xff08;如人像分割模型&#xff09;的示例代码&#xff1a; #导入相关的库 import cv2 …

什么是网络安全 ?

网络安全已成为我们生活的数字时代最重要的话题之一。随着连接设备数量的增加、互联网的普及和在线数据的指数级增长&#xff0c;网络攻击的风险呈指数级增长。 但网络安全是什么意思&#xff1f; 简而言之&#xff0c;网络安全是一组旨在保护网络、设备和数据免受网络攻击、…

Java多线程并发中部分不并发的问题

写Java实验发现个有意思的问题 三个线程&#xff0c;一个线程打印字符a&#xff0c;一个线程打印字符b&#xff0c;另一个线程打印数字&#xff0c;多次运行结果都是先打印混合输出的ab&#xff0c;完了再打印数字 有图有真相&#xff0c;我运行了10次 完整的代码是这个 clas…

计算机毕业设计 基于SpringBoot的智能停车场计费系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

二十七、微服务案例

目录 一、实现输入搜索功能 1、下载代码&#xff0c;在idea上打开 2、新建RequestParams类&#xff0c;用于接收解析请求 3、在启动类中加入客户端地址Bean&#xff0c;以便实现服务 4、编写搜索方法 5、新建返回分页结果类 6、实现搜索方法 7、编写控制类&#xff0c;…

下载网页内容成HTML文件

今天遇到了一个非常好用的、开源的网页下载插件: SingleFile&#xff0c;它可以将当前网页里的文字、图片、超链接等&#xff0c;合并成单一的.html文件&#xff0c;便于保存和浏览查看。下面介绍SingleFile的安装和使用。 1、下载SingleFile插件 SingleFile官网地址&#xff…

解决OSError: [Errno 28] No space left on device报错和搭建AIrtest无线配置手机集群

OSError: [Errno 28] No space left on device和搭建AIrtest无线配置手机集群 做手机无限集群控制时&#xff0c;常常遇到这种错误问题。表示您的设备上没有足够的可用磁盘空间来完成某个操作。我们遇到了还得重新开端口和输入ip&#xff0c;如果有几百台手机是不是中午就不吃…

数据里有{1,2,3,4,5,6,7,8,9},请随机打乱顺序,生成一个新的数组

问题&#xff1a;数据里有{1,2,3,4,5,6,7,8,9}&#xff0c;请随机打乱顺序&#xff0c;生成一个新的数组。 思路&#xff1a; 旧数组 nums&#xff0c;新数组 newNums 1、先创建一个新数组&#xff0c;用来存打乱数据后的元素&#xff0c;新旧数组的长度要一致 2、然后遍历数组…

OpenMMlab导出yolox模型并用onnxruntime和tensorrt推理

导出onnx文件 直接使用脚本 import torch from mmdet.apis import init_detector, inference_detectorconfig_file ./configs/yolox/yolox_tiny_8xb8-300e_coco.py checkpoint_file yolox_tiny_8x8_300e_coco_20211124_171234-b4047906.pth model init_detector(config_fi…

【算法】链表-20231127

这里写目录标题 一、面试题 02.02. 返回倒数第 k 个节点二、82. 删除排序链表中的重复元素 II三、141. 环形链表 一、面试题 02.02. 返回倒数第 k 个节点 提示 简单 130 相关企业 实现一种算法&#xff0c;找出单向链表中倒数第 k 个节点。返回该节点的值。 注意&#xff1a;本…

【Vue3+Vite】解决build后空白页的问题

目录 Hash 模式 HTML5 模式&#xff08;历史模式&#xff09; 配置Nginx 配置Spring Boot Hash 模式 build后空白页的问题可能是使用的是历史模式&#xff0c;因为Vue是一个单页的客户端应用&#xff0c;如果没有适当的服务器配置&#xff0c;访问会得到一个 404 错误…

通用电气调查网络攻击和数据盗窃指控

通用电气正在调查有关威胁行为者在网络攻击中破坏了公司开发环境并泄露据称被盗数据的指控。 通用电气 (GE) 是一家美国跨国公司&#xff0c;业务涉及电力、可再生能源和航空航天行业。 本月早些时候&#xff0c;一个名为 IntelBroker 的威胁行为者试图在黑客论坛上以 500 美…

linux复习笔记05(小滴课堂)

hell脚本与crontab定时器的运用 查看状态&#xff1a; 关闭服务&#xff1a; 开启服务&#xff1a; 重启服务&#xff1a; crontab定时器的使用&#xff1a; 我们可以看到没有任何任务。 编辑&#xff1a; 我们可以看到这个任务了。 删除所有任务&#xff1a; 这代表着每分钟…