当前位置: 首页 > article >正文

【Linux详解】命令行参数|环境变量

目录

一、命令行参数

二、环境变量

1.环境变量的基本概念

2.查看环境变量的方法

3.环境变量相关命令

4.环境变量的组织方式以及获取环境变量的三种方法

环境变量具有全局属性


一、命令行参数

【示例1】main函数也是函数,main函数可以带参吗?

没错,main函数有三种形式,其中最完整的形式是

int main(int argc, char* argv[], char* env[])
{

}

main函数的参数可带可不带,我们今天讨论的肯定是带参的,那么这些参数是什么呢?这些是命令行参数,让我们接下来看看吧

int main(int argc, char* argc[]){}
  • ·argc(argument count)是一个整数,表示传递给程序的命令行参数的数量。

  • ·argv(argument vector)是一个字符指针数组,其中每个指针指向一个参数字符串。

我们直接来看看这个argv里面有什么东西

int main(int argc, char* argv[]){
  for(int i = 0; i < argc; i++){
    printf("argv[%d]->%s\n",i,argv[i]);
  }
  return 0;
}
[wuxu@Nanyi lesson14]$ gcc -o test minglinghang.c -std=c99
[wuxu@Nanyi lesson14]$ ./test
argv[0]->./test
[wuxu@Nanyi lesson14]$ ./test -a
argv[0]->./test
argv[1]->-a
[wuxu@Nanyi lesson14]$ ./test -d
argv[0]->./test
argv[1]->-d
[wuxu@Nanyi lesson14]$ ./test -a -b -c -d
argv[0]->./test
argv[1]->-a
argv[2]->-b
argv[3]->-c
argv[4]->-d

 

【问题1】为什么要有命令行参数?

本质:命令行参数本质是交给我们程序的不同的选型,用来定制不同的程序功能。命令中会携带很多的选项

应用:自定义命令

下面我们自定义一个命令cdd,这个命令允许用户带1个选项,如果这个选项是-a就输出“Hello,I am cdd”,-b选项就输出“cdd is cool”

#include <stdio.h>
#include <string.h>

int main(int argc,char* argv[],char* env[]){

  if(argc == 2 && strcmp("-a",argv[1]) == 0)
  {
    printf("Hello, I am cdd\n");
  }
  else if(argc == 2 && strcmp("-b",argv[1]) == 0)
  {
    printf("cdd is cool!\n");
  }else{
    printf("\r\tYou are supposed to use -a or -b\n");
  }

  return 0;
}
[wuxu@Nanyi lesson14]$ ./cdd -a
Hello, I am cdd
[wuxu@Nanyi lesson14]$ ./cdd -b
cdd is cool!
[wuxu@Nanyi lesson14]$ ./cdd -a -b
        You are supposed to use -a or -b

【问题2】谁干的?

结论1:父进程的数据,能被子进程看到并且访问

结论2:命令行中启动的程序,都会变成进程,其实都是bash的子进程

所以也就是父进程bash干的。bash是一个命令行解释器,我们输入的./cdd -b默认是输入给父进程bash/shell的

  1. 1.程序启动时:当您在命令行中输入程序名称并按回车时,命令行解释器(如 shell)会启动程序,并将命令行参数传递给程序。

  2. 2.操作系统:操作系统负责创建进程,并将命令行参数准备好。当程序开始执行时,操作系统将参数传递给程序的 main 函数。

二、环境变量

1.环境变量的基本概念

环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数。

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

【示例1】我们在系统中执行ls命令时,不需要./ls,而我们执行自己编写的C语言程序,并编译为可执行程序时,确需要使用./才能运行,这是为什么呢?

使用which命令可以查看该指令的存储位置,比如 which ls,会发现ls存储在/usr/bin/目录中

[wuxu@Nanyi lesson14]$ which ls
alias ls='ls --color=auto'
        /usr/bin/ls

系统中维护了一个PATH环境变量,系统可以帮助我们在PATH环境变量保存的各个路径中查找命令。echo $PATH 命令的作用是输出当前用户的PATH环境变量值。这个值通常包含多个目录,用冒号(:)分隔。例如:

[wuxu@Nanyi lesson14]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/wuxu/.local/bin:/home/wuxu/bin

也就是说,只要我们执行某个命令,这个命令在PATH的环境变量下,那么就可以不使用 ./就可以执行我们的程序。

而我们的程序并没有保存在PATH环境变量的指定目录下,因此无法不带./就执行。所以我们可以通过将可执行文件保存到PATH指定目录,这样就可以不带./运行了。但是这种方式会污染系统的命令,所以我们不建议使用这种方式

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

2.查看环境变量的方法

echo $[环境变量名]

常见的环境变量

◉ PATH:指定命令的搜索路径

◉ HOME:指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)

当我以root用户身份登录时,我的HOME环境变量保存的是/root;但如果我以wuxu用户身份登录时,我的HOME环境变量保存的/home/wuxu。从这里可以发现,不同用户的HOME目录(也称为家目录)是不一样的

[root@Nanyi lesson14]# echo $HOME
/root
[root@Nanyi lesson14]# su wuxu
[wuxu@Nanyi lesson14]$ echo $HOME
/home/wuxu

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

SHELL环境变量定义了当前用户的默认shell类型。这个变量告诉系统在用户登录时应该启动哪个shell。shell是用户与操作系统交互的界面,它负责解释用户输入的命令并执行它们。

默认情况下,当用户登录时,系统会启动用户配置的默认shell。这个shell可以是各种类型的shell,如Bash、Zsh、Fish等。不同的shell有不同的命令语法和特性,因此用户可以根据个人喜好或工作需要选择不同的shell。

SHELL变量的值通常是shell的路径,例如:

  • /bin/bash:Bash(Bourne-Again SHell)是大多数Unix-like系统中默认的shell。

  • /bin/zsh:Zsh(Z shell)是一个强大的shell,提供了许多扩展和增强功能。

  • /bin/fish:Fish是一个现代化的shell,以其简洁的语法和强大的自动完成功能而受到欢迎。

 

[wuxu@Nanyi lesson14]$ echo $SHELL
/bin/bash

3.环境变量相关命令

1️⃣ echo:显示某个环境变量值

[wuxu@Nanyi lesson14]$ echo $PWD
/home/wuxu/lesson14

2️⃣ export:设置一个新的环境变量

[wuxu@Nanyi lesson14]$ export wuxu=123
[wuxu@Nanyi lesson14]$ echo $wuxu
123

注意:export设置的环境变量仅在当前会话有效,当我们将整个会话关闭,重新打开Linux命令行时,这个环境变量就会消失。

在系统中,每次启动bash时,该bash会从系统环境变量配置文件中读取环境变量信息,而export仅仅只是修改了本次启动的bash环境变量,一旦关闭重启后,将会重置环境变量。如果想要使得自定义环境变量永久存在,就需要修改配置文件,也就在/etc/profile添加环境变量

3️⃣ env:显示所有环境变量

4️⃣ unset:清除环境变量

 

 

5️⃣ set:显示本地定义的shell变量和环境变量

显示本地定义变量的前20行

[wuxu@Nanyi lesson14]$ set | head -20
BASH=/usr/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")
BASH_VERSION='4.2.46(2)-release'
COLUMNS=107
COMP_WORDBREAKS=$' \t\n"\'><=;|&(:'
DIRSTACK=()
EUID=1000
GROUPS=()
HISTCONTROL=ignoredups
HISTFILE=/home/wuxu/.bash_history
HISTFILESIZE=1000
HISTSIZE=1000

我们可以直接在bash命令行直接定义变量,不再使用export。set除了显示环境变量外,还显示了本地自定义的shell变量,例如

[root@Nanyi lesson14]# bash
[root@Nanyi lesson14]# hahshjs=12902
[root@Nanyi lesson14]# echo $hahshjs
12902

本地变量与bash环境变量的区别:本地定义的变量是局部变量,只在当前shell中有效,而环境变量是全局变量,在整个系统中都是可见的。环境变量通常用于设置系统级别的配置,而本地定义的变量用于存储脚本或命令行中的临时数据。

4.环境变量的组织方式以及获取环境变量的三种方法

每个进程都有一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串

下面介绍3种可以从环境表获取环境变量的方法

1️⃣ getenv

 使用getenv实现pwd命令:

[wuxu@Nanyi lesson14]$ cat testStatus.c
#include<stdio.h>
#include<stdlib.h> 
int main()
{
        printf("%s\n", getenv("PWD"));
        return 0;
}
[wuxu@Nanyi lesson14]$ make
gcc -o testStatus testStatus.c -std=c99
[wuxu@Nanyi lesson14]$ ./testStatus
/home/wuxu/lesson14

2️⃣ 通过第三方变量environ获取

使用environ时,需要先对该变量进行声明,即extern char** environ。下面使用代码打印环境变量的所有内容 

#include<stdio.h>
#include<stdlib.h> 

int main()
{
        extern char **environ;
        for(int i = 0; environ[i]; i++)
        {
                printf("[%d]->%s\n", i, environ[i]);
        }
        return 0;
}

3️⃣ main函数env参数(命令行第三个参数)

我们在使用命令执行某些可执行程序时,bash会帮助给该程序传入3个参数↓↓↓

 

ls命令为例,ls -a -l,它的命令行参数有3个,分别时ls、-a、-l,因此argv保存的就是{“ls”, “-a”, “-l”, NULL},而第三个参数就是bash传递给它的子进程的环境变量。

下面使用main的env参数打印所有环境变量

#include <stdio.h>

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

环境变量具有全局属性

环境变量具有全局属性,可以被子进程继承下去。子进程的环境变量是从父进程继承来的,默认所有的环境变量都会被子进程继承。

 


http://www.kler.cn/a/293014.html

相关文章:

  • 1.7 JS性能优化
  • 【HarmonyOS NEXT】一次开发多端部署(以轮播图、Tab栏、列表为例,配合栅格布局与媒体查询,进行 UI 的一多开发)
  • Vue 的生命周期函数 和 Vuex
  • Bugku CTF_Web——文件上传
  • 前端-同源与跨域
  • 在Java中使用ModelMapper简化Shapefile属性转JavaBean实战
  • OpenAI SORA团队负责人 通往智能的方式 报告笔记
  • 网络层 V(IPv6)【★★★★★★】
  • k8s-pod 实战三 (Liveness Probe 和 Readiness Probe 详细分析)
  • Stage 模型应用程序包的结构
  • Java设计模式【命令模式】-行为型
  • 国内领先线上运动平台:如何借助AI技术实现业务腾飞与用户体验升级
  • HarmonyOS开发实战( Beta5版)合理使用动画丢帧规范实践
  • 替换Windows AD时,网络准入场景如何迁移对接国产身份域管?
  • Linux——中间件、数据库(理论)
  • 2024高教社杯全国大学生数学建模竞赛(A题)深度剖析 _ 建模完整过程+详细思路+代码全解析
  • Quartz.Net_依赖注入
  • GitHub Copilot的详细介绍
  • RHCE必过技巧,无需本人参加也可拿证?
  • 紫光展锐完成Android 15同步升级,驱动技术创新与生态共赢
  • 【区块链 + 人才服务】紫金研究院知识库管理系统 | FISCO BCOS应用案例
  • GAMES101(0~1作业)
  • django企业开发实战-学习小结1
  • hiprint打印/jsPDF使用/html2canvas
  • 本地使用Docker部署Nexus Maven私有仓库工具结合内网穿透实现远程管理
  • AI学习记录 - 旋转位置编码