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

文章目录

  • 命令行参数
  • 环境变量
    • 环境变量的概念
    • 常见的环境变量
    • 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 programsPATH=$PATH:$HOME/.local/bin:$HOME/binexport 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 programsPATH=$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.rhkb.cn/news/168203.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(二)docker:建立oracle数据库mount startup

这章其实我想试一下startup部分做mount&#xff0c;因为前一章在建完数据库容器后&#xff0c;需要手动创建用户&#xff0c;授权&#xff0c;建表等&#xff0c;好像正好这部分可以放到startup里&#xff0c;在创建容器时直接做好&#xff1b;因为setup部分我实在没想出来能做…

订水商城H5实战教程-02系统登录

目录 1 创建数据源2 创建自定义应用3 创建全局变量4 实现登录功能5 控制弹窗是否显示6 最终的效果 上一篇我们分析了订水商城的功能&#xff0c;功能分析好了之后&#xff0c;就需要开发功能。用户登录商城的第一步就是进行登录&#xff0c;登录的时候需要同意用户协议&#xf…

SpringBoot AOP + Redis 延时双删功能实战

一、业务场景 在多线程并发情况下&#xff0c;假设有两个数据库修改请求&#xff0c;为保证数据库与redis的数据一致性&#xff0c;修改请求的实现中需要修改数据库后&#xff0c;级联修改Redis中的数据。 请求一&#xff1a;A修改数据库数据 B修改Redis数据 请求二&#xff…

修炼k8s+flink+hdfs+dlink(六:学习k8s-pod)

一&#xff1a;增&#xff08;创建&#xff09;。 直接进行创建。 kubectl run nginx --imagenginx使用yaml清单方式进行创建。 直接创建方式&#xff0c;并建立pod。 kubectl create deployment my-nginx-deployment --imagenginx:latest 先创建employment&#xff0c;不…

CSS页面基本布局

前提回顾 1. 超文本标记语言&#xff08;HTML&#xff09;是一种标记语言&#xff0c;用来结构化我们的网页内容并赋予内容含义&#xff1b; &#xff08;超文本标记语言&#xff08;英语&#xff1a;HyperText Markup Language /ˈhaɪpətekst ˈmɑːkʌp ˈlŋɡwɪdʒ /…

由浅到深 : Self-Attention (自注意力机制)

Self-Attention 看到下面的第一个saw是动词&#xff0c;第二个saw是名词。 因为第一个saw和第二个saw在形式上没有任何差别。如果任务是进行词性的判断&#xff0c;把上面的词直接输入给神经网络&#xff0c;那么它肯定不能够正确分析。 想要正确分析词性&#xff0c;那么该…

CRM自动化意味着什么?企业如何从中受益?

客户关系管理&#xff08;CRM&#xff09;软件不再仅仅适用于大公司或销售周期长的行业&#xff0c;它越来越成为各种规模企业的重要工具。 在日常工作中&#xff0c;当你陷入流程的所有细节时&#xff0c;可能会产生不必要的工作。因此&#xff0c;如果你想要CRM提供的组织和…

Redis的持久化策略:RDB与AOF(面试题详解)

文章来源&#xff1a;Redis持久化的两种方式&#xff1a;RDB与AOF&#xff08;详解&#xff09;&#xff0c;订正了一些错误 一、概述&#xff1a; RDB和AOF持久化的由来&#xff1f; 因为Redis中的数据是基于内存的&#xff0c;所以如果出现服务器断电或者服务器宕机&#xf…

数据结构堆详解

[TOC]堆详解 一&#xff0c;堆 1.1堆的概念 堆的性质&#xff1a; 堆中某个节点的值总是不大于或不小于其父节点的值&#xff1b; 堆总是一棵完全二叉树。 1.2堆的存储模式 我们前面的文章提到过&#xff0c;二叉树的两种存储模式&#xff0c;一个是顺序存储&#xff0c;一…

【Java集合类面试八】、 介绍一下HashMap底层的实现原理

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a; 介绍一下HashMap底层的…

华为OD技术面试-最短距离矩阵(动态规划、广度优先)

背景 记录2023-10-21 晚华为OD三面的手撕代码题&#xff0c;当时没做出来&#xff0c;给面试官说了我的想法&#xff0c;评价&#xff1a;解法复杂了&#xff0c;只是简单的动态规范 或 广度优先算法&#xff0c;事后找资料记录实现方式。 题目 腐烂的橘子 问题描述&#xff…

怎样找外企/远程的工作

“如果你既不想卷&#xff0c;又不想参与职场的勾心斗角&#xff0c;也不算行业大牛&#xff0c;还不愿意冒太高风险&#xff0c;那还有一种渠道&#xff0c;就是找海外公司的远程工作&#xff0c;比如我有几个程序员朋友&#xff0c;都是拿着硅谷动辄 20w 刀的薪水&#xff0c…

头脑风暴之约瑟夫环问题

一 问题的引入 约瑟夫问题的源头完全可以命名为“自杀游戏”。本着和谐友爱和追求本质的目的&#xff0c;可以把问题描述如下&#xff1a; 现有n个人围成一桌坐下&#xff0c;编号从1到n&#xff0c;从编号为1的人开始报数。报数也从1开始&#xff0c;报到m人离席&#xff0c…

重生奇迹mu宠物带来不一样的体验

重生奇迹mu宠物有什么作用&#xff1f; 全新版本中更是推出了各种宠物&#xff0c;在玩游戏时还可以带着宠物&#xff0c;一起疯狂的刷怪等等&#xff0c;可以为玩家带来非常不错的游戏体验&#xff0c;那么下面就来给大家说说各种宠物适合做什么事情。 1、强化恶魔适合刷怪 …

爱创科技携手洽洽食品,探索渠道数字化最优解!

坚果的下半场&#xff0c;是从吃到喝。 消费升级大潮下&#xff0c;健康养生理念逐渐深入人心。以“天然健康”为核心的食品新消费潮流正加速形成&#xff0c;一个个打着“美味与营养”黄金设定的品类风口正被不断创建&#xff0c;其中人气有增无减的当属植物基饮品。据相关报告…

HarmonyOS鸿蒙原生应用开发设计- HarmonyOS Sans 字体

HarmonyOS设计文档中&#xff0c;为大家提供了独特的字体&#xff0c;开发者可以根据需要直接引用。 开发者直接使用官方提供的字体内容&#xff0c;既可以符合HarmonyOS原生应用的开发上架运营规范&#xff0c;又可以防止使用别人的字体侵权意外情况等&#xff0c;减少自主创…

【Linux驱动】Linux设备树(二)—— 添加设备树节点

了解了设备树的基本语法以后&#xff0c;就可以试着自己手动添加一个节点了&#xff0c;添加完节点以后&#xff0c;需要重新编译生成 .dtb 文件&#xff0c;然后保存到uboot的加载目录下。 目录 1、查看绑定信息文档 2、添加设备树节点 3、编译设备树文件(.dtb) 4、替换设…

JAVA基础(JAVA SE)学习笔记(七)面向对象编程(进阶)

前言 1. 学习视频&#xff1a; 尚硅谷Java零基础全套视频教程(宋红康2023版&#xff0c;java入门自学必备)_哔哩哔哩_bilibili 2023最新Java学习路线 - 哔哩哔哩 第二阶段&#xff1a;Java面向对象编程 6.面向对象编程&#xff08;基础&#xff09; 7.面向对象编程&…

IP协议(下)

目录 一、IP分片 1.为什么需要IP分片 2.IP报头信息 二、分片的组装 1.接收方怎么知道一个报文被分片了 2.同一个报文的分片怎么全部识别出来的 3.报文如何排序&#xff0c;如何得知报文有没有收全 4.怎么将各分片正确组装 5.怎么确定合成的报文是正确的 6.总结 三、…