【Linux】环境变量(图文)
目录
一、main函数的参数解释:
1、argc和argc的解释
2、为什么要这样设置?
3、注意:
4、命令行计算器:
二、认识环境变量
三、见见环境变量
1、执行一个程序的前提
2、指令:echo $PATH
3、为什么系统自带的指令运行时不用加 " ./ "
4、环境变量:PWD
5、环境变量:USER
6、查看所有环境变量:env
7、创建新的环境变量的指令:export
8、总结:
9、main函数的第三个参数
10、bash维护的环境变量表
11、不使用命令行参数传参,如何获取环境变量?
12、获取环境变量的第三种方法:environ
四、本地变量
1、set+回车,可以查看系统中所有变量,包括环境变量和本地变量
2、移除环境变量 / 本地变量指令:unset
五、问题:bash进程只有用户登录系统后才存在,而所有环境变量都在bash进程的上下文中,但当我们关闭连接后又重启时,这些环境变量会恢复到默认值,那这些环境变量是从哪里来的呐?
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家
点击跳转到网站
一、main函数的参数解释:
1、argc和argc的解释
平时我们写C语言时,main函数一般都是不带参数的,但其实main也有参数,先来介绍前两个参数:
![]()
main函数的参数其实就是命令行的参数:
(1)第一个参数argc是第二个参数argv数组的大小;
(2)第二个参数argv是用来保存命令行输入的参数的;
通过下述代码测试:
1 #include
2 int main(int argc,char* argv[]) 3 { 4 for(int i = 0;i < argc;i++) 5 { 6 printf("argv[%d]:%s ",i,argv[i]); 7 } 8 9 return 0; 10 } 当我们运行该可执行文件时,后面如果带有参数,则后面这些参数就会被argv数组接收保存,这个操作是bash做的:
这些命令行提示符都是bash给我们输出的:
bash还会将我们输入"./myprocess a b c ",以空格为分隔符,将每一段当做字符串存在argv数组中,同时以NULL结尾,所以我们还可以这样打印:
1 #include
2 int main(int argc,char* argv[]) 3 { 4 for(int i = 0;argv[i];i++) 5 { 6 printf("argv[%d]:%s ",i,argv[i]); 7 } 8 9 return 0; 10 } ~ 因为argv是以NULL结尾,所以当for循环遇到NULL就会自动结束。
2、为什么要这样设置?
场景之一就是可以使一个程序通过命令行传入不同参数从而实现不同功能:
1 #include
2 #include 3 int main(int argc,char* argv[]) 4 { 5 if(argc > 2) 6 { 7 printf("输入了多个参数,输入无效 "); 8 return 0; 9 10 } 11 if(strcmp("-1",argv[1])==0) 12 { 13 printf("执行-1功能 "); 14 } 15 else if(strcmp("-2",argv[1]) == 0) 16 { 17 printf("执行-2功能 "); 18 } 24 return 0; 25 }
3、注意:
我们平时使用的指令(如ls,pwd),都带有选项(如ls -a),而大部分指令都是C/C++写的,就是通过main的参数达到的不同选项实现不同功能,这些选项也是命令行参数
命令行参数就是linux指令选项的基础!
4、命令行计算器:
通过main参数的功能,可以实现一个简易版命令行计算器:
二、认识环境变量
(1)环境变量不只有一个,而是有很多,而且环境变量彼此之前没有关系。
(2)环境变量一般是系统内置的具有特殊用途的变量。
(3)定义变量的本质其实就是开辟空间,在运行期间我们的程序也能开辟空间。
(4)操作系统(bash)使用C语言写的程序,它能在运行中开辟空间。系统的环境变量本质就是系统自己开辟的空间,只是用环境变量给这份空间命名和内容。
三、见见环境变量
1、执行一个程序的前提
执行一个程序的前提是要在系统里面找到这个程序,所以平时我们运行程序时需要在可执行程序名前面加" ./ ",不然系统会提示找不到
但是我们使用shell自带的指令就不需要带./,如ls、pwd等等。
2、指令:echo $PATH
该指令是用来查看系统默认去搜索的各个路径:
注意" : "是路径之间的分割符。
3、为什么系统自带的指令运行时不用加 " ./ "
我们自己写的程序想要像系统指令那样不用加" ./ ",有两种方法:
(1)可以将自己的可执行文件拷贝到指令echo $PATH所展示的任意一个路径下。但是这种方法会污染系统的路径,所以建议使用第二种方法。
(2)将自己的可执行程序的路径放到PATH中,指令格式如下图:
注意要将红框中的" :$PATH "带上,因为这个指令会直接覆盖原PATH内容,而$PATH代表的就是原有PATH内容,所以需要加上。
此时运行我们自己的程序也不需要加" ./ "了:
若不小心将原有PATH内容覆盖了:
此时系统自带的指令就都不可以使用了,此时只需要要重启shell,即可恢复原有PATH内容。
4、环境变量:PWD
系统pwd指令怎么知道当前我在哪个路径?
就是因为添加了PWD环境变量,这个环境变量会记录我的当前路径。
可以通过下面指令查看:
5、环境变量:USER
该环境变量记录的是当前登录的用户:
6、查看所有环境变量:env
7、创建新的环境变量的指令:export
8、总结:
环境变量就是当你进入系统时,存储和传递系统配置信息、控制程序运行环境等重要数据的,方便你之后去访问。
9、main函数的第三个参数
讲到环境变量就可以谈谈main函数的第三个参数:char* env[ ]
env数组和argv数组都是用来存储数据的,只是env存储的是环境变量
10、bash维护的环境变量表
在系统看来其实这些环境变量就是一行一行字符串:
bash内部有个env表(与main函数的第三个参数类似),每个元素就是用来存储每一行环境变量的首地址,通过这个表来维护环境变量。并且环境变量是具有全局属性,可以被子进程继承下去。
所以我们知道bash会维护两张表,一张是命令行参数的argv表,一张是env表,这样我们才能给main函数传参。
11、不使用命令行参数传参,如何获取环境变量?
通过一个系统调用:
char *getenv(const char *name);
参数传的是环境变量名,函数返回环境变量的内容。
示例代码:
1 #include
2 #include 3 #include 4 #include 5 int main(int argc,char* argv[]) 6 { 7 8 const char* username = getenv("USER"); 9 if(username)printf("%s ",username); 10 else printf("None "); 11 12 return 0; 13 }
通过这个系统调用,我们就可以通过获取环境变量进行筛选,比如该程序只能被限定用户使用,这样限定后,即使是root用户也不能执行该程序:
1 #include
2 #include 3 #include 4 #include 5 int main(int argc,char* argv[]) 6 { 7 8 const char* username = getenv("USER"); 9 if(username != "HF")printf("你的用户名为:%s,你没有权限访问这个程序 ",username); 10 else printf("你可以执行 "); 11 12 return 0; 13 }
12、获取环境变量的第三种方法:environ
environ类型是" char** ",这是内部定义的一个全局变量,我们知道char二级指针可以看成一个char指针数组,所以environ其实跟env表差不多,每一行都是环境变量的首地址:
使用environ获取环境变量的示例代码:
1 #include
2 #include 3 #include 4 #include 5 int main(int argc,char* argv[]) 6 { 7 8 //通过environ获取环境变量 9 extern char** environ; 10 for(int i = 0;environ[i];i++) 11 { 12 printf("%s ",environ[i]); 13 } 14 15 16 return 0; } 因为是env表以NULL结尾,所以for循环的循环条件可以像上述这样写。
四、本地变量
除了环境变量,其实还是本地变量,定义本地变量的方法直接像下述那样在命令行写,也是通过echo $xxx查看:
1、set+回车,可以查看系统中所有变量,包括环境变量和本地变量
2、移除环境变量 / 本地变量指令:unset
五、问题:bash进程只有用户登录系统后才存在,而所有环境变量都在bash进程的上下文中,但当我们关闭连接后又重启时,这些环境变量会恢复到默认值,那这些环境变量是从哪里来的呐?
答案:这些环境变量是从磁盘的某些脚本文件或者配置文件来的。
六、关于环境变量的相关代码
该小点内容来自豆包AI:
#include
#include #include // 使用 getenv 函数获取环境变量的值 void get_env_value(const char *name) { char *value = getenv(name); if (value != NULL) { printf("The value of %s environment variable is: %s ", name, value); } else { printf("The %s environment variable is not set. ", name); } } // 使用 environ 全局变量访问所有环境变量 void list_all_environment_variables() { char **env = environ; while (*env != NULL) { printf("%s ", *env); env++; } } // 使用 putenv 函数设置环境变量 void set_env_with_putenv(const char *name, const char *value) { char new_env[100]; snprintf(new_env, sizeof(new_env), "%s=%s", name, value); if (putenv((char *)new_env) == 0) { get_env_value(name); } else { printf("Failed to set the environment variable using putenv. "); } } // 使用 setenv 函数设置环境变量 void set_env_with_setenv(const char *name, const char *value) { if (setenv(name, value, 1) == 0) { get_env_value(name); } else { printf("Failed to set the environment variable using setenv. "); } } // 使用 unsetenv 函数删除环境变量 void delete_env(const char *name) { get_env_value(name); if (unsetenv(name) == 0) { get_env_value(name); } else { printf("Failed to delete the environment variable. "); } } // 子进程中环境变量的继承 void child_process_inherit_env(const char *name, const char *value) { if (setenv(name, value, 1) == 0) { pid_t pid = fork(); if (pid == 0) { // 子进程 char *value_in_child = getenv(name); if (value_in_child != NULL) { printf("The value of %s in child process is: %s ", name, value_in_child); } _exit(0); } else if (pid > 0) { // 父进程 wait(NULL); } else { perror("fork"); } } } int main() { // 获取 PATH 环境变量的值 get_env_value("PATH"); // 列出所有环境变量 printf("All environment variables: "); list_all_environment_variables(); // 使用 putenv 设置环境变量 set_env_with_putenv("MY_VARIABLE", "hello"); // 使用 setenv 设置环境变量 set_env_with_setenv("ANOTHER_VARIABLE", "world"); // 删除环境变量 delete_env("MY_VARIABLE"); // 子进程中环境变量的继承 child_process_inherit_env("INHERITED_VARIABLE", "from_parent"); return 0; }