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

目录

一、命令行参数

二、环境变量

1.环境变量的基本概念

2.查看环境变量的方法

3.环境变量相关命令

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

环境变量具有全局属性


一、命令行参数

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

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

cpp 复制代码
int main(int argc, char* argv[], char* env[])
{

}

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

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

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

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

cpp 复制代码
int main(int argc, char* argv[]){
  for(int i = 0; i < argc; i++){
    printf("argv[%d]->%s\n",i,argv[i]);
  }
  return 0;
}
cpp 复制代码
[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"

cpp 复制代码
#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;
}
cpp 复制代码
[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/目录中

cpp 复制代码
[wuxu@Nanyi lesson14]$ which ls
alias ls='ls --color=auto'
        /usr/bin/ls

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

cpp 复制代码
[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目录(也称为家目录)是不一样的

cpp 复制代码
[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,以其简洁的语法和强大的自动完成功能而受到欢迎。

cpp 复制代码
[wuxu@Nanyi lesson14]$ echo $SHELL
/bin/bash

3.环境变量相关命令

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

cpp 复制代码
[wuxu@Nanyi lesson14]$ echo $PWD
/home/wuxu/lesson14

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

cpp 复制代码
[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行

cpp 复制代码
[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变量,例如

cpp 复制代码
[root@Nanyi lesson14]# bash
[root@Nanyi lesson14]# hahshjs=12902
[root@Nanyi lesson14]# echo $hahshjs
12902

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

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

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

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

1️⃣ getenv

使用getenv实现pwd命令:

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

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

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

cpp 复制代码
#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参数打印所有环境变量

cpp 复制代码
#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;
}

环境变量具有全局属性

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

相关推荐
S+叮当猫3 小时前
第五部分:2---信号的介绍、产生、处理
linux·运维·服务器
东城绝神4 小时前
《Linux运维总结:基于ARM64+X86_64架构CPU使用docker-compose一键离线部署mongodb 7.0.14容器版副本集群》
linux·运维·mongodb·架构
WZF-Sang6 小时前
Linux权限理解【Shell的理解】【linux权限的概念、管理、切换】【粘滞位理解】
linux·运维·服务器·开发语言·学习
小橞7 小时前
Linux搭建简易路由转发
linux·运维·服务器
robot_大菜鸟7 小时前
linux-L7-linux 查看json文件
linux·运维
Flying_Fish_roe7 小时前
linux-网络管理-网络抓包
linux·网络·php
小技与小术9 小时前
lvs-nat模式实验详解
linux·运维·服务器·网络·lvs
py.鸽鸽9 小时前
Linux2-mkdir,touch,cat,more
linux
aabbcc456aa9 小时前
ubuntu安装mysql 8.0忘记root初始密码,如何重新修改密码
linux·mysql·ubuntu
张太行_9 小时前
Linux 调用write()函数后,内核一般多久将数据写入磁盘
linux·运维