Linux:环境变量
目录
一、补充知识:命令行参数
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:程序所在路径
这个命令可以看成三级:
- 第一级,PATH=程序所在路径。这条命令会临时用程序所在路径覆盖PATH中所有路径,此时,大部分命令都无法使用了。由于是临时的,重新打开bash(命令行窗口)就能恢复。
- 第二级,PATH=$PTAH:程序所在路径。这样写系统就会在PATH添加一条这个程序所在的路径,但也是临时的。
- 第三级,即完整命令,在保证第二级的基础上能让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脚本。
更多推荐
所有评论(0)