Linux:命令行参数和环境变量

news2025/1/19 17:02:28

文章目录

  • 命令行参数
  • 环境变量
    • 环境变量的概念
    • 常见的环境变量
    • PATH
  • 环境变量表
  • 本地变量和环境变量
  • 命令分类

本篇主要解决以下问题:

  1. 什么是命令行参数
  2. 命令行参数有什么用
  3. 环境变量是什么
  4. 环境变量存在的意义

命令行参数

在学习C语言中,对于main函数当初的写法是没有任何参数的,但是实际上,main函数是可以有参数的,比如下面的写法:

#include <stdio.h>

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

因此这里将内容打印出来,看看这当中是什么内容

程序运行结果如图所示

[test@VM-16-11-centos 10_15]$ vim myproc.c
[test@VM-16-11-centos 10_15]$ make
gcc -o myproc myproc.c
[test@VM-16-11-centos 10_15]$ ./myproc 
0:./myproc

其实,命令行参数是用来支持各种指令级别的命令行选项的设置,例如这里的argv数组中,存储的字符串其实就是用户写的命令,而如果现在我在运行程序的时候带上选项

[test@VM-16-11-centos 10_15]$ ./myproc -a -b -c -d
0:./myproc
1:-a
2:-b
3:-c
4:-d

会发现打印的信息就是以用户写的指令开始进行分割,然后把信息放到数组中,从中其实看出,用户在运行程序的时候写的命令或者是带的选项都可以被main函数读取并且传参,函数体内部就可以利用这个机制实现不同的选项带来的结果

比如,Linux中有ls命令,用来查看文件夹中的内容,如果使用的是ls -a或者是ls -l这些选项,就会产生不同的结果,实际上这样的结果也是通过这个原理,通过读取argv数组中的内容就可以实现各种目的

这里其实可以模拟实现一个touch命令:

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
	if (argc == 2)
	{
		if (strcmp(argv[0], "./myproc") == 0)
		{
			FILE* pf = fopen(argv[1], "w");
			if (pf == NULL)
			{
				perror("fopen fail\n");
				return 1;
			}
			fclose(pf);
		}
        else  
        {
            printf("commend error,you should use ./myproc [name]\n");
        }
	}
	else
	{
		printf("commend error,you should use ./myproc [name]\n");
	}
	return 0;
}

运行结果如下所示:

[test@VM-16-11-centos 10_15]$ ./myproc test.txt
[test@VM-16-11-centos 10_15]$ ll
total 20
-rw-rw-r-- 1 test test   64 Oct 15 15:36 Makefile
-rwxrwxr-x 1 test test 8568 Oct 15 15:57 myproc
-rw-rw-r-- 1 test test  602 Oct 15 15:57 myproc.c
-rw-rw-r-- 1 test test    0 Oct 15 15:57 test.txt

这样就模拟实现了一个touch指令,只不过现在还有一个问题,在实际使用touch指令的时候,我并不需要带前面的这个./,而是直接可以运行,那么为什么呢?

这就涉及到了环境变量的问题:

环境变量

首先,不管是在什么系统什么环境中,要执行一个命令,必须要找到相应的可执行程序,这是一定的,那么由此可以引出环境变量的概念:

环境变量的概念

  • 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找
  • 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性

常见的环境变量

  1. PATH:指定命令的搜索途径
  2. HOME:指定用户的主工作目录
  3. SHELL:当前Shell,一般是/bin/bash

那么现在查看touch命令的位置

[test@VM-16-11-centos 10_15]$ which touch
/usr/bin/touch

从中可以看出,touch命令确实是被放在了这个地方,而正是由于它被放在了这个文件夹内,因此在运行的时候会默认在这个路径下搜索运行,因此,如果我们把前面定义的myproc程序放到对应的目录下,那么当执行命令的时候,会优先到对应的目录下搜索,因此也就不需要指定是在当前路径,而是会选择去一个默认路径,如果基于这样的理论,就可以找到对应的内容了

[test@VM-16-11-centos 10_15]$ sudo mv myproc /usr/bin
[test@VM-16-11-centos 10_15]$ myproc test1.txt
[test@VM-16-11-centos 10_15]$ ll
total 8
-rw-rw-r-- 1 test test  64 Oct 15 15:36 Makefile
-rw-rw-r-- 1 test test 600 Oct 15 16:08 myproc.c
-rw-rw-r-- 1 test test   0 Oct 15 16:09 test1.txt
-rw-rw-r-- 1 test test   0 Oct 15 15:57 test.txt

从中可以看出,确实创建成功了,也就是说上面的理论是正确的

PATH

PATH路径中,存在的路径就是上面所说的默认搜索路径,如果我们能想办法让路径增加呢?也就是说,能否通过增加PATH中的值,就能达到在默认路径下搜索文件了,在Linux中存在一个export命令可以修改PATH路径,下面来进行执行

[test@VM-16-11-centos 10_15]$ export PATH=$PATH:/home/test/10_15
[test@VM-16-11-centos 10_15]$ myproc test1.txt
[test@VM-16-11-centos 10_15]$ ll
total 20
-rw-rw-r-- 1 test test   64 Oct 15 15:36 Makefile
-rwxrwxr-x 1 test test 8568 Oct 15 16:19 myproc
-rw-rw-r-- 1 test test  600 Oct 15 16:08 myproc.c
-rw-rw-r-- 1 test test    0 Oct 15 16:21 test1.txt

从中可以看出,已经成功的将PATH路径添加到这里了,于是在程序的默认搜索路径中就多了/home/test/10_15路径,bash会在这个路径下进行搜索执行的命令

但是同时有一个问题,当退出Linux机器重新访问后,PATH文件中的路径又恢复成了原来的信息文件,综上可以总结出一些信息:

Linux机器在登陆的时候会发生什么?

  1. 输入用户名和密码
  2. 进行认证
  3. 形成环境变量,比如PATHPWDHOME这些
  4. 根据用户名进行一定的初始化
  5. cd ¥HOME

这样,就可以根据不同的用户进入不同的目录中,实现不同的权限级别的信息了

环境变量表

在引入环境变量表的概念前,先看环境变量

和环境变量相关的命令:

  1. echo: 显示某个环境变量值
  2. export: 设置一个新的环境变量
  3. env: 显示所有环境变量
  4. unset: 清除环境变量
  5. set: 显示本地定义的shell变量和环境变量

在这里插入图片描述
上图展示了系统中的环境变量,实际上在main函数的参数中,是有第三个参数的,而这个参数提供的就是环境变量表,也就是说,系统在启动程序的时候,是可以选择给main函数进程提供两张表的:

  1. 命令行参数表
  2. 环境变量表

下面做实验来证明环境变量表的存在性:

#include <stdio.h>

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

在这里插入图片描述
此时运行出的结果和前面基本相同,从中也印证了前面说的原理,在进程启动的时候,系统会提供两个表供使用

思考

命令行启动的进程都是shell/bash的子进程,这是前面进行进程学习的时候知道的,但是问题在于子进程的命令行参数和环境变量是从哪里来的?答案是父进程来的,那么父进程的环境变量信息又是从哪里来的呢?

此时要和前面的内容进行一些联系,为什么每一次重新登陆,都会为用户形成新的bash解释器,并且新的bash解释器会形成自己的环境变量表信息呢?这是由于它从配置文件中读取到了这些信息

由此可以得出一个结论:环境变量信息是以脚本配置文件的形式所存在的

每一次登陆的时候,bash进程会从一个叫做.bash_profile文件中读取内容,由此为bash进程创建一张环境变量表信息,由此bash在创建其他进程的时候,就可以传递环境变量信息了

查看环境变量

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

本地变量和环境变量

上面最后演示了环境变量的读取文件,那么这里引入了一个新的概念叫做本地变量,那么本地变量应该如何进行理解?

直接用实验来论证:

首先创建一个本地变量:

[test@VM-16-11-centos ~]$ MYENV="hello"
[test@VM-16-11-centos ~]$ echo $MYENV
hello

此时创建出的是一个本地变量,但是本地变量并没有被放到环境变量中,因此在环境变量中也是搜索不到这个本地变量的:

[test@VM-16-11-centos ~]$ env | grep MYENV
# 无输出结果

此时需要用一个命令:export->可以将本地命令转到环境变量中去

[test@VM-16-11-centos ~]$ export MYENV
[test@VM-16-11-centos ~]$ env | grep MYENV
MYENV=hello

此时,在环境变量中就找到了这个配置文件,那么在main函数中是否会存在呢?

[test@VM-16-11-centos 10_18]$ ./myproc |grep MYENV
13:MYENV=hello

也找到了这个变量,就进一步的论证了,环境变量表是由bash传递给子进程的

现在重启Linux机器:

# 找不到内容了
[test@VM-16-11-centos ~]$ env | grep MYENV
# 运行结果也找不到对应的内容
[test@VM-16-11-centos ~]$ ~/10_18/myproc | grep MYENV

这是由于,在登陆Linux服务器后,会根据配置文件中的信息对bash进行初始化,而此时并没有进行初始化信息,因此就需要对配置文件进行一些修改:

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

# 增加配置信息
MYENV=hello  
export MYENV  

export PATH

此时继续重新启动

[test@VM-16-11-centos ~]$ env | grep MYENV
MYENV=hello
[test@VM-16-11-centos ~]$ ~/10_18/myproc | grep MYENV
12:MYENV=hello

找到了对应的内容,由此引出本地变量和环境变量:

**本地变量:**只在bash进程内部有效,不会被子进程继承下去
**环境变量:**通过让所有子进程继承的方式,实现自身的全局性

由此得出一个结论:环境变量是具有全局性的

命令分类

看下面的实验:

# 将PATH变量设置为空
[test@VM-16-11-centos ~]$ export PATH=""
# 以下命令均不能使用
[test@VM-16-11-centos ~]$ ll
-bash: ls: No such file or directory
[test@VM-16-11-centos ~]$ touch
-bash: touch: No such file or directory
[test@VM-16-11-centos ~]$ mkdir
-bash: mkdir: No such file or directory
# pwd仍然可以使用
[test@VM-16-11-centos ~]$ pwd
/home/test

为什么呢?

Linux中的命令分类:

  1. 常规命令:shell通过fork让子进程执行的
  2. 内建命令:shell命令行的一个函数,可以直接读取shell内部定义的本地变量

而在上面的测试中,像lsmkdir这样的命令,都是shell通过fork创建子进程来执行的,而这里的PATH路径已经被用户破坏了,因此找不到搜索的路径,因此找不见是当然的事,但是为什么pwd可以找到?这是由于pwd这样的命令是内建命令,这是shell命令行的一个函数,可以直接读取shell内部的本地变量,因此就可以找到对应的值进行输出了

本篇是关于命令行参数和环境变量的,要清楚环境变量的组织形式:

在这里插入图片描述
会提供一个environ指针,这个指针会指向一张环境表,环境表是一个字符指针数组,每一个指针都会有一个字符串

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

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

相关文章

Spring framework Day 23:容器事件

前言 容器事件是 Spring Framework 中的一个重要概念&#xff0c;它提供了一种机制&#xff0c;使我们能够更好地了解和响应 Spring 容器中发生的各种事件。通过容器事件&#xff0c;我们可以在特定的时间点监听和处理容器中的各种状态变化、操作和事件触发&#xff0c;以实现…

【网络编程】多路转接之select、poll、epoll

目录 一、如何进行高效的IO 以read/recv为例 二、五种IO模型 三、常见的高级IO 四、非阻塞IO 1、recv和send自带的非阻塞IO 2、可以将文件描述符设为非阻塞 2.1open自带的非阻塞IO 2.2通过fcntl函数将一个文件描述符设置为非阻塞 2.3非阻塞IO的返回值判定 三、多路转…

网络安全(黑客)自学方向

每年报考网络安全专业的人数很多&#xff0c;但不少同学听说千万别学网络安全&#xff0c;害怕网络安全专业很难就业。下面就带大家深入了解一下网络安全专业毕业后可以干什么&#xff0c;包括网络安全专业的就业前景和方向等。 随着信息化时代的到来&#xff0c;网络安全行业…

Intellij IDEA 运行时报 Command line is too long

文章目录 前言解决方法2020.3 之前的版本2020.3 以及之后版本 前言 有时候使用Intellij IDE 使用项目时&#xff0c;会出现“Command line is too long” 错误&#xff0c;查了很多资料才找到解决方案。为解决该错误颇费周折&#xff0c;写下此文让同道中人少走弯路。 解决方法…

ROL,PIT,YAW

简言之&#xff0c; roll是旋转角&#xff0c;是“翻滚”。绕X轴旋转,ROL pitch是俯仰角&#xff0c;是“点头“。绕Y轴旋转,PIT yaw是偏航角&#xff0c;是‘摇头“。绕Z轴旋转,YAW

软考考试时间已出!采用连考形式!

2023年下半年计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试批次安排已出&#xff01;下面是具体的考试安排。 通知原文如下&#xff1a;↓↓↓ 按照《2023年下半年计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试有关工作调整的通告》&#x…

代码随想录算法训练营第二十六天 | LeetCode 39. 组合总和、40. 组合总和 II、131. 分割回文串

代码随想录算法训练营第二十六天 | LeetCode 39. 组合总和、40. 组合总和 II、131. 分割回文串 文章链接&#xff1a;组合总和 组合总和II 分割回文串 视频链接&#xff1a;组合总和 组合总和II 分割回文串 目录 代码随想录算法训练营第二十六天 …

leetcode 5

leetcode 5 题目是通过枚举字符串&#xff0c;然后判断是否子字符串满足回文。 引用传递和值传递相比&#xff0c;引用传递可以减少内存空间。提高代码运行效率。 https://www.cnblogs.com/yanlingyin/archive/2011/12/07/2278961.html

ZKP4.1 SNARKs via Interactive Proofs (Justin Thaler)

ZKP学习笔记 ZK-Learning MOOC课程笔记 Lecture 4: SNARKs via Interactive Proofs (Justin Thaler) 4.1 Interactive Proofs: Motivation and Model Interactive Proofs P solves problem, tells V the answer. Then they have a conversation.P’s goal: convince V the …

微信小程序一键获取位置

需求 有个表单需要一键获取对应位置 并显示出来效果如下&#xff1a; 点击一键获取获取对应位置 显示在 picker 默认选中 前端 代码如下: <view class"box_7 {{ showChange1? change-style: }}"><view class"box_11"><view class"…

Excel·VBA单元格区域数据对比差异标记颜色

之前的一篇博客《ExcelVBA单元格重复值标记颜色》&#xff0c;是对重复的整行标记颜色 而本文是按行对比2个单元格区域的数据&#xff0c;并对有差异的区域&#xff08;一个单元格区域有的&#xff0c;而另一个单元格区域没有的&#xff09;标记颜色&#xff0c;且只要存在任意…

杨辉三角按列求和

假设求杨辉三角这一列 我们考虑这个格子&#xff1a; 然后对其不断展开 综上&#xff1a; ∑ i 0 n ( i k ) ( n 1 k 1 ) \sum_{i0}^n\binom i k\binom {n1}{k1} i0∑n​(ki​)(k1n1​) ∑ i l r ( i k ) ( r 1 k 1 ) − ( l k 1 ) \sum_{il}^r\binom i k\binom{r1}{k…

Kafka存取原理与实现分析,打破面试难关

系列文章目录 上手第一关&#xff0c;手把手教你安装kafka与可视化工具kafka-eagle Kafka是什么&#xff0c;以及如何使用SpringBoot对接Kafka 架构必备能力——kafka的选型对比及应用场景 Kafka存取原理与实现分析&#xff0c;打破面试难关 系列文章目录一、主题与分区1. 模型…

每日一博 - Code如何被发布到生产环境

文章目录 概述Flow 概述 关于公司如何将代码发布到生产环境的是一个什么样的流程呢&#xff1f; 下面的图示展示了典型的工作流程。 步骤 1&#xff1a;流程始于产品负责人根据需求创建用户故事。步骤 2&#xff1a;开发团队从积压工作中挑选用户故事&#xff0c;将它们放入…

Flutter——最详细(CustomScrollView)使用教程

CustomScrollView简介 创建一个 [ScrollView]&#xff0c;该视图使用薄片创建自定义滚动效果。 [SliverList]&#xff0c;这是一个显示线性子项列表的银子列表。 [SliverFixedExtentList]&#xff0c;这是一种更高效的薄片&#xff0c;它显示沿滚动轴具有相同范围的子级的线性列…

pycharm操作git

pycharm操作git 之前用命令做的所有操作&#xff0c;使用pychrm点点就可以完成 克隆代码 上方工具栏Git ⇢ \dashrightarrow ⇢ Clone ⇢ \dashrightarrow ⇢ 填写地址&#xff08;http、ssh&#xff09; 提交到暂存区&#xff0c;提交到版本库&#xff0c;推送到远程 直接…

IOday7

A进程 #include <head.h> int main(int argc, const char *argv[]) {pid_t cpidfork();if(cpid>0)//父进程向管道文件2写{ int wfd;if((wfdopen("./myfifo2",O_WRONLY))-1){ERR_MSG("open");return -1;} char buf[128]"";while(1){bze…

ps或游戏提示d3dcompiler_47.dll缺失怎么修复?常见的修复方法总结

在当今这个信息化的时代&#xff0c;计算机已经成为我们生活和工作中不可或缺的一部分。然而&#xff0c;随着软件的不断更新和升级&#xff0c;一些技术问题也时常困扰着我们。其中&#xff0c;d3dcompiler_47.dll缺失就是一个常见的问题。本文将详细介绍五种修复方案&#xf…

CART(classification and regression tree)

基尼指数 在分类问题中&#xff0c;假设有K个类&#xff0c;样本点属于第k类的概率为pk&#xff0c;则概率分布的基尼指数定义为 Gini指数越小表示集合的纯度越高&#xff0c;反之&#xff0c;集合越不纯 CART CART分类树默认使用基尼指数选择最优特征 常见数构建算法&#…

从零实现FFmpeg6.0+ SDL2播放器

FFmpeg6.0开发环境搭建播放器代码框架分析解复用模块开发实现包队列和帧队列设计音视频解码线程实现SDL2音频声音输出SDL2视频画面渲染-YUV显示音视频同步-基于音频 地址: https://xxetb.xet.tech/s/3NWJGf