深入学习Linux: 命令行参数与环境变量详解

文章目录

  • 1. 命令行参数
    • 1.1 main函数的参数
    • 1.2 命令行参数的作用
  • 2. 环境变量
    • 2.1 理解一个问题
    • 2.2 PATH环境变量
    • 2.3 其他环境变量
  • 3. C/C++代码与进程之间的关系
    • 3.1 用代码获取环境变量
      • 3.1.1 main函数最多有几个参数?
      • 3.1.2 shell外壳里的环境变量是哪里来的?
    • 3.2 获取环境变量的若干种方法
    • 3.3 环境变量、本地变量、内建命令
      • 3.3.1 创建自己的环境变量
    • 3.4 内建命令

1. 命令行参数

1.1 main函数的参数

main函数是可以有参数的。main函数的参数由bash和系统自动传递。命令行参数的本质是一个字符串,shell以空格为分割符号,切成了若干的子串。

细节一:命令行参数至少是1,argc>=1,argv[0]一定会有元素,指向的就是程序名。
细节二:选项是以空格分割的字符串,一个字符也是字符串。
细节三:argv的本质是一张表,元素由argc决定,argv[argc]是最后一个,且始终为NULL。

1.2 命令行参数的作用

为什么要有命令行参数?命令行参数的本质应用,是为了实现一个命令可以根据不同的选项,实现不同的子功能。也是Linux中所有命令选项功能的实现方式。问题:VS2022有没有命令行参数?有的。cat file.txtcat < file.txt如何打印出文件内容?本质是通过命令行参数,将文件打开,打开后读文件,打印内容。

2. 环境变量

2.1 理解一个问题

环境变量具有全局属性的根本原因是:环境变量可以被bash进程的子进程继承,所有在Linux下的子进程都会拥有对应的环境变量。

./的本质是相对路径,本质是告诉OS,用户要执行的bin,就在当前路径下。

2.2 PATH环境变量

Linux怎么知道我应该去哪一个路径下找可执行程序?除了去/usr/bin路径下去找,还会不会去其他路径下去找?Linux系统,会存在所谓的环境变量的东西。
PATH是该环境变量的变量名:

echo$PATH

以冒号为分割符的多串路径,告诉Linux系统,如果用户执行一个可执行文件,没有指明路径,去哪几个路径下去找?

PATH的本质是协助Linux进行指令查找的环境变量。

如何将路径配置到环境变量里?就可以执行的时候不带有./

PATH=[你的路径]

你这么写就直接覆盖了:

PATH=$PATH:[你想要添加的路径]

总结:
PATH:指定命令的搜索路径。
PATH环境变量是全局的。

2.3 其他环境变量

系统级的变量,变量名和变量内容,往往具有全局属性。
还有没有其他环境变量?查询:

env

介绍其余环境变量:

echo$HISTSIZE

记忆你之前使用过的命令,默认是1000,统计最近使用的1000条命令。

echo$OLDPWD

记忆用户在运行时上一次所存在的工作路径。

echo$SSH_TTY

记录终端文件,终端窗口不一样,输入重定向对内容进行重新输入。
PATH:指定命令的搜索路径。当你在命令行输入一个命令时,系统会按照 PATH 中列出的目录顺序依次查找对应的可执行文件。
HOME:当前用户的主目录路径。执行cd ~cd不带参数时,就会跳转到该目录。不同用户的 HOME 不同,例如/home/zhangsan/root
SHELL:当前用户所使用的 Shell 解释器的路径。常见的有/bin/bash/bin/zsh等,决定了你在终端中使用的命令解释器类型。

3. C/C++代码与进程之间的关系

3.1 用代码获取环境变量

3.1.1 main函数最多有几个参数?

三个参数,拿到系统的环境变量表,本质是将环境变量表传递给进程。
有什么用?不同的环境变量有不同的用途。
是谁传递的?怎么传递的?
环境变量在bash没有拿到的时候在哪里?
是谁传递给你的?默认是在bash内部的,bash本质是一个进程,是存储在内存中的,是临时表,内存级的。我的程序都是bash进程的子进程,子进程代码和数据是可以共享的,是父进程传递的。
所以环境变量具有全局属性。

存在两张环境变量表,当我们运行程序时,bash会fork出一个子进程,子进程可以看到父进程的参数。所以说,不传参数也能看到环境变量的原因是,子进程进行了继承。

不传参数怎么获取环境变量?
子进程都是bash的子进程,你可以获得bash的表,子进程天然可以继承父进程的数据。
语言会默认提供全局变量,全局的指针可以指向环境变量表。获取环境变量的第二种方式。

需要记住的是,环境变量可以被获取。
bash有两张表,一张是命令行参数表,一张是环境变量表。

3.1.2 shell外壳里的环境变量是哪里来的?

bash的环境变量是哪里来的?是从Linux系统的配置文件里面来的,启动时会把配置文件加载进来,所以当时你改的是内存级的数据,你关掉Xshell又打开会重新从配置文件中加载。
什么是配置文件,配置文件又是哪里来的?
家目录存在两个配置文件:
.bashrc
.bash_profile
上面的两个文件其实是相关的。

bash在启动时,会访问.bashrc文件,会将配置文件载入,修改一下就可以看到bash被执行,echo一行字就可以了。

root怎么不执行?每一个人都会有自己的家目录,改的不是root的配置文件。

为什么会给每个用户都搞一个bash?

while:;dopsaxj|grepbash;sleep1;donewhile:;dopsaxj|grepbash;sleep1;echo"#############";done

每开一个窗口就会有一个bash,每个子进程都会加载一个环境变量。
最常见:

mangetenv

原理是,根据名字查找环境变量的内容,根据环境变量名遍历这张表,并依次比较,遍历成功将右边返回,失败返回NULL。
如何用C/C++获取环境变量:

char *whoami = getenv("USER");

3.2 获取环境变量的若干种方法

环境变量的作用是限制程序的执行。
获取环境变量的三种做法:

  1. main函数参数:char* env[]
  2. C语言全局变量:char** environ
  3. 最佳实践:getenv(name)

测试:限制访问用户名。

3.3 环境变量、本地变量、内建命令

3.3.1 创建自己的环境变量

我想创建一个自己的环境变量怎么办?

test_env=12344env|grepTEST_ENV

存在但env不到,这个叫本地变量。
导出成环境变量:本质是在将本地变量放到环境变量表里,你就可以查到了:

exportTEST_ENV

再次查询就有了。
如果这个本地变量本来就没有,可以用export直接导也可以:

exportAAA=asdfghj

能不能被自己的C语言程序获得?

getenv("TEST_ENV");

子进程是可以获得父进程环境变量的,环境变量是全局的本质:环境变量是可以被子进程继承的。
如何删除环境变量:

unset[环境变量名]

取消命令行的环境变量:本质就是将环境变量,从环境变量表中删除。

其实,这些也都是内存级的,关掉重新打开就好了。

本地变量和环境变量的区别:本地变量无法被子进程继承,不具备全局性,只在bash内部可以访问!!

类比于局部变量和全局变量。

为什么要有本地变量?

cnt=0;while[$cnt-le100];doecho$cnt;letcnt++;done

shell当中的本地变量是为了支持语法的,用于保存一些临时信息。

set

可以查询系统变量和环境变量。
如果我想让我的环境变量关掉打开后还有,打开.bash_profile,在里面export导入一个环境变量。

3.4 内建命令

提出问题:
本地变量只能在shell内部运行,不能被子进程继承。
echo子进程看不到本地变量是如何被打印的?

  1. echo这个进程是怎样能打印本地变量的?

命令和命令是不一样的,存在二进制文件级别的命令:
普通命令:
内建命令:在shell内部自己定义,bash自己内部的一次函数调用,不依赖第三方路径。

内建命令是shell自己的,意味着内建命令的执行不需要环境变量。


欢迎大家批评指正!!!