Linux 命令行参数和环境变量

Linux 命令行参数和环境变量

七月 14, 2025 次阅读

环境变量 (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 来判断是否遍历完了

环境变量参数存储图:

env

我们通过判断是否遍历到空指针来遍历整个环境变量

#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