环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
环境变量通常具有某些特殊用途,在系统中具有全局特性。
举几个栗子:
我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
系统命令其实也是一个个程序。但在命令行上输入某些系统命令时(如cd, pwd, cp等),我们从不在命令前加其所在路径但系统却可以找到并执行他。这是由于PATH环境变量记录了命令的搜索路径。
查看环境变量方法
为什么有些系统指令可以直接执行,不需要带路径;而我们编写的程序需要带路径才能执行?
这是由于PATH环境变量记录了命令的搜索路径。所有的系统命令都可以在PATH环境变量所记录的路径下找到。
想不带路径直接执行自己编写的程序?
将我们编写的可执行程序的所在路径加入环境变量PATH当中
export
命令用于导出环境变量,并使其对所有程序可见
export PATH=$PATH:file_path //追加
export PATH=file_path //覆写
此时就可以直接通过可执行文件名运行程序了,不需要再加路径。
请注意:此更改仅对当前会话有效。如果你想要永久生效,应将该目录添加到你的shell配置文件中(例如,对于Bash来说是 ~/.bashrc)。
用于指定用户的主工作目录
不同登录用户的HOME环境变量不同
cd ~
命令可以直接切换到家目录,就是因为HOME环境变量记录了家目录的路径。
C/C++的main函数共有三个参数:
int main(int argc, char *argv[], char *env[]);
- argc:命令行参数的个数,默认为1。
- argv:命令行参数表,默认保存
./program
- env:环境变量表
每个进程都会收到一张环境变量表,环境变量表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境变量字符串。
环境变量表以NULL结尾
提示:bash也是一个进程,他也会收到环境变量表。在执行基本指令时不需要带路径是因为bash获取到了环境变量PATH。
方法一:通过main函数的第三个参数获取环境变量表
#include
int main(int argc, char *argv[], char *env[])
{
int i = 0;
while(env[i] != NULL){
printf("%s\n", env[i]);
++i;
}
return 0;
}
方法二:通过全局变量environ获取环境变量表
#include
#include
int main(int argc, char *argv[])
{
int i = 0;
while(environ[i] != NULL){
printf("%s\n", environ[i]);
++i;
}
return 0;
}
注意:environ定义在头文件
中,是一个char** 类型,和env的类型和用法完全相同。
方法三:通过系统调用getenv获取指定的环境变量
#include
#include
int main(int argc, char *argv[])
{
printf("%s/n", getenv("PATH"));
return 0;
}
注意:getenv函数的声明包含在头文件
中
我们知道了每个进程都会收到一张环境表,那么环境表是从哪来的呢?答案是,从其父进程继承来的。
环境变量具有全局属性,可以被子进程继承下去。
测试代码:
#include
#include
int main()
{
char * env = getenv("MYENV");
if(env){
printf("MYENV: %s\n", env);
}
else{
printf("variable do not exist!\n");
}
return 0;
}
直接运行,发现该环境变量根本不存在:
我们首先要导出环境变量 export MYENV="hello world"
再次运行程序,发现进程获取到该环境变量了:
bash是所有在命令行上启动的进程的父进程,通过上面的测试就说明环境变量是可以被子进程继承下去的!
注意:
export
的作用是将局部变量导出为环境变量,使其可以被当前shell进程的子进程继承,并在整个环境中可见和使用。如果不使用export
命令,设置的变量是局部变量不是环境变量只在当前shell进程中有效,不会被子进程继承。- 以上的操作均只在本次登录有效,重新登录后所有的自定义变量都会被清除。若想长期有效需修改对应的配置文件,shell进程在被创建时会从文件中载入环境变量,并供所有的子进程继承。
命令行参数是在执行命令时,通过命令行传递给程序的额外信息。它们是一些字符串值,用于向程序提供输入、配置选项或操作参数等。
在命令行中,通常以空格分隔的形式提供命令和参数。命令行参数可以分为两类:
位置参数(Positional Arguments):位置参数是按照它们在命令行中出现的顺序传递给程序的参数。程序可以根据位置来解析和使用这些参数。例如,program arg1 arg2
中的arg1
和arg2
就是位置参数。如指令mv dir1 dir2, cp dir1 dir2等等。
选项参数(Option Arguments):选项参数是以某种特定的格式传递给程序的参数,通常以短横线(-)或双短横线(–)开头。选项参数用于配置程序的行为或提供特定的操作。例如,program -f filename
中的-f
就是一个选项参数,用于指定要操作的文件名。如指令ls -a -l, rm -r -f等等
命令行参数可以帮助程序根据不同的需求进行不同的操作或配置。在C语言中,可以通过main
函数的参数argv来获取命令行参数表,并在程序中进行处理和使用命令行参数。
每个进程都会收到一张命令行参数表,命令行参数表是一个字符指针数组,每个指针指向一个以’\0’结尾的命令行参数字符串。
命令行参数表同样以NULL结尾
C/C++的main函数共有三个参数:
int main(int argc, char *argv[], char *env[]);
- argc:命令行参数的个数,默认为1。
- argv:命令行参数表,默认保存
./program
- env:环境变量表
一个接收命令行选项参数的简单程序:
int main(int argc, char** argv){
if(argc == 1)
{
cout << "Run without option!" << endl;
return 0;
}
//程序中内置的选项
vector<string> options;
options.push_back("-a");
options.push_back("-b");
options.push_back("-c");
options.push_back("-d");
//匹配查找输入的选项
for(int i = 1; i<argc; ++i){
auto ret = find(options.begin(), options.end(), argv[i]);
if(ret != options.end())
{
cout << "option: " << argv[i] << endl;
}
else{
cout << "option " << argv[i] << " is not available!" << endl;
break;
}
}
return 0;
}
运行结果:
echo $NAME
:显示指定名称的shell变量和环境变量的值。如果该变量没有被定义,则不会显示任何内容。
env
:显示所有的环境变量和其值。
export
:将shell变量导出为环境变量。该命令将指定的shell变量添加到环境变量表中,使其在当前shell会话中可用,并在子进程中也可用。
set
:显示本地定义的shell变量和环境变量的值。该命令会显示所有的本地定义的shell变量和环境变量,包括当前shell会话中定义的变量和从父进程继承的变量。
unset
:删除指定名称的shell变量和环境变量。该命令会删除指定的shell变量或环境变量,使其在当前shell会话中不再可用。如果该变量是一个环境变量,则该命令只会在当前shell会话中删除该变量,而不会影响其他进程。