环境变量——PATH - 指南

        今天我们要学习的是Linux下,系统命令的本质!以及其让命令实现的原理!

        手搓系统命令基础知识之环境变量PATH!


手搓命令的基础知识

        先说结论:所谓命令,只是特定目录下的普通文件系统执行的命令(如 ls、mkdir等)只是系统去特定目录下运行指定命令所对应的文件程序:(我们可以通过which命令查看指定命令的文件所在路径)

        可以看到这些命令的路径都在 /usr/bin 路径下,而我们平时执行的代码只能在代码所在目录下进行:如下图我们要执行可执行程序text,只能在当前路径执行,无法在其他路径执行(除去你指定路径才能在其他路径执行)。

        系统可执行的命令,是因为系统能在指定路径下找到该命令程序,那我们能不能也把特定程序加入系统的指定路径下,使我们在其他路径下也能调用我们自定的命令,以此形成对应的可执行命令?

        输入命令:

cp 文件名 /usr/bin

可能会遇到权限问题,问题如下:

cp: cannot create regular file '目标文件': Permission denied

我们可以通过调整文件权限解决:

输入命令:

sudo cp 文件名 /usr/bin

或者修改文件的权限:

chmod 755 目标文件

        当我们成功把我们的可执行程序添加到系统能识别的指定路径下后,就意味着我们成功制造了个系统命令,并且在任意目录下都能直接调用。


附加知识

为何我们每次执行当前目录的可执行程序需要在执行程序前加上 ./ 才能运行,如图展示:(我们要运行可执行程序text)

        原因是:./ 为我们识别可执行程序提供了指定的路径(即定位在当前路径下寻找指定可执行程序)。

        而不加 ./ 时,系统默认认为该可执行程序为系统指定路径下的可执行程序。

        所以加不加 ./ 是为了区分系统程序和当前目录下的程序


环境变量

         环境变量(environmentvariables)⼀般是指在操作系统中⽤来指定操作系统运⾏环境的⼀些参数。

环境变量的作用:我们在编写代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,⽣成可执⾏程序,原因就是有相关环境变量帮助编译器进⾏查找。

环境变量通常具有某些特殊⽤途,还有在系统当中通常具有全局特性

        命令行获取环境变量的代码:

env

        命令行查看指定环境变量的方法:

echo $变量名

与环境变量相关的命令

  • echo:显示某个环境变量值。
  • export: 设置⼀个新的环境变量。
  • env:显示所有环境变量。
  • unset:清除环境变量。
  • set:显示本地定义的shell变量和环境变量。

        环境变量的组织方式:(这张图片,能在代码调用环境变量时可以直观感觉到是如何获取变量的)

        每个程序都会收到⼀张环境表,环境表是⼀个字符指针数组,每个指针指向⼀个以’\0’结尾的环境字符串。


c/c++与环境变量

 代码获取环境变量:

方法一:

        在c/c++中,main可以传入三个参数,其中最后一个参数env即为环境变量的参数(排列方式与上边环境变量的组织方式相同)。

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

        环境变量具有全局性:bash进程的环境变量从系统配置文件中获得,然后环境变量能被继承,即子进程也可以继承到相应的环境变量表,所以其具有全局性。

方法二:

        通过第三方变量environ获取。

        (libc中定义的全局变量environ( char **environ )指向环境变量表,environ没有包含在任何头⽂件中,所以在使⽤时要⽤ extern声明)

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

方法三:

        通过getenv函数获取指定变量。(日常操作中最常用的)

        通常环境变量是通过 name=value 的形式给出的,使用 environ 指针打印出的所有的环境变量的形式就是如此。通过使用 getenv 函数可以给出 name 来获得 value 的值,并实现打印环境变量。

        要带头文件 #include<stdlib.h>。

#include
#include
#include
int main()
{
    char *whoami = getenv("USER");
    printf("whoami = %s",whoami);
    char *path = getenv("PATH");
    printf("path = %s",path);
    return 0;
}

        由此我们便得到指定的环境变量:

        获取环境变量后使用的案例展示:

#include
#include
#include
#include
int main()
{
    char *whoami = getenv("USER");
    printf("whoami = %s\n",whoami);
    if(strcmp(whoami,"root")==0)
    {
        printf("whoami = %s\n",whoami);
        printf("运行该执行指令\n");
    }
    else
    {
        printf("whoami = %s\n",whoami);
        printf("不准执行该指令\n");
    }
    return 0;
}

       如我们可以获取当前用户信息,如果是指定用户则可以执行该指令,如果不是则不可以执行该指令。


getenv函数配合putenv函数改变环境变量:

#include
#include
#include
int main(void){
    // 定义字符指针:path用于存储拼接后的PATH环境变量,ptr用于临时存储原PATH值
    char *path,*ptr;
    // 定义循环变量i,用于遍历环境变量数组
    int i=0;
    // 获取系统环境变量中"PATH"的值,返回指向该值的指针
    ptr=getenv("PATH");
    // 为path分配内存:原PATH长度 + "PATH="(5个字符) + "c:\\temp"(7个字符) + 字符串结束符'\0'
    // 这里+15是预留足够空间,确保拼接后不会越界
    path=malloc(strlen(ptr)+15);
    // 先将"PATH="复制到path中,作为新环境变量的键名前缀
    strcpy(path,"PATH=");
    // 将原PATH的值拼接到path后(即"PATH=原PATH内容")
    strcat(path,ptr);
    // 在PATH末尾追加新路径"c:\\temp"(即"PATH=原PATH内容c:\\temp")
    strcat(path,"c:\\temp");
    // 将拼接后的path设置为新的环境变量(覆盖原PATH)
    putenv(path);
    // 遍历全局环境变量数组environ,打印所有环境变量
    // environ数组以NULL结尾,当environ[i]为NULL时结束循环
    while(environ[i]){
        printf("%s\n",environ[i++]);
    }
    return 0;
}


PATH

        看完了环境变量,回归正题,接着学习我们的PATH是什么。

        除了上面我们把命令文件放入系统能识别的路径下,还有没有其他方法能让系统识别到我们设置的命令文件?

        有!我们可以给系统提供识别路径,当我们调用命令时,系统也会在我们添加的路径下进行查找识别!

        在系统中,存在称为 PATH 的环境变量,其记录了我们运行命令时系统查找命令的路径。


查看PATH

        Linux下,查看系统命令识别路径的代码:

echo $PATH

路径之间的冒号(:)为分隔符。


设置PATH

        设置PATH也分临时生效与永久生效两种,临时生效一般用于测试命令,永久生效用于长时间使用。


临时修改

        直接在终端执行 export 命令修改,关闭终端或重启 Shell 后失效。

# 添加单个路径到 PATH 末尾(推荐,避免覆盖原有路径)
export PATH=$PATH:/新路径/目录
# 示例:添加当前目录(.)到 PATH
export PATH=$PATH:.
# 示例:添加自定义目录 /usr/local/mybin
export PATH=$PATH:/usr/local/mybin
# 若需添加到 PATH 开头(优先查找该路径)
export PATH=/新路径/目录:$PATH

注意:不要直接执行 export PATH=/新路径,这会覆盖原有 PATH,导致系统命令(如 ls、cd)无法执行!

        当然不用慌,可以试着重启。

        如果无法改会原来的路径,那可以去开一个正常的账号,复制那个账号的路径回来覆盖即可。


永久修改

        需修改 Shell 的配置文件,修改后需重新加载配置或重启 Shell 生效。

        永久修改也分为对当前用户生效和对所有用户生效。

对当前用户生效

第一步:在命令行打开相应文件

# 用文本编辑器打开 .bashrc
vim ~/.bashrc

第二步:在文件末尾添加路径

# 示例:添加 /usr/local/mybin 到 PATH
export PATH=$PATH:/usr/local/mybin

第三步:保存退出后,让配置立即生效

# Bash 执行
source ~/.bashrc
# 或
. ~/.bashrc

对所有用户生效(系统级)

第一步:编辑全局配置文件(需 sudo)

# 编辑 /etc/profile
sudo vim /etc/profile
# 或编辑 /etc/environment(无需 export,直接写键值对)
sudo vim /etc/environment

第二步:添加路径(以 /etc/profile 为例,如果是/etc/environment 只需要直接添加即可)

        进入/etc/profile后在尾部添加下方代码即可:

export PATH=$PATH:/系统级新路径

第三步:保存退出后,需重启系统或执行以下命令生效(对所有用户)

source /etc/profile

测试图片:我以添加路径 /root/test1 为例,用 sudo vim /etc/profile 命令进行示范:


        由此便学习完了PATH的定义,我们便可以开启手搓系统命令的重要一步!

总结

        Linux下系统命令的本质是一个可执行文件,而系统通过环境变量PATH来记录相应命令的执行文件的路径,当调用命令时,系统即在其记录路径下寻找相应命令文件并运行。我们可以通过添加路径使系统对我们自制命令进行搜索执行!以此做到手搓系统命令的目的。


        今天的学习到此结束\\\\٩( 'ω' )و ////

posted @ 2025-12-27 10:48  gccbuaa  阅读(0)  评论(0)    收藏  举报