Linux环境变量详解

文章目录

  • [1. 前言](#1. 前言)
  • [2 什么是PATH环境变量](#2 什么是PATH环境变量)
  • [3. 如何添加PATH环境变量](#3. 如何添加PATH环境变量)
  • [4. 系统中的其他环境变量](#4. 系统中的其他环境变量)
  • [5. 环境变量的由来](#5. 环境变量的由来)
  • [6. 环境变量的基本操作](#6. 环境变量的基本操作)
    • [6.1 设置环境变量](#6.1 设置环境变量)
    • [6.2 通过getenv获取环境变量](#6.2 通过getenv获取环境变量)
    • [6.3 环境变量的应用场景](#6.3 环境变量的应用场景)
  • [7. 通过命令行参数获取环境变量](#7. 通过命令行参数获取环境变量)

1. 前言

本篇文章将以PATH环境变量为例来对整个Linux环境变量进行学习理解。

本文着重讲解了什么是PATH环境变量、如何添加PATH环境变量、系统中的其他环境变量、环境变量的由来、环境变量的基本操作以及命令行参数中环境变量的体现。

2 什么是PATH环境变量

Linux中的各种指令本质上是/usr/bin/目录下的一个个可执行程序,和我们自己编写的可执行程序没有任何区别:

但是我们发现,执行我们自己的程序时需要指定路径,但是执行Linux中的各种指令却不需要指定路径:

这是因为系统中存在PATH环境变量,PATH中存放着这些指令的地址 。当我们使用这些指令时,系统会自动去PATH中寻找对应指令,如果找到了就执行,找不到就报错command not found

3. 如何添加PATH环境变量

我们可以使用echo $PATH来查看PATH环境变量中包含的内容:

注:PATH中不同路径之间用:分割。

我们也可以通过向PATH中添加内容来让我们自己的程序可以不需要指定路径就能被执行

==法一: ==直接将程序添加到/usr/bin/目录下(不建议使用这种方法,因为我们写的程序没有经过测试,容易污染指令池)。

==法二: ==使用export命令将当前可执行程序的路径导入到PATH中。

法二相关说明:

  1. 其中的$PATH代表之前PATH中内容,:之后的为新添加的内容。注意不要直接export PATH=/home/czh/practice,这样会把之前的PATH覆盖掉,使得Linux中的各种指令必须指定路径使用。
  2. PATH中不能由空格,因为Linux中以空格为分隔符。
  3. 使用export命令声明,变量只在**当前的shell(BASH)或其子shell(BASH)**下是有效的,在关闭shell后失效,再打开新shell时就没有这个变量,需要使用的话还需要重新定义。

4. 系统中的其他环境变量

PATH环境变量只是系统中众多环境变量的一种,除了PATH,我们还有许多其他环境变量,且不同的环境变量有不同的功能,也适用于不同的场景,比如:

  • HOSTNAME:主机名
  • USER:当前用户名
  • PWD:当前系统路径
  • HOME:当前用户的家目录
  • HISTSIZE:shell能记忆的最多历史命令的条数

我们可以使用env命令来查看系统中所有的环境变量:

5. 环境变量的由来

ls -al /home/czh可以发现家目录下存在两个隐藏文件.bash_profile.bashrc

实际上,当我们在登录shell时,操作系统会让我们当前的shell进程执.bash_profile中的内容,而.bash_profile又会调用执行.bashrc,它们会将对应的环境变量导入到shell进程的上下文环境中 。所以,如果我们上面不小心将$PATH覆盖掉了也不用担心,重新登录shell就好了。

至此,环境变量的定义如下:

环境变量是操作系统为了满足不同的应用场景,预先在系统内设置的一大批全局变量,这些变量往往具有特殊功能,且能够一直被bash以及bash的子进程访问。

注:环境变量具有全局属性的根本原因是环境变量会被子进程继承。

6. 环境变量的基本操作

6.1 设置环境变量

Linux命令行其实是可以定义变量的,但是以这种方式定义出来的变量是本地变量,即只在bash进程中有效,而不是环境变量,因为环境变量具有全局属性:

我们可以使用export直接定义环境变量,也可以使用它将已存在的本地变量导为环境变量:

我们可以使用set命令来查看所有变量,包括环境变量和本地变量;使用 unset 来取消变量,包括环境变量和本地变量:

6.2 通过getenv获取环境变量

我们可以使用echo $环境变量名来获取特定的环境变量,也可以通过getenv()函数来获取环境变量:

其中name是我们要获取的环境变量的名称,如果获取成功就返回该环境变量的具体内容,失败就返回null

有了getenv函数后,我们就可以自己编写系统中的某些指令了,比如pwd

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

#define MYPWD "PWD"

int main()
{
    char* env = getenv(MYPWD);
    printf("%s\n", env);
    return 0;
}

6.3 环境变量的应用场景

我们上面提到,环境变量是操作系统为了满足不同的应用场景,预先在系统内设置的一大批全局变量。其中PATH是为了满足我们指令路径搜索的需求,而除了指令需求之外还有许多其他需求,其中非常重要的一个就是身份认证。

我们以一个例子说明:

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

#define USER "USER"

int main()
{
    char* who = getenv(USER);
    if(strcmp(who, "root") == 0)
    {
        printf("Operation success!\n");
    }
    else 
    {
        printf("Permission denied!\n");
    }
    return 0;
}

注:这里要使用su -,而不能使用su,因为su -会重新登录shell,此时shell会重新加载环境变量,让$USERczh变为root,而su只是把用户身份切换为root

我们可以在程序内部通过getenv函数来获取当前的Linux用户,然后判断其是否具备某种权限,再执行对应操作,另外,我们还可以通过stat来获取一个文件的其他属性,比如读写执行等,然后根据这些属性判断一个用户是否能对该文件进行操作:

7. 通过命令行参数获取环境变量

我们上面提到,程序可以通过getenv函数来获取环境变量,其实除了getenv函数,程序还可以通过命令行参数传递来获取环境变量。

学过C语言的同学应该都知道,main函数其实是有参数的,且这些参数通过命令行传递:

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

其中argv是一个指针数组,数组里面的每一个元素都指向一个字符串,argc用来指定数组元素的个数;它们配合使用可以实现类似于ls -a -l -d选项的功能。

而指针数组env就是用于接受父进程传递过来环境变量的参数,我们可以通过在main函数中打印env中的内容来验证它:

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

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

程序也可以通过环境表environ来获取环境变量

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

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

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

注:environ是一个全局的外部变量,所以切记使用前要用extern关键字进行声明,然后再使用。


相关推荐
cv高级工程师YKY几秒前
SRE - - PV、UV、VV、IP详解及区别
大数据·服务器·uv
眠修30 分钟前
Kuberrnetes 服务发布
linux·运维·服务器
BAOYUCompany2 小时前
暴雨服务器成功中标华中科技大学集成电路学院服务器采购项目
运维·服务器
鳄鱼皮坡3 小时前
仿muduo库One Thread One Loop式主从Reactor模型实现高并发服务器
运维·服务器
即将头秃的程序媛3 小时前
centos 7.9安装tomcat,并实现开机自启
linux·运维·centos
fangeqin4 小时前
ubuntu源码安装python3.13遇到Could not build the ssl module!解决方法
linux·python·ubuntu·openssl
小Mie不吃饭4 小时前
FastAPI 小白教程:从入门级到实战(源码教程)
运维·服务器
爱奥尼欧5 小时前
【Linux 系统】基础IO——Linux中对文件的理解
linux·服务器·microsoft
戒不掉的伤怀5 小时前
【Navicat 连接MySQL时出现错误1251:客户端不支持服务器请求的身份验证协议;请考虑升级MySQL客户端】
服务器·数据库·mysql
超喜欢下雨天5 小时前
服务器安装 ros2时遇到底层库依赖冲突的问题
linux·运维·服务器·ros2