【Linux系统】命令行参数和环境变量

文章目录

  • 一、命令行参数
    • [1. main 函数参数](#1. main 函数参数)
    • [2. 如何理解命令行参数](#2. 如何理解命令行参数)
  • 二、环境变量
    • [1. 基本概念](#1. 基本概念)
    • [2. 常见环境变量](#2. 常见环境变量)
    • [3. 查看环境变量方法](#3. 查看环境变量方法)
      • [3.1 测试 PATH](#3.1 测试 PATH)
      • [3.2 测试 HOME](#3.2 测试 HOME)
    • [4. 和环境变量相关的命令](#4. 和环境变量相关的命令)
    • [5. 环境变量的组织方式](#5. 环境变量的组织方式)
    • [6. 获取环境变量](#6. 获取环境变量)
      • [6.1 命令行第三个参数](#6.1 命令行第三个参数)
      • [6.2 通过系统调用获取](#6.2 通过系统调用获取)
      • [6.3 第三方变量 environ](#6.3 第三方变量 environ)
    • [7. 本地变量](#7. 本地变量)
  • 总结

一、命令行参数

1. main 函数参数

在我们一开始学习 C C C 语言的时候, m a i n main main 函数一直都是作为函数的入口,而在实际代码的运行中, m a i n main main 也会被其他函数所调用,其有两个参数: a r g c argc argc 和 a r g v argv argv。

c 复制代码
#include <stdio.h>    
    
int main(int argc, char* argv[])    
{    
    for(int i = 0; i < argc; i ++)    
    {    
        printf("argv[%d]:%s\n", i, argv[i]);                                                                                                                           
    }    
    return 0;    
}    
  1. a r g c argc argc:表示 a r g v argv argv 数组的元素个数。

  2. a r g v argv argv:一个变长的字符指针数组,用来存放运行时的命令行参数(以空格为分隔符),并且以 N U L L NULL NULL 结尾。

2. 如何理解命令行参数

m a i n main main 命令行参数:是运行同一个命令,可以通过不同的选项,来实现不同的子功能的方法!(指令选项的实现方法)

c 复制代码
#include <stdio.h>    
#include <string.h>    
    
int main(int argc, char* argv[])    
{    
    if(argc != 2)    
    {    
        printf("Usage:%s [-a/-b/-c]\n", argv[0]);    
        return 1;    
    }    
    
    const char* arg = argv[1];    
    
    if(strcmp(arg, "-a") == 0)    
        printf("这是功能1\n");    
    else if(strcmp(arg, "-b") == 0)    
        printf("这是功能2\n");    
    else if(strcmp(arg, "-c") == 0)    
        printf("这是功能3\n");    
    else    
        printf("Usage:%s [-a/-b/-c]\n", argv[0]);    
                                                                                                                                                                        
    return 0;    
}    

因此,每个进程都会拥有一张 a r g v argv argv 表,用来支持实现选项功能!


二、环境变量

要执行一个程序,必须先找到它!我们自己实现的二进制程序需要带有 ./ 才能运行(表示当前路径),而系统提供的指令却不需要,这是为什么?

实际上,在系统中, b a s h bash bash 会通过环境变量 P A T H PATH PATH(系统中搜索指令的默认搜索路径),来帮助系统找到目标二进制文件!

1. 基本概念

环境变量( e n v i r o n m e n t v a r i a b l e s environment\ variables environment variables)一般是指在操作系统中用来指定操作系统运行环境 的一些参数 (被 b a s h bash bash 使用,即用户间接使用)。其通常具有某些特殊用途,还有在系统当中通常具有全局特性。

如:我们在编写 C / C C/C C/C++ 代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。

2. 常见环境变量

环境变量 内容
P A T H PATH PATH 指令 / / /命令的搜索路径
H O M E HOME HOME 当前用户的家目录 ~(即用户登录到 L i n u x Linux Linux 系统时的默认目录)
S H E L L SHELL SHELL 当前 s h e l l shell shell,它的值通常是 /bin/bash
U S E R USER USER 当前用户名
L O G N A M E LOGNAME LOGNAME 登陆时的用户名
H I S T S I Z E HISTSIZE HISTSIZE 保存的历史命令的数量
H O S T N A M E HOSTNAME HOSTNAME 当前主机的主机名
P W D PWD PWD 当前 s h e l l shell shell 所在的路径
O L D P W D OLDPWD OLDPWD s h e l l shell shell 上一次所在的路径

3. 查看环境变量方法

命令:echo $[环境变量名称]

其中,这里路径都是绝对路径 。多个路径之间以 : : : 分割,如果前一个路径没有找到,将会继续在下一个路径寻找,如果都没有找到,则说明该命令不存在。

3.1 测试 PATH

添加环境变量,不仅可以将命令拷贝到系统路径下,还可以将该命令的所在路径添加到 P A T H PATH PATH 路径。

  1. PATH=[要添加的路径]:会将 P A T H PATH PATH 之前的路径也一同覆盖掉。
  1. PATH=$PATH:[要添加的路径]:追加路径,不会覆盖。

注意:添加的环境变量不是永久的,当断开连接或者重新打开终端时,环境变量会自动恢复默认!

3.2 测试 HOME

H O M E HOME HOME 环境变量,是当前用户的家目录(~)。

由于是存放的当前用户的家目录,因此 r o o t root root 用户的 H O M E HOME HOME 环境变量自然也是 /root 目录:

4. 和环境变量相关的命令

命令 作用
e c h o echo echo 显示某个环境变量值
e x p o r t export export 设置一个新的环境变量
e n v env env 显示所有环境变量
u n s e t unset unset 清除环境变量
s e t set set 显示本地定义的 s h e l l shell shell 变量和环境变量

5. 环境变量的组织方式

每个程序都会收到一张环境变量表:环境变量表是一个字符指针数组,每个指针指向⼀个以'\0' 结尾的环境字符串。因此,环境变量就是一个 k e y = v a l u e key=value key=value 的字符串。

在我们在命令行输入命令时, b a s h bash bash(内部存储了两张表)会获取到我们的命令行参数,然后先构建命令行参数表 ,再根据命令找到环境变量表 中的 P A T H PATH PATH,然后根据其中的路径寻找,如果找到,就创建进程执行。

那么环境变量最开始在哪里呢? ------ ------ ------ 在系统的相关配置文件中!

在家目录下,有两个 b a s h bash bash 默认配置文件:


总结一下,环境变量的生命周期是由 b a s h bash bash 决定的:

  1. 在登录的时候, b a s h bash bash 会根据环境变量配置文件来创建环境变量表,在 b a s h bash bash 运行期间,修改的环境变量其实是修改的 b a s h bash bash 里存放的环境变量表,在退出的时候, b a s h bash bash 回收,空间释放。等到再次登陆,又会重新根据配置文件重新创建新的环境变量表,因此之前修改过的表就会丢失。

  2. 如果修改了环境变量配置文件,对当前运行的 b a s h bash bash 中的环境变量表并无影响(因为其在修改前就已经创建),但等到 b a s h bash bash 退出,再次登陆时, b a s h bash bash 就会依据修改过的配置文件来创建新的环境变量表,进而在以后的每一次登陆,环境变量都会修改,从而达到永久修改的目的。

6. 获取环境变量

6.1 命令行第三个参数

m a i n main main 函数的第三个参数 e n v env env:一个变长的字符指针数组,用来存放环境变量,并且也以 N U L L NULL NULL 结尾。

c 复制代码
#include <stdio.h>    
    
int main(int argc, char* argv[], char* env[])    
{    
    (void)argc;    
    (void)argv;    
    
    for(int i = 0; env[i]; i ++)    // 当 env[i] == NULL 时,循环结束    
    {                                                                                                                                                                   
        printf("env[%d]-> %s\n", i, env[i]);    
    }    
    
    return 0;    
}  

可以看到,获取到了所有的环境变量:

环境变量有什么特性呢? ------ ------ ------ 环境变量通常具有全局属性,可以被子进程继承下去。

  1. 环境变量是由父进程( b a s h bash bash)获取。

  2. 环境变量可以被子进程继承。(全局特性)

6.2 通过系统调用获取

常用 g e t e n v getenv getenv 和 p u t e n v putenv putenv 函数来访问指定的环境变量。

c 复制代码
#include <stdio.h>    
#include <stdlib.h>    
    
int main()    
{    
    char* value = getenv("PATH");    // 获取PATH环境变量的内容
    
    if(value == NULL)    
        return 1;    
    
    printf("PATH->%s\n", value);                                                                                                                                        
    
    return 0;    
}   

小应用 ------ 只针对特定用户才能使用的代码逻辑:

c 复制代码
#include <stdio.h>    
#include <stdlib.h>    
#include <string.h>    
    
int main()    
{    
    const char* who = getenv("USER");                                             
    
    if(who == NULL)    
        return 1;    
    
    if(strcmp(who, "ybc") == 0)    
    {    
        printf("程序正常运行逻辑!\n");    
    }    
    else    
    {    
        printf("Only ybc!!\n");    
    }    
    
    return 0;    
} 

为什么环境变量可以被子进程继承呢?

  1. 子进程可以根据环境变量来进行个性化操作(如上述,定制一个只能由自己执行的程序)。

  2. 可以通过环境变量来进行进程级别的数据传递,进而可以实现对子进程的控制逻辑。

6.3 第三方变量 environ

在 l i b c libc libc 中定义的全局变量 e n v i r o n environ environ 指向环境变量表。由于 e n v i r o n environ environ 没有包含在任何头文件中,所以在使用时,要用 e x t e r n extern extern 声明。

c 复制代码
#include <stdio.h>    
    
extern char** environ;		// 声明全局变量                                                                                                                                                  
    
int main()    
{    
    for(int i = 0; environ[i]; i ++)    // 当 environ[i] == NULL 时,循环结束        
    {                                                                                                                                                                           			   
    	printf("environ[%d]-> %s\n", i, environ[i]);
    }                                                   
  
    return 0;
}  

7. 本地变量

我们可以在 s h e l l shell shell 命令行中自定义本地变量,其不会被子进程继承,只能在 b a s h bash bash 内部有效。

b a s h bash bash 会记录两套变量:

  1. 环境变量:可以通过 env 命令来查看所有环境变量。
  2. 本地变量:可以通过 set 命令来查看所有本地和环境变量。

由于 b a s h bash bash 内部需要支持 s h e l l shell shell 脚本(一种脚本语言),因此需要支持本地变量。

也可以利用 export 命令将本地变量导入到环境变量:

我们导入的环境变量在谁里面?

导入在 b a s h bash bash 里面!

为什么 e x p o r t export export(子进程)能把环境变量给 b a s h bash bash(父进程)呢?

因为 e x p o r t export export 是内建命令 ( b u i l t − i n c o m m a n d built-in\ command built−in command):其不需要创建子进程,而是让 b a s h bash bash 自己调用函数执行,或者系统调用完成!也就是说,只要 b a s h bash bash 能够运行,内建命令就能够运行。


总结

环境变量是操作系统特定的一些全局变量,其通常有特定的用途,用来记录系统相关的信息,比如:主机名、家目录的路径、当前命令行的路径、命令的搜索路径等等。这些环境变量都能够被子进程继承,因此类似 g c c gcc gcc、 g g g++ 等工具也能继承,从而可以通过环境变量找到动静态库来进行链接。

相关推荐
还不秃顶的计科生3 小时前
linux下conda未安装的解决方法(离线安装linux下的conda)
linux·运维·服务器
DeeplyMind3 小时前
Linux的Dynamic debug功能
linux·dynamic debug
LJ-SEU3 小时前
win-ubuntu网络转发
linux·网络·ubuntu
QT 小鲜肉3 小时前
【个人成长笔记】在Ubuntu中的Linux系统安装 anaconda 及其相关终端命令行
linux·笔记·深度学习·学习·ubuntu·学习方法
QT 小鲜肉3 小时前
【个人成长笔记】在Ubuntu中的Linux系统安装实验室WIFI驱动安装(Driver for Linux RTL8188GU)
linux·笔记·学习·ubuntu·学习方法
爱学习饼4 小时前
CentOS下安装配置JDK24和tomcat11
linux·运维·centos
迎風吹頭髮5 小时前
Linux服务器编程实践26-TCP连接超时重连机制:超时时间计算与重连策略
服务器·网络·php
@realXuan5 小时前
实践 3:Vim 编辑器的使用
linux·vim