Linux命令行与环境变量
目录
Linux命令行与环境变量
命令行
简单介绍命令如何传递
环境变量
环境变量PATH
环境变量HOME
环境变量PWD
环境变量SHELL
理解环境变量
Linux命令行与环境变量
命令行
前面写C语言时,很少关注过main函数的参数,也没有考虑过main为什么会有参数。
实际上在C语言中,main函数一共有三个参数,在命令行部分先关注前两个参数:
argc:表示main函数接收到参数个数argv:表示main函数接收的参数
根据下面的代码观察这两个参数具体的效果:
#include <stdio.h>int main(int argc, char* argv[]) {printf("%d\n", argc);for(int i = 0; i < argc; i++) {printf("%s\n", argv[i]);}
}
对应的Makefile如下:
TARGET=test
SRC=test.c$(TARGET):$(SRC)gcc $^ -o $@ -std=c99.PHONY:clean
clean:rm -f $(TARGET)
直接运行程序可以看到下面的结果:

如果在输入./test后,再输入一些字符串可以看到下面的结果:

可以看到,argc的值即为终端上包括./test在内的所有字符串的个数,而argv是一个字符串数组,存储着终端上包括./test在内的以空格间隔的字符串,这个数组的最后一个元素就是NULL。这就是main函数的两个参数。
前面提到Linux下的命令都是文件,并且因为Linux是C语言编写的,所以所有命令所带有的选项即为存储在argv数组中的字符串,而根据不同的参数值实现不同的功能就可以通过类似于下面的形式完成:
#include <stdio.h>
#include <string.h>int main(int argc, char* argv[])
{if(argc == 1) {printf("默认功能\n");} else if(strcmp(argv[1], "-f1")==0) {printf("功能1\n");}return 0;
}
简单介绍命令如何传递
在Linux下输入的命令首先会被Shell拿到。
前面提到父进程和子进程的代码是共有的,但是二者数据是各自独立的,但是数据独立实际上只会建立在其中一个进程修改了数据,如果二者都是对变量进行只读不写,那么也没有必要单独为两个进程开辟两个数据空间
对于上面的情况亦是如此,直接在终端上执行的进程,其父进程都是Shell,并且父进程和子进程都只是以只读的方式访问main函数的参数,所以就不会出现两个数据空间。
从上面的过程中也可以看出,在设计操作系统、编程语言等时,相互都是存在依赖关系的
环境变量
前面提到main函数参数实际上有三个,而这第三个参数就是所谓的环境变量env,与argv一样,env是一个字符串数组
使用下面的代码可以看到其中的内容:
#include <stdio.h>int main(int argc, char* argv[], char* env[])
{for(int i = 0; env[i]; i++) {printf("%s\n", env[i]);}return 0;
}
需要注意的是,因为argc只能表示argv中的参数个数,所以对于循环终止条件来说,因为env的最后一个位置时NULL,所以读取到NULL即可停止
运行上面的代码,可以看到结果是一堆字符串,这些字符串就是所谓的环境变量
在Linux中,环境变量和对应的值都是键值对的形式,一共有三种方式查看系统中的环境变量:
- 程序中遍历
env数组 env指令- 使用
environ指针访问
environ本质是一个二级指针,其指向的是每一个环境变量的地址,所以通过下面的代码也可以访问到所有的环境变量:
#include <stdio.h>
#include <unistd.h>// 引入外部变量
extern char** environ;int main() {for(int i = 0; environ[i]; i++) {printf("%s\n", environ[i]);}return 0;
}
环境变量PATH
PATH指定了命令默认搜索的位置,因为其值中默认是/.../bin,所以命令执行是会默认去/bin目录下找,所以前面将自己写的程序移动到/bin路径下就可以运行是因为默认从/bin路径下搜索
可以使用echo $PATH查看当前用户的PATH环境变量的值
也可以使用echo ${PATH},此处的{}表示限定变量的边界
如果需要修改PATH值,可以使用PATH=指定的路径,但是这种方式只是修改了位于内存的系统进程中对应的PATH,而不会影响到本地配置文件中的PATH,并且这种方式会覆盖当前系统进程中的PATH值。
通过上述方式修改只需要退出当前用户再重新登陆即可重新加载对应的配置文件中的 PATH
如果需要修改PATH对应的配置文件,可以到用户的家目录下找到.bash_profile文件,修改其中的PATH值为需要的值即可
环境变量HOME
在Linux中,HOME环境变量指定了每一个用户的家目录,对于root用户来说,其值即为/root,对于普通用户该值即为/home/用户名
使用echo $HOME查看结果如下:
普通用户:

root用户:

在用户登录时,首先bash会从配置文件中加载对应的值到HOME中,此时bash进程中的cwd就是家目录,因为HOME的值为当前用户的家目录,而因为大部分运行在bash进程之上的指令都是bash进程的子进程,子进程会与父进程共用一块数据,所以子进程的cwd与父进程的cwd相同。所以如果直接在家目录运行一个普通的程序时,查看其cwd值可以看到结果与父进程相同,例如下面的结果:

需要注意,并不是所有的命令都是bash进程的子进程,例如cd命令
cd 命令并不是一个单独的进程,而是一个内建(built-in)命令。所以如果使用cd改变当前bash的工作路径,cd指令通过chdir函数对bash进程中的数据直接进行修改,从而达到直接改变bash进程的cwd,例如下面的效果:
为了更加直观得看到当前bash进程的PID,可以使用echo $$命令,其中的$$就代表当前bash的PID

环境变量PWD
在Linux中,PWD中的值为当前用户所处的工作路径,所以使用pwd命令查看当前的工作路径实际上就是在读取PWD中的值

PWD一般用于进程在当前工作路径下创建一个文件,在标准库中提供了一个函数为getenv,原型如下:
char *getenv(const char *name); // 参数传递环境变量名,返回环境变量值
只要获取到了当前路径,就可以在当前路径下创建文件
如果需要在程序中创建或修改一个环境变量,可以使用putenv函数,原型如下:
int putenv(char *string);// 参数传递一个键值对,如果指定的环境变量已经存在就实现修改,否则就是新增
对应的还有一个OLDPWD环境变量,该环境变量的值为上一次的工作路径,这也就是为什么使用cd -可以切换为上一次工作路径的原因

环境变量SHELL
在Linux中,SHELL表示当前使用的终端:

理解环境变量
环境变量本质是系统提供的具有全局属性的变量,既然是全局属性,则证明所有进程都可以访问到环境变量,这个过程实际上就是通过进程之间的父子关系实现的,因为环境变量本质是被bash进程从配置文件加载的,所以bash进程和其子进程就都可以看到环境变量。在大部分情况下环境变量是不会被修改的,所以bash进程和子进程实际上是共用一块环境变量空间
前面提到有一些指令时内建指令,另一部分是外部命令,常见的内建命令还有echo和export
在Linux中,bash是shell脚本语言的一种实现,而shell是一个命令行解释器,用户通过它与操作系统进行交互,它可以运行命令、脚本和程序,所以可以在命令行直接创建一个变量,这种变量也被称为本地变量,例如:
![]()
本地变量与环境变量基本一致,只是本地变量不具有全局属性,即父子进程不会共享
使用set可以查看当前创建的本地变量和环境变量,如果想要清除指定的本地变量可以使用unset + 本地变量名
本地变量也可以使用echo命令输出:
![]()
如果需要将本地变量添加到环境变量,可以使用export命令,例如:

也可以直接将变量的初始化结合export使用:

