今天我们要学习的是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来记录相应命令的执行文件的路径,当调用命令时,系统即在其记录路径下寻找相应命令文件并运行。我们可以通过添加路径使系统对我们自制命令进行搜索执行!以此做到手搓系统命令的目的。
今天的学习到此结束\\\\٩( 'ω' )و ////

