Linux:命令行参数与环境变量(进程五)

今天我们来学习进程的另一个重要知识点,命令行参数与环境变量

我们先来探讨一下命令行参数是什么,话不多说,现在开始啦

命令行参数

1.命令行参数概念

在执行程序时,除了程序名本身,我们还可以在后面跟上一些额外的 "输入",这些输入就叫做命令行参数(Command-Line Arguments)

你可以把它理解为:给程序的 "启动指令" 或 "配置选项"

生活中的例子:

  • 你去餐厅吃饭,服务员问你:"请问你要什么主食?" 你回答:"一碗米饭。" 这里的 "一碗米饭" 就是你给服务员的 "参数"
  • 你使用打车软件,输入 "目的地:天安门",这个 "天安门" 就是你给打车软件的 "参数"

**编程中的例子:**当你在终端里输入以下命令时:

复制代码
ls -l -a
  • ls 是程序名。
  • -l 和 -a就是传递给 ls 程序的命令行参数
  • ls 程序根据这两个参数,执行了 "以长格式(-l)列出 当前 目录下的所有(包括隐藏文件)文件" 这个特定行为

没有命令行参数,程序的行为是固定的。有了它,同一个程序就可以根据不同的输入,完成不同的任务

2.argc

argc (Argument Count)

  • 它是一个整数,代表命令行参数的总个数
  • 注意 :程序名本身也被算作一个参数。所以 argc 的值至少是 1
3.argv

argv (Argument Vector)

  • 它是一个字符串指针数组 (char *argv[])。
  • argv[0] 指向程序名的字符串(例如 "./my_program"
  • argv[1] 指向第一个命令行参数的字符串(例如 "hello"
  • argv[2] 指向第二个命令行参数的字符串(例如 "world"
  • ... 以此类推。
  • argv[argc] 是一个 NULL 指针,标志着参数列表的结束
4.argc与argv的应用

下面我们创建两个文件来写测试用例:

运行以后我们就可以发现argvi会打印出./code 后面跟着的命令行参数-a, -b, -c

或许你会说,这有什么用呢,那我现在问一个问题,你如何使用不同的命令行参数匹配对应的功能?

使用argc与ragv就行

这里我们更改一下code.c的代码

cpp 复制代码
#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;                                                                                                                                                                                                
    }    
    if (strcmp(argv[1], "-a") == 0)    
    {    
        printf("这是功能1 : %s\n", argv[1]);    
    }    
    else if (strcmp(argv[1], "-b") == 0)    
    {    
        printf("这是功能2 : %s\n", argv[1]);    
    }    
    else if (strcmp(argv[1], "-c") == 0)    
    {    
        printf("这是功能3 : %s\n", argv[1]);    
    }    
    else     
    {    
        printf("usage : %s [-a/-b/-c]\n", argv[0]);    
    }    
    //for (int i = 0; i < argc; i++)    
    //{    
    //    printf("argv[%d] : %s\n", i, argv[i]);    
    //}    
    return 0;    
}                                      

此时我们再次运行,输入对应的-a, -b, -c就会匹配对应的功能,是不是很有用,这就是为什么我们使用类似ls等指令的时候,命令行参数的不同会使结果不同

5.总结
  • 命令行参数是程序启动时,用户通过终端传递给程序的额外信息
  • 在 C 语言中,main 函数通过 argcargv 两个参数来接收它们
  • argc 是参数的总个数(包含程序名)
  • argv 是一个字符串数组,存储了具体的参数内容,argv[0] 是程序名,argv[argc]NULL

掌握了命令行参数,你就可以编写更加灵活和通用的程序,比如像 **ls, gcc**这样功能强大的命令行工具

在下一部分,我们将学习环境变量,它是操作系统为进程提供的另一种重要的配置信息来源

环境变量

1.环境变量的基本概念

• 环境变量(environment variables)⼀般是指在操作系统中⽤来指定操作系统运⾏环境的⼀些参数

• 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪

⾥,但是照样可以链接成功,⽣成可执⾏程序,原因就是有相关环境变量帮助编译器进⾏查找。

• 环境变量通常具有某些特殊⽤途,还有在系统当中通常具有全局特性

2.查看环境变量⽅法

env:输出所有的环境变量

echo $NAME //NAME:你的环境变量名称

3.常⻅环境变量

PATH : 指定命令的搜索路径

HOME : 指定⽤⼾的主⼯作⽬录(即⽤⼾登陆到Linux系统中时,默认的⽬录)

SHELL : 当前Shell,它的值通常是/bin/bash

USER : 当前用户的用户名

LOGNAME : 当前登录的用户名

OLDPWD : 上一个pwd,这就是为什么cd -可以回到上一个地址

HISTSIZE : 保存历史命令最大条数,上述显示1000,说明最多可以保存1000条使用过的命令

4.测试PATH,理解export
  1. 创建code.c⽂件
cpp 复制代码
#include <sdtio.h>

int main()
{
    printf("hello linux!\n");
    return 0;
}
  1. 对⽐ ./code 执⾏和之间 code 执⾏

发现只有./code(即带上当前路径)才可以执行,而code会显示无法找到

  1. 为什么有些指令可以直接执⾏(如ls, tree, pwd),不需要带路径,⽽我们的⼆进制程序需要带路径才能执⾏?

这是因为系统的环境变量PATH在起作用

如果不带当前路径,系统默认就会去PATH里面查找,怎么查找呢,就是一个一个遍历存储在PATH路径下的所有路径的文件,如果发现一样的,就执行它

如果我们也想直接使用code运行程序怎么办呢,就需要使用到export了

  1. 将我们的程序所在路径加⼊环境变量PATH当中, export PATH=$PATH:code程序所在路径

此时就可以直接执行啦!

5.和环境变量相关的命令
  1. echo: 显⽰某个环境变量值

  2. export: 设置⼀个新的环境变量

  3. env: 显⽰所有环境变量

  4. unset: 清除环境变量

  5. set: 显⽰本地定义的shell变量和环境变量

我们已经使用了echo export env了,现在我们使用unset将PATH删除掉

不要担心他没了,我们删除的只是临时的PATH,等我们再次登录user1用户,它就会自动恢复默认

6.环境变量的组织⽅式

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

字符串

那照这样说的话,是不是main函数也会有一个env表呢,我们是不是可以通过main函数的env表打印出系统的env呢?答案是可以的,这个时候我们引入main的另一个参数,env

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

运行一下,并且和env对比一下

一模一样!

7.通过第三⽅变量environ获取环境变量

这里我们再次改变一下code.c的代码,引入environ

libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头⽂件中,所以在使⽤时要⽤

extern声明

cpp 复制代码
#include <stdio.h>                                                                                                                                              
#include <stdlib.h>                                                                                                                                                
                                                                                                                                                
int main()                                                                                                                                                
{                                                                                                                                                
    extern char** environ;                                                                                                                                                
    for (int i = 0; environ[i]; i++)                                                                                                                                                
    {                                                                                                                                                
        printf("environ[%d]->%s\n", i, environ[i]);                                                                                                                                                              
    }                                                                                                             
    return 0;                                                                                                                                                
} 

运行,也打印出了系统的环境变量

8.通过系统调⽤获取或设置环境变量

• putenv , 后⾯讲解

• getenv , 本次讲解

code.c代码改为下面这样

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

int main()
{
    printf("%s\n", getenv("PATH"));
    return 0;
}

运行就可以打印PATH字符串

9/环境变量通常是具有全局属性的

环境变量通常具有全局属性,可以被⼦进程继承下去

为了验证这个,我们将code.c改为下面的代码

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

此时系统里面是没有MYENV这个环境变量的,所以**./code是没有输出的**

我们就使用这个code,如果我们将MYENV添加到环境变量,并且再次启动这个./code输出我们刚刚添加的MYENV,就验证了我们的观点,全局变量是具体全局属性的

验证成功!!

这就是这篇博客讲的内容啦,如果觉得有帮助记得给我一个点赞,评论一下你的看法哦,下篇见~

相关推荐
大树8812 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠12 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质12 小时前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush412 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行52012 小时前
Linux 11 动态监控指令top
linux
小宇宙Zz12 小时前
Maven依赖冲突
java·服务器·maven
Inhand陈工13 小时前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智13 小时前
ARP代理--工作原理
运维·网络·arp·arp代理
不会C语言的男孩14 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
shushangyun_14 小时前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化