在 Linux 系统的学习与开发中,命令行参数环境变量是两个极为重要的概念,它们是程序与系统、程序与用户交互的关键桥梁。本文将从基本概念入手,逐步深入,结合代码示例详细解析这两个知识点。


一、环境变量:操作系统的“运行参数”

(一)基本概念

环境变量(environment variables)是操作系统中用来指定运行环境的参数集合。它有以下几个关键特性:

  • 特殊用途:比如在编译 C/C++ 程序时,链接器依靠环境变量查找动态 / 静态库,我们无需手动指定库路径也能完成链接。
  • 全局特性:在系统中具有全局性,影响范围广泛。

(二)常见环境变量

Linux 系统中有许多预定义的环境变量,以下是最常见的几个:

环境变量 作用 示例
PATH 指定命令的搜索路径,系统会按该路径顺序查找可执行程序 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
HOME 指定用户的主工作目录,即用户登录系统后的默认目录 普通用户为/home/xxx,root 用户为/root
SHELL 指定当前使用的 Shell,Linux 默认通常是/bin/bash /bin/bash

(三)查看环境变量的方法

最直接的方式是使用 echo命令,格式为echo $变量名

  • 单变量查看:echo $变量名,如echo $PATH
  • 批量查看:env显示所有环境变量;set显示本地 Shell 变量和环境变量。

(四)举例

1、PATH环境变量测试

将以上简单的代码编译成可执行程序后,我们来对比两种执行方式:

  • 带路径执行:./hello

  • 直接执行:hello

问题来了,为什么系统命令(如lscd)可以直接执行,而我们的hello程序必须带路径?

那是因为系统命令的可执行文件位于PATH环境变量指定的路径中,系统会自动搜索;而hello所在路径不在PATH中,所以必须手动指定路径。

所以我们可以试试将程序路径加入PATH:

export PATH=$PATH:程序实际所在路径

直接执行hello,此时程序可以正常运行。

2、HOME环境变量测试

  • root 用户执行:echo $HOME,输出/root

  • 普通用户执行:echo $HOME,输出/home/xxx(xxx 为用户名)。

如下图,执行cd ~; pwd,输出的路径与$HOME的值一致,说明~HOME的简写。

(五)与环境变量相关的命令

命令 功能
echo 显示单个环境变量的值
export 设置新的环境变量(或导出已有变量为环境变量)
env 显示所有环境变量
unset 清除环境变量
set 显示本地定义的 Shell 变量和环境变量

(六)环境变量的组织方式

每个程序都会收到⼀张环境表,环境表是⼀个字符指针数组,每个指针指向⼀个以’\0’结尾的环境字符串。

(七)通过代码获取环境变量

在 C 语言中,有两种常见方式获取环境变量。

方式 1:通过main函数的第三个参数

main函数可以接收第三个参数char *env[],它指向环境变量表。

#include <stdio.h>

int main(int argc, char *argv[], char *env[])
{
    int i = 0;
    for(; env[i]; i++){
        printf("%s\n", env[i]);
    }
    return 0;
}

运行的结果和使用env命令一样。

方式 2:通过全局变量environ

#include <stdio.h>

int main(int argc, char *argv[])
{
    extern char **environ;

    int i = 0;
    for(; environ[i]; i++){
        printf("%s\n", environ[i]);
    }
    return 0;
}

libc中定义了全局变量environ,它指向环境变量表。由于environ未包含在头文件中,使用时需用extern声明。

(八)通过系统调用获取或设置环境变量

Linux 提供了系统调用函数来获取或设置环境变量,常用的有 getenv和 putenv(后面讲解)

函数getenv:获取指定环境变量的值

函数原型:char *getenv(const char *name);

#include <stdio.h>
#include <stdlib.h>  // getenv需要的头文件
int main()
{
    printf("%s\n", getenv("PATH"));
    return 0;
}

(九)环境变量的全局属性

环境变量具有全局属性可以被子进程继承。我们通过一个例子来验证这一点。

#include <stdio.h>
#include <stdlib.h>
int main()
{
    char *env = getenv("MYENV");
    if(env){
        printf("%s\n", env);
    }
    return 0;
}

直接运行程序,无输出(因为MYENV环境变量不存在)。

此时我们导出环境变量MYENV:

export MYENV="hello world"

再次运行程序:

说明子进程(我们的程序)继承了父进程(Shell)的环境变量。

但当我们执行MYENV="hello world“(不export)时,这个变量仅属于当前 Shell 的本地变量(Local Variable),其作用域仅限于当前 Shell 进程本身,不会被子进程(例如我们编译的 C 程序)继承。

原理分析:

  • Shell 进程在创建子进程时,会将自己的环境变量(通过 export 声明的变量)复制一份传递给子进程,但本地变量不会被复制。
  • 因此,直接执行 MYENV="hello world" 后运行程序,子进程中无法获取 MYENV;而通过 export MYENV="hello world" 声明后,MYENV 成为环境变量,才能被子进程继承。

(十)环境变量的持久化设置

临时通过 export 设置的环境变量,会在当前 Shell 关闭后失效。若需环境变量永久生效(系统重启后仍可用),需修改系统配置文件,具体分为以下两种场景:

  • 对所有用户生效(全局设置)

修改 /etc/profile 或 /etc/environment 文件(需 root 权限),所有用户登录后均可使用该环境变量。(以修改 /etc/profile 为例)

1、使用 root 权限打开文件

sudo vim /etc/profile

2、在文件末尾添加环境变量声明

export MYENV="hello world"  # 格式:export 变量名=值(值若含空格需用引号包裹)

3、无需重启,执行以下命令让系统重新加载配置文件:

source /etc/profile
  • 仅对当前用户生效(局部设置)

修改当前用户主目录下的 ~/.bashrc 或 ~/.bash_profile 文件(无需 root 权限),仅当前用户可使用该环境变量。(以修改 ~/.bashrc 为例)

1、打开文件

vim ~/.bashrc  # 或 gedit ~/.bashrc

2、在文件末尾添加环境变量声明

export MYENV="hello world"

3、使配置立即生效

source ~/.bashrc  # 重新加载当前用户的配置文件

注意事项:

  • 配置文件中的环境变量声明必须带 export,否则仅为文件所在 Shell 的本地变量,无法被子进程继承。
  • 若同时修改了全局和局部配置文件,局部配置会覆盖全局配置(优先级:~/.bashrc > ~/.bash_profile > /etc/profile)。
  • 对于 ~/.bash_profile 和 ~/.bashrc 的区别:
    • ~/.bash_profile 仅在用户登录时加载(如通过 ssh 登录或图形化界面登录);
    • ~/.bashrc 在每次打开新的终端窗口时加载,更适合日常临时添加的环境变量,推荐优先使用。

二、命令行参数

(一)基本概念

命令行参数是用户在启动程序时,通过命令行传递给程序的参数,用于控制程序的行为、指定输入输出等。例如ls -l /home中,-l/home都是ls命令的命令行参数。

(二)命令行参数在 C 程序中的表示

想必大家对这两个参数都很眼熟,但是我们并不知道是干什么用的。

C 程序通过main函数的前两个参数接收命令行参数

  • int argc参数个数(argument count),包含程序名本身。
  • char *argv[]参数数组(argument vector),每个元素是一个参数字符串,argv[0]是程序名,argv[1]argv[argc-1]是用户传入的参数。

例如:

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("参数个数 argc = %d\n", argc);

    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    
    return 0;
}


三、命令行参数与环境变量的区别与联系

对比项 命令行参数 环境变量
作用域 仅对当前启动的程序有效 具有全局属性,可被子进程继承
传递时机 程序启动时通过命令行传递 程序启动前已由系统或用户设置
修改方式 需重新启动程序并传入新参数 可通过export、修改配置文件等方式动态修改(或持久化)
联系 两者都是程序与外部交互的方式,共同决定程序的运行行为

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐