@TOC
0. 引入
众所周知,命令、程序、工具...本质上都是可执行的文件。我执行自己的程序时,需要带./
,是为了找到对应的程序。
" title="">
那为什么系统的命令可以直接执行,而不用带路径呢?那是因为环境变量(这里是PATH:指定命令的搜索路径)
:yellow_heart: 查看环境变量
echo $NAME [NAME:环境变量名]
可以看到,环境变量PATH以:
作为分隔符,分隔出多条路径,执行系统命令时,会从左向右依次查找,直至找到。
" title="">
:yellow_heart:那么,怎么样使我们自己的可执行程序不带路径就能直接执行呢?
- 把命令(我们自己写的可执行程序也可以看做是某种命令) 拷贝到环境变量PATH的某一路径下
严重不推荐,因为会污染命令池。现在我们知道,所谓的安装软件,就是把软件拷贝到系统环境的某一特定路径下。
把我们的当前路径添加到环境变量PATH中
export PATH=$PATH:当前路径 导环境变量
这里设置的是内存级的环境变量,并没有写入到系统文件中,关闭xshell也会释放掉。
1. 概念(重要)
1.1 环境变量
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数或具有某些特殊用途的系统级变量。
:yellow_heart: 常见的环境变量
- PATH : 指定命令的搜索路径
- HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的家目录)
- SHELL : 当前Shell版本,它的值通常是/bin/bash。
" title="">
:yellow_heart: 一系列环境变量相关指令
echo 显示某个环境变量值
export 设置一个新的环境变量
env 显示所有环境变量
1.2 本地变量
:heart: 系统中还存在着一种变量,叫做本地变量,是与本次登陆(session会话)有关的变量,只在本次登陆有效。
set 显示本地或环境变量
unset 清除本地或环境变量
" title="">
这个环境变量没有写到配置文件中,关闭xshell会释放掉。不过我们现在所谈的环境变量都是系统级的。
" title="">
2. 查看环境变量
众所周知,main函数是可以携带参数的,传递命令行参数。
#include<stdio.h>
int main(int argc,char* argv[])
{
for(int i = 0;i<argc;i++)
{
printf("argv[%d]->%s\n",i,argv[i]);
}
return 0;
}
- argc:限定命令行字符串个数
- argv:指针数组
" title="">
:yellow_heart: 那么命令行参数有什么意义呢?
众所周知,指令有很多选项,用来完成同一个命令的不同子功能。选项底层就是通过命令行参数实现的 ——
" title="">
我们可以通过给同一个程序带入不同参数的方式,呈现出不同的功能。比如下面这段程序,就可以通过输入不同选项,输出不同的结果。
#include<stdio.h>
#include<string.h>
int main(int argc,char* argv[])
{
if(argc != 2)
{
// 限定传两个命令行参数,否则打印如下错误信息
printf("Usage:%s-[a|b]\n",argv[0]); return 1;
}
if(strcmp(argv[1],"-a")==0)
printf("hello a4\n");
else if(strcmp(argv[1],"-b")==0)
printf("hello beatles\n");
else
printf("hello\n"); //默认
}
运行结果 ——
" title="">
2.1 通过代码
命令行的第三个参数 & 第三方变量environ。
1.命令行的第三个参数
main函数除了可以传递命令行参数,还可以传递环境变量env
.
⛄️ 环境变量的组织方式
每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以\0
结尾的环境变量字符串。
" title="">
于是我们就可以用程序来获取环境变量 ——
#include<stdio.h>
#include<string.h>
int main(int argc,char* argv[],char* env[])
{
for(int i = 0; env[i]; i++)
{
printf("%d->%s\n",i,env[i]);
}
return 0;
}
2.第三方变量environ
environ
是系统默认提供的第三方变量,类型char**,指向环境表的起始地址。
#include<stdio.h>
#include<string.h>
int main()
{
extern char** environ;
for(int i = 0;environ[i];i++)
{
printf("%s\n",environ[i]);
}
return 0;
}
environ是系统提供的外部指针,编译时自动制定好环境变量的位置,从而获取环境变量 ——
然而,以上两种方式极极极不常用,只是为了说明环境变量是可以传到程序里的,了解即可。
2.2 getenv
:heart: 可以通过环境变量名,获取环境变量内容
#include<stdio.h>
#include<stdlib.h>
int main()
{
printf("%s\n",getenv("PATH"));
printf("%s\n",getenv("HOME"));
printf("%s\n",getenv("SHELL"));
return 0;
}
我们拿着变量名,找到环境变量,再拿到变量中内容 ——
" title="">
即便如此,我们也不会没事儿去获取环境变量,但是这个概念非常重要。
3. 环境变量具有全局属性
:heart: 环境变量具有全局属性,本质是因为环境变量可以被子进程继承的。
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("I am a process.pid:%d,ppid:%d\n",getpid(),getppid());
return 0;
}
多跑几遍,可以看到我的PID一直在变,因为进程子在不断新建,但PPID保持不变,而它的父进程就是-bash
,即命令行解释器。命令行上启动的进程,父进程都是bash
(fork).
" title="">
那么怎么证明环境变量具有全局属性呢?在myproc中写如下一段代码
#include<stdio.h>
#include<stdlib.h>
int main()
{
printf("my_env_string:%s\n",getenv("my_env_string"));
return 0;
}
" title="">
环境变量,影响了整个“用户”系统 ——
" title="">
持续更新~@边通书