目录

一、补充知识:命令行参数

1.概念

2.查看命令行参数

3.在系统中的应用

二、环境变量的介绍

1.概念

 2.常见环境变量

3.查看环境变量的方法

测试PATH: ​编辑

4.一系列环境变量:

三、操作环境变量

1.命令

2.代码(主函数参数)

3.代码(getenv函数)

4.代码(environ变量)

四、环境变量的特性

1.环境变量具有全局特性

2.本地变量和内建命令(built-in command)

五、Shell脚本


一、补充知识:命令行参数

1.概念

执行c语言程序时,可以从命令行传递值给main函数,这些值被成为命令行参数。

这些值被传递到哪里去了?答:主函数的参数

c语言的主函数完整原型应该如下:

int main(int argc, char *argv[]);
  • argc(argument count): int类型,表示参数的个数,包括程序名本身,因此至少为1。
  • argv(argument vector):是函数指针数组,每一个指针都是char* ,指向一个字符串(也就是对应的命令行参数)。

2.查看命令行参数

我们可以通过如下代码来查看命令行参数:

#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;
}

这段代码本质就是循环打印每一个命令行参数,编译执行查看结果。

可以看到,命令行参数本质就是将我们执行的命令看成字符串,以空格划分输入argv数组中。

3.在系统中的应用

应用场景:Linux命令参数:

Linux是用c语言编写的,那么Linux命令自然也是c程序,也有主函数,实现原理实际上就是用主函数的参数去接收命令的参数,加上分支条件判断语句,就能实现不同的功能。

例如ls命令:

我们可以简单模拟一条Linux命令:

code.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");
  return 0;
}

通过if语句判断接受参数,不同参数实现不同功能,编译之后,code程序就类似于Linux命令了:

进程拥有一张argv表,用于实现命令的选项功能。

二、环境变量的介绍

1.概念

环境变量是全局变量,用于存储影响程序行为的各种参数。环境变量可以在整个系统范围内或特定用户会话中设置,并且可以被所有进程继承。

系统执行程序的前提条件:要执行程序,必须先找到它!

思考:

我们之前要执行程序,采用的都是./+程序名,ls等指令的实际路径是/usr/bin,为什么这些路径不需要呢?

由于环境变量:PATH的存在,系统能直接找到它!

 2.常见环境变量

常用环境变量有如下三种:

  • PATH:指定命令的搜索路径。
  • HOME:指定用户的主工作目录(即用户登陆到系统的默认目录,就称之为家目录)。
  • SHELL:当前Shell,它的值通常是/bin/bash。

3.查看环境变量的方法

查看指定环境变量:

echo $NAME # NAME替换成环境变量名称

测试PATH:

可以看到PATH中是一系列路径并且以‘:’分开,在执行命令时,系统就从这些路径之中依次寻找命令源程序文件。‘/usr/bin’就在其中,ls等命令在该目录下,因此可以直接执行。

因此,如果我们想要让code程序可以直接被执行,那么我们就可以将code所在路径加入环境变量。

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

 这个命令可以看成三级:

  1. 第一级,PATH=程序所在路径。这条命令会临时用程序所在路径覆盖PATH中所有路径,此时,大部分命令都无法使用了。由于是临时的,重新打开bash(命令行窗口)就能恢复。
  2. 第二级,PATH=$PTAH:程序所在路径。这样写系统就会在PATH添加一条这个程序所在的路径,但也是临时的。
  3. 第三级,即完整命令,在保证第二级的基础上能让PATH永久更新。

示范:

4.一系列环境变量:

  • HOME:记录家目录
  • USER:记录当前用户
  • LOGNAME:登陆时的用户,一般与USER一致
  • SHELL:记录当前使用的Shell(Shell指命令行工具,bash也是SHELL的一种)
  • HISTSIZE:一个整数值,表示BASH最多记录HISTSIZE条之前用过的命令,输入hisotry即可查看历史命令。
  • HOSTNAME:当前主机的主机名
  • PWD:当前所在工作路径
  • OLDPWD:以前的PWD,  输入cd - 可切换到OLDPWD

三、操作环境变量

1.命令

env:查看所有环境变量

echo: 查看单个变量内容 

echo $NAME # NAME替换成环境变量名称

export:添加一个新的环境变量

export NAME=VALUE # NAME替换为你要添加的名称,VALUE替换成你想给这个变量添加的值

unset:清除环境变量

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

2.代码(主函数参数)

先上代码:

#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;
}

 如图所示,我们使用了main函数的第三个参数,env数组,这个数组就对应系统的环境变量,由于该数组会以NULL作为最后一个元素,那么我们就可以按图中的方式用for循环遍历打印。这样,我们就通过C代码得到了所有的环境变量。

运行结果:

3.代码(getenv函数)

我们可以使用man命令快速上手getenv函数

man 3 getenv

 

 可以看到该函数需要的头文件是stlib.h,参数是要查询的环境变量名(const char* 类型),返回值是对应的环境变量值(const char* 类型)。

示例:

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

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

  // 只是为了不让编辑器报警
  (void)argc;
  (void)argv;
  (void)env;

  char *val = getenv("PATH");
  if (val == NULL)
    return 1;

  printf("%s\n", val);

  return 0;
}

思考:如何将程序只能被某个指定用户执行?

只需要在程序中通过getenv获取环境变量的USER对应的值,加以判断即可!!!

因此,代码获取环境变量可以对我们的代码实施一些定制化操作!

4.代码(environ变量)

这是一个二级指针,实际上它等效于主函数的第三个参数env。

它的头文件是unistd.h,要使用它,必须用extern声明:

extern char **environ;

代码:

#include <stdio.h>
#include <unistd.h>

extern char **environ;

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

  // 只是为了不让编辑器报警
  (void)argc;
  (void)argv;

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

  return 0;
}

结果依旧是打印全部的环境变量内容。

四、环境变量的特性

1.环境变量具有全局特性

子进程、甚至子进程的子进程、.... 都可以拿到环境变量。这就是环境变量的全局特性。

验证:

​

#include <stdio.h>
#include <unistd.h>

extern char **environ;

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

  // 只是为了不让编辑器报警
  (void)argc;
  (void)argv;

  pid_t id = fork();

  if (id == 0) {
    // 子进程
    for (int i = 0; environ[i]; i++) {
      printf("environ[%d]: %s\n", i, environ[i]);
    }
  }

  sleep(3);
  return 0;
}

2.本地变量和内建命令(built-in command)

本地变量:

Shell中还有一种概念叫本地变量。直接执行i=10,这样本地变量i就被创建了。echo命令和env命令都无法查看,我们需要执行set命令,在执行结果中确实能找到i=10这条本地变量。

我们可以通过export i ,把i=10写入到环境变量中

内建命令(bullit-in command):

我们知道,一般的命令在执行的时候,都是bash这个父进程创建了对应的子进程去执行的。而子进程的数据是不能直接传给父进程的。

export命令是内建命令,是B由ash自己调用函数或者系统调用完成!

五、Shell脚本

这里只做基本介绍,更详细的语法等读者可以自行搜索学习。

我们可以将一系列命令整合到一个.sh文件中,替我们依次执行完成这些命令!

test.sh:

# 指定bash路径
#!/bin/bash

touch file
ls

 很多开源项目的为了让用户方便的安装都会使用shell脚本。

更多推荐