【Linux】环境变量

目录

环境变量

一个现象的引入

总结:argv和env的配合

其他环境变量

USER和LOGNAME

HISTSIZE=1000

PWD

OLDPWN

活动环境变量的方法

创建环境变量

取消环境变量

以代码的方式获得环境变量

方法1:main函数参数打印

方法2:getenv系统调用

方法3:environ

环境变量的特性


环境变量

一个现象的引入

main函数由参数吗------有的

bash 复制代码
#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("argc = %d\n", argc);
    printf("命令行参数:\n");
    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    return 0;
}


hzx@VM-0-12-ubuntu:~$ gcc args.c -o args
hzx@VM-0-12-ubuntu:~$ ./args hello world 123
argc = 4
命令行参数:
argv[0] = ./args
argv[1] = hello
argv[2] = world
argv[3] = 123
参数 全称 含义
argc argument count 命令行参数的个数
argv argument vector 命令行参数的字符串数组

这个东西类比学习命令的时候

bash 复制代码
ls -a -l /home/hzx


argc = 4
argv[0] = "ls"
argv[1] = "-a"
argv[2] = "-l"
argv[3] = "/home/hzx"

为什么这样设计?

原因 说明
统一 所有程序用同一套机制接收参数
灵活 参数个数不限,可多可少
简单 程序内部只需遍历 argv
标准化 所有 Linux 命令都遵循这个规则

为什么系统的文件没有./,反而自己写的需要?

任何一个命令要执行他的时候要先找到他,./是指的是当前目录下,那是因为系统当中存在环境变量------PAPH,帮助找到文件。

可以通过把自己的文件放到和系统一样的路径下就可以了(要用root权限)------但不推荐

这里的PAPH环境变量,告诉系统当前文件的位置去执行。

在unbutun怎么查找环境变量的内容?------输入env,里面的结构是名称=内容

查找想要的echo $PHPY

怎么恢复?关掉unbutun重启就可以了。

那到底怎么才能把自己的文件放到系统的文件路径下,不会删掉系统文件的路径呢?

PATH=$PATH:文件路径

如何理解环境变量?

环境变量的值是被bash保存起来的,执行命令的时候是bash找到对应的路径的。bash形成一张表,叫做环境变量表,他就是指针数组。

看下图------下面一个一个的环境变量就是字符串,放到了一个指针数组里面。

这个这个指针数组可以说是形成了一张表,他是由bash形成的,例如执行ls -a -l的时候,他不是由子进程先拿到的,是先由bash拿到的,bash拿到程序的名字ls,再结合环境变量PATH,PATH里面有多个路径,把ls和PATH的多个路径进行拼接,如果命令在就创建子进程执行他。

结论:bash有两张表一个是环境变量表(argv),一个是命令行参数表(env)

环境变量最开始从哪里来的?

从配置文件来的,系统启动,bash会读取配置文件所有包括环境变量直接或间接的值,并创建环境变量表。

总结:argv和env的配合

命令行参数表(argv)和环境变量表(env)是程序启动时由 main 函数同时接收的两组信息,二者分工明确、配合紧密:argv 来自用户在命令行输入的参数,告诉程序"要做什么" ;env 来自 shell 继承的系统环境变量,告诉程序"在哪里找资源、用什么配置" 。程序运行时,先从 argv 解析出用户意图,再从 env 读取运行环境,两者结合才能正确完成任务------缺了 argv,程序不知道用户想干什么;缺了 env,程序找不到依赖的库和配置,也无法正常运行。

以 ls -l /home/hzx 为例,当你在终端敲下这条命令时,shell 会先解析它,把命令名和参数拆成 argv = ["ls", "-l", "/home/hzx"],同时把当前 shell 的环境变量(如 PATH、HOME、LANG 等)一起通过 exec 系列函数传递给新创建的 ls 进程;ls 的 main 函数收到 argc = 3 和上述 argv、env 后,会遍历 argv 识别出 -l 这个选项并设置"详细列表"标志,同时把 /home/hzx 记录为要列出的目标目录,接着它利用 env 里的 PATH 找到自己需要的动态库、利用 LANG 决定显示语言,然后调用 opendir 和 readdir 打开并读取 /home/hzx 目录内容,对每个文件调用 stat 获取权限、大小、时间等信息,最后按照 -l 要求的格式把结果输出到终端------整个过程就是 argv 告诉 ls"做什么"(详细列出 /home/hzx),env 告诉 ls"在哪找资源、用什么配置"(库路径、语言环境),二者配合完成这条命令。

其他环境变量

USER和LOGNAME

USER:当前用户

LOGNAME:登录的用户

su -:输入他的时候他会切换成root账号,对应的USER和LOGNAME都会变

bash 复制代码
su - 相当于:
  1. 退出当前 shell
  2. 以 root 身份重新登录
  3. 重新加载所有环境变量
  4. USER 和 LOGNAME 都变成 root

sudo:切换的时候USER会变,LOGNAME不变

bash 复制代码
sudo 相当于:
  1. 保持当前 shell 环境不变
  2. 临时以 root 身份执行命令
  3. USER 变成 root(有效身份变了)
  4. LOGNAME 不变(原始登录用户没变)

HISTSIZE=1000

当用上下箭头的时候,可以查看历史命令,但他只能查找最近的1000条。

PWD

记录shell的当前位置

OLDPWN

上一次shell所在的路径,每次cd到一个新的路径都会更新他

活动环境变量的方法

创建环境变量

exprot 名称=内容

将自己创建的环境变量放到环境变量表里面

取消环境变量

unset 名称

以代码的方式获得环境变量

方法1:main函数参数打印

实际上main函数有三个参数

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

env[0] = "SHELL=/bin/bash"
env[1] = "PWD=/home/hzx"
env[2] = "HOME=/home/hzx"
env[3] = "USER=hzx"
env[4] = "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
...
env[n] = NULL

直接打印可以获得环境变量的信息

参数 全称 含义
argc argument count 命令行参数个数
argv argument vector 命令行参数数组
env environment 环境变量数组

问题:这个环境变量是谁的?父进程(bash)

环境变量可以被子进程继承,也可以被孙子进程继承......------因此环境变量有全局特性

为什么要这么设计?

方法2:getenv系统调用

getenv这个也是个函数,他是根据环境变量的名字获取环境内容

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

int main() {
    char *path = getenv("PATH");
    char *home = getenv("HOME");
    char *user = getenv("USER");
    
    printf("PATH = %s\n", path);
    printf("HOME = %s\n", home);
    printf("USER = %s\n", user);
    return 0;
}

一个只有特定用户执行的程序

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

int main() {
    // 1. 从环境变量获取当前用户名
    char *user = getenv("USER");
    
    // 2. 检查是否获取成功
    if (user == NULL) {
        printf("错误:无法获取 USER 环境变量\n");
        return 1;
    }
    
    // 3. 判断是否是允许的用户
    if (strcmp(user, "hzx") == 0 || strcmp(user, "root") == 0) {
        printf("欢迎,%s!你有权限执行此程序。\n", user);
        printf("程序正在执行...\n");
        // 这里放真正要执行的逻辑
    } else {
        printf("抱歉,%s,你没有权限执行此程序。\n", user);
        printf("只有 hzx 和 root 可以执行。\n");
        return 1;
    }
    
    return 0;
}
方法3:environ

environ是一个全局变量

项目 说明
类型 char **(字符指针数组)
声明 extern char **environ
头文件 无(需要手动 extern 声明)
内容 所有环境变量
结尾 environ[n] = NULL
cpp 复制代码
#include <stdio.h>

// 声明全局变量 environ
extern char **environ;
/*这个变量在别处定义(libc 里)

这里只是声明,不分配内存

链接时找到真正的定义
*/

int main() {
    // 遍历环境变量表
    for (int i = 0; environ[i]; i++) {
        printf("environ[%d] = %s\n", i, environ[i]);
    }
    return 0;
}

如果非要选一个建议用方法3

环境变量的特性

特性 说明
全局性 所有进程都能访问
继承性 父进程传给子进程
持久性 登录期间一直存在
可修改性 可以动态设置、删除
键值对形式 KEY=VALUE 格式
字符串类型 值只能是字符串
区分大小写 PATH 和 path 不同

小概念:本地变量

他和环境变量都在bash内部使用的,但是本地变量不会传给子进程,只会在bash内部使用。

这个之前的pwd和export解释有联系,他和ls那些命令不同,是内建命令,不会依赖环境变量,因此他是由bash亲自去完成的,bash自己调用系统函数

相关推荐
可涵不会debug3 小时前
C++ std::bind 实战教程:线程池、回调场景全覆盖
linux·开发语言·c++
实点科技3 小时前
远程IO模块的柜外安装:装在什么位置、防尘罩怎么选配
运维·服务器·网络
云计算-Security3 小时前
AI 赋能运维:UniRack 主机纳管平台的架构与实践
运维·人工智能·架构
云絮.3 小时前
Spring MVC(二)
服务器·spring·mvc
青梅味猪大肠3 小时前
【操作系统-26】进程互斥软件实现-Peterson算法
linux·运维·服务器
分布式存储与RustFS3 小时前
在 Kubernetes 里跑对象存储的三个方案:Helm、Operator、以及什么时候别用 K8s
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
怪力左手3 小时前
docker+qemu创建镜像
运维·docker·容器
wdfk_prog4 小时前
Wi-Fi Direct教程 01:在 Ubuntu 搭建双 mac80211_hwsim + wpa_supplicant 2.12
linux·运维·服务器·ubuntu·ros·wifi-direct
fengkai45454 小时前
十一、MySQL 第 1‑3 章
运维·数据库·mysql
wusam4 小时前
计算机网络第二章习题解答
服务器·网络·计算机网络