Linux 命令行参数和环境变量
环境变量 (Environment Variables) 概念
定义: 环境变量是指在操作系统中用来指定操作系统运行环境的一些参数
示例:
在编写C/C++代码时,链接过程中通常不需要明确知道动态或静态库的位置,但仍能成功链接并生成可执行程序。这是因为相关环境变量帮助编译器进行查找特性:
- 通常具有特殊用途
- 在系统中具有全局特性
常见环境变量示例
PATH
指定命令的搜索路径。HOME
指定用户的主工作目录(即用户登录到Linux系统时的默认目录)。SHELL
当前使用的Shell,其值通常是/bin/bash。
我们可以通过 echo 指令查看环境变量:
echo $NAME //NAME:你的环境变量名称
示例如下:
╭─ljx@VM-16-15-debian ~/linux_review/lesson1/dir1
╰─➤ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/games
系统的命令本质上也是可执行程序,而你自己编译出来的可执行程序执行是需要指定对应路径的,但系统的命令确不需要指定路径就可以调度,这是为什么呢?
这正是环境变量起到了作用,当你输入一个命令的时候,系统是会去 PATH 环境变量对应的路径下面查找是否有对应可执行程序的,而你自己编译出来的可执行程序的路径并不在
PATH 环境变量中,因此若你不提供自己的可执行程序对应的路径,系统在 PATH 所包含的所有路径中查找后没有发现该可执行程序,就会报错
这里我们可以举例验证一下,下面这个可执行程序默认情况下是需要指定路径才可以运行的:
╭─ljx@VM-16-15-debian ~/linux_review/lesson1/dir1
╰─➤ ./test.o 130 ↵
I am parent process, my pid is 2027036
I am child process, my pid is 2027037 my ppid is 2027036
╭─ljx@VM-16-15-debian ~/linux_review/lesson1/dir1
╰─➤ test.o
zsh: command not found: test.o
但我们可以用个 export 命令导入一个新的路径环境变量到 PATH 中去:
╭─ljx@VM-16-15-debian ~/linux_review/lesson1/dir1
╰─➤ export PATH=$PATH:/home/ljx/linux_review/lesson1/dir1
╭─ljx@VM-16-15-debian ~/linux_review/lesson1/dir1
╰─➤ test.o
I am parent process, my pid is 2027629
I am child process, my pid is 2027630 my ppid is 2027629
然后你就会惊奇的发现,不用指定路径也可以运行这条指令了,我们查看一下 PATH 变量,会发现多了一条
刚刚被我们导入的路径:
╭─ljx@VM-16-15-debian ~/linux_review/lesson1/dir1
╰─➤ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/games:/home/ljx/linux_review/lesson1/dir1
Linux 中如果想要查看到所有的变量,可以通过 env 命令查看:
╭─ljx@VM-16-15-debian ~/linux_review/lesson1/dir1
╰─➤ env
USER=ljx
LOGNAME=ljx
HOME=/home/ljx
PATH=/usr/local/bin:/usr/bin:/bin:/usr/games
SHELL=/usr/bin/zsh
...... #后面内容太多就省略了
除了这种方式获取环境变量,我们还可以通过代码获取环境变量,不过在此之前,我得先介绍一下 main 函数传参的前两个参数 argc 和 argv
命令行参数
这两个参数分别代表的是命令行参数的个数以及命令行参数
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
for(int i = 0; i < argc; ++i)
{
cout << argv[i] << endl;
}
return 0;
}
我们运行这段代码:
╭─ljx@VM-16-15-debian ~/linux_review/lesson1/dir1
╰─➤ ./arg.o 111 222 333
./arg.o
111
222
333
你会发现,argv 的第一个参数是进程名称,后面分别就对应的是输入的命令行参数
命令行参数中存储的是一个个的 char* 指针,因此最后一个 argv 的下一个 char* 是空指针,因此可以改写成如下遍历形式:
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
for(int i = 0; argv[i]; ++i)
{
cout << argv[i] << endl;
}
return 0;
}
当遍历到 argv[i] 为0的时候,就会退出循环,最终运行结果和上面相同
环境变量参数
同样的,环境变量也可以通过这种方式获取,环境变量对应的是 main 函数的第三个参数 env(名字随便取的,你喜欢怎么叫都行)
当然,环境变量参数不像命令行参数一样有一个 argc 用于计数,但我们可以通过判断是否便利到了 nullptr 来判断是否遍历完了
环境变量参数存储图:

我们通过判断是否遍历到空指针来遍历整个环境变量
#include <iostream>
using namespace std;
int main(int argc, char *argv[], char *env[])
{
for(int i = 0; env[i]; ++i)
{
cout << env[i] << endl;
}
return 0;
}
可以看到,打印出来的数据和通过 env 指令获取的一模一样:
╭─ljx@VM-16-15-debian ~/linux_review/lesson1/dir1
╰─➤ ./arg.o
USER=ljx
LOGNAME=ljx
HOME=/home/ljx
PATH=/usr/local/bin:/usr/bin:/bin:/usr/games
SHELL=/usr/bin/zsh
...... # 同理,省略了后面的数据
除此之外,我们还可以利用第三方变量 environ 来获取环境变量:
#include <iostream>
using namespace std;
int main()
{
extern char **environ;
for(int i = 0; environ[i]; ++i)
{
cout << environ[i] << endl;
}
return 0;
}
libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用
extern声明
进程是如何获取环境变量的?
子进程的环境变量都是会从父进程继承过来的,而我们创建的所有进程,都是通过 bash 或 zsh 等命令行工具创建出来的,因此
在我们运行一个进程的时候,这个进程就自然将 bash 进程的环境变量继承过来了
getenv
该函数可以用于获取环境变量对应的参数:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
extern char **environ;
cout << getenv("PATH") << endl;
return 0;
}
运行后即可直接查看到 PATH 环境变量存储的内容:
╭─ljx@VM-16-15-debian ~/linux_review/lesson1/dir1
╰─➤ ./arg.o
/usr/local/bin:/usr/bin:/bin:/usr/games