【Linux】命令行参数与环境变量

张开发
2026/4/4 10:49:51 15 分钟阅读
【Linux】命令行参数与环境变量
本篇文章主要讲解 Linux 中常用的命令行参数与环境变量目录1 命令行参数2 环境变量3 总结1 命令行参数什么是命令行参数命令行参数就是在命令行中输入命令时在程序后面所带的参数。比如我们平常使用的命令ls -a -l -i其中 ls 是程序名-a、-l、-i 就是命令行参数所以其实各种命令的参数就是命令行参数。之前我们说过各个命令也是二进制可执行程序而命令行参数是可以被我们通过 main 函数来获取的所以在可执行程序中我们就可以通过判断命令行参数来执行不同的功能。比如在 ls 这个命令的实现的 C 语言程序中肯定是通过 main 函数获取了不同的命令行参数如果是 -a 命令行参数那么就会展示出所有的文件如果是 -l 参数那就会展示出文件的详细信息这样就可以实现不同的功能了。如何获取以及使用命令行参数命令行参数主要是通过 main 函数中的两个参数来获取的int main(int argc, char* argv[]); argc: 命令行参数的个数包括可执行程序的名字 argv: 是一个 char* 类型的数组每一个元素指向了对应命令行参数的字符串argv[0] 为可执行程序的名字以 NULL 结尾我们可以通过下面这个代码来验证一下//test.c #include stdio.h int main(int argc, char* argv[]) { printf(命令行参数个数: %d\n, argc); //argc 为命令行参数个数 for (int i 0; i argc; i) printf(argv[%d]: %s\n, i, argv[i]); //argv[] 以 NULL 结尾 for (int i 0; argv[i]; i) printf(argv[%d]: %s\n, i, argv[i]); return 0; }./test -a -b -c下面我们可以写一个样例代码通过这个代码理解一下 ls 的原理#include stdio.h #include string.h int main(int argc, char* argv[]) { if (argc ! 2) { printf(please input on %s -v1/v2/v3\n, argv[0]); return 1; } if (strcmp(argv[1], -v1) 0) { printf(这是功能1\n); } else if (strcmp(argv[1], -v2) 0) { printf(这是功能2\n); } else if (strcmp(argv[1], -v3) 0) { printf(这是功能3\n); } else { printf(没有该功能\n); } return 0; }我们通过不同的命令行参数实现了不同的功能ls 也是这样的。通过不同的命令行参数以实现不同的功能。为什么会有命令行参数命令行参数的存在可以使得我们在编程时就用命令行参数来实现不同的功能用户在输入命令时就可以使用命令参数来达到不同的效果。比如 ls 命令用户就可以通过对应的选项来向 ls 这个程序来传递不同的命令行参数已达到不同的效果实现了类似功能的不同表现形式。2 环境变量什么是环境变量环境变量是系统中具有一些特殊用途的全局变量具有全局属性也是一些可以用来指定操作系统运行环境的参数。比如我们使用 which 命令which lswhich 找到了 ls 所在目录那么 which 是如何找到的呢就是从 PATH 环境变量中找到的我们可以通过如下命令来查看 PATH 环境变量的内容echo $PATHPATH 这个环境变量就是记录各种可执行文件的路径的所以当我们使用命令时就可以直接通过可执行程序的名字就能执行而不用带路径。但是我们自己写的文件就是需要带上目录因为我们的路径并不在 PATH 环境变量指定的目录里面//mytest.c #include stdio.h int main() { printf(hello world\n); return 0; }直接 mytest 是运行不了的我们需要带上路径才可以但是一旦我们将 mytest 可执行程序拷贝到 PATH 环境变量指定的目录下面比如 /usr/bin/ 目录直接输入程序名就可以执行了所以PATH 环境变量的作用就是指定我们系统的可执行程序或者各种命令的搜索路径有了 PATH 环境变量我们在执行命令时就可以不同带目录直接输入可执行程序的名字也就是命令就可以直接执行命令了。其实在 Windows 系统中也是有环境变量的也是有 PathTMP 等环境变量的Windows 中这些环境变量与 Linux 中的环境变量的作用是相同的PATH 就是方便系统查找可执行程序的、TMP 是存放系统的临时文件目录等等其都是一些具有特殊用途的全局变量。如何查看环境变量1 查看一个具体环境变量的值我们可以通过在命令中输入如下命令来查看一个环境变量echo $环境变量名称其中 $ 是获取环境变量的内容。比如查看常见的环境变量PATH、HOME、PWDecho $PATH echo $HOME echo $PWD这样就可以查看相应的环境变量的内容了。2 查看所有环境变量我们可以使用下面这两个命令来获取全部环境变量env printenvenv 是 environment 的缩写正好对应的就是环境的意思。如何在代码中获取环境变量环境变量是系统中一些具有特殊用途的全局变量如果我们想在代码中使用这些特殊用途该怎么获取对应的环境变量呢1 通过 main 函数中的第三个参数 env 数组获取在 main 函数中不仅有前两个跟命令行参数相关的参数还有第三个参数是跟环境变量相关的int main(int argc, char* argv[], char* env[]);第三个变量和第二个参数类型相同都是一个 char* 类型的数组只不过第二个参数指向的是每一个命令行参数的字符串第三个变量中的每个元素指向的是每个环境变量的字符串最后以 NULL 结尾。#include stdio.h int main(int argc, char* argv[], char* env[]) { int i 0; for (; env[i]; i) printf(%s\n, env[i]); return 0; }2 通过引入第三方变量 environ 获取environ 是一个第三方变量其类型为 char**其实与上面 main 函数的第三个参数 env 的类型是一样的。这个 environ 变量会指向一张 char* 类型的环境变量表实际上就是一个 char* 类型的数组但是如果我们想要使用这个 environ 变量我们必须通过extern关键字来引入外部变量。#include stdio.h int main() { extern char** environ;//引入外部变量 int i 0; for (; environ[i]; i) printf(%s\n, environ[i]); return 0; }3 通过系统调用来获取环境变量我们可以通过 getenv 来获取环境变量也可以通过 putenv 来设置环境变量#include stdlib.h char *getenv(const char *name); name: 要获取的环境变量名字的字符串比如PATH、HOME 等 返回值 返回的是指向环境变量内容字符串的 char* 指针 #include stdlib.h int putenv(char *string); string: 为namevalue形式的字符串如果name环境变量已经存在那么就将原环境变量的值更新为value值;如果name环境变量不存在那就引入该环境变量 返回值: 如果设置成功返回0; 不成功返回非0值示例代码#include stdio.h #include stdlib.h int main() { char* pwd getenv(PWD); char* home getenv(HOME); printf(pwd: %s, home: %s\n, pwd, home); int n putenv(MYENV100); if (n ! 0) { perror(putenv); return 1; } printf(环境变量设置成功, MYENV: %s\n, getenv(MYENV)); return 0; }环境变量的使用由于每个环境变量都具有特殊功能所以我们可以使用一些环境变量来实现系统中的一些命令1 cdcd 是修改当前工作路径的命令。其中cd ~ 是进入家目录cd - 是进入最近一次被访问的目录其实这两个目录都在环境变量中保存着家目录是在 HOME 环境变量中最近一次访问目录是在 OLDPWD 环境变量中所以我们只要在程序中获取这两个环境变量再使用一个系统调用更改当前工作目录就可以了。修改当前工作目录的系统调用为 chdir其中 path 就是你要修改路径的字符串所以我们就可以通过如下程序来实现 cd 命令//mycd.c #include stdio.h #include string.h #include stdlib.h #include unistd.h int main(int argc, char* argv[]) { if (argc ! 2) { printf(Usage: %s path\n, argv[0]); return 1; } //打印更改目录之前的 pwd printf(更改前: %s\n, getenv(PWD)); const char* path argv[1]; if (strcmp(argv[1], -) 0) { //进入上一次的目录 path getenv(OLDPWD); } else if (strcmp(argv[1], ~) 0) { //进入家目录 path getenv(HOME); } //修改目录 int n chdir(path); if (n 0) { //修改失败 perror(chdir); return 2; } //打印更改之后的pwd printf(更改后: %s\n, getenv(PWD)); return 0; }如果我们这样写 mycd 命令可以发现更改路径前后打印出来的路径是不变的是因为 PWD 这个环境变量是需要实时更新的其不会自己更新而是系统会通过 getcwd 系统调用来实时更新 PWD 环境变量的内容#include unistd.h char *getcwd(char buf[.size], size_t size); buf: 指向存放当前工作路径字符串的缓冲区 size: 缓冲区 buf 的字节大小 返回值成功返回存放工作路径的缓冲区地址也就是 buf 的地址不成功返回 NULL所以我们需要通过 getcwd 来查看路径的改变通过 cd 这个示例我们可以看到有一些环境变量除非用户自己更新否则是不会改变的比如 PATH而有些环境变量是需要用过某些系统调用实时更新的比如 PWD 就是通过 getcwd 来实时更新的。2 pwdpwd 的实现就更简单了只需要我们获取一下环境变量 PWD 的值打印一下就可以了//mypwd.c #include stdio.h #include stdlib.h int main() { const char* pwd getenv(PWD); printf(%s\n, pwd); return 0; }与环境变量相关的命令1echo查看一个环境变量的值我们可以使用 echo 命令来查看具体一个环境变量的值比如 echo $PATH上面已经讲解过这里就不再赘述。2 export设置一个新的环境变量我们可以使用 export 命令来引入一个新的环境变量或者更新旧的环境变量添加环境变量: export [环境变量名称值] 更新环境变量: export PATH$PATH:your_add_path想要导入新的环境变量时必须使用 export 关键字否则添加的变量称为本地变量只在当前进程有效是无法被子进程继承的环境变量的全局属性在下一小节#include stdio.h #include stdlib.h #include unistd.h int main() { //在命令行 bash 进程中通过 export 设置 MYENV 环境变量 //在当前进程(bash的子进程)中获取 MYENV 并打印 char* myenv getenv(MYENV); printf(myenv: %s\n, myenv); return 0; }可以看到本地变量是不会被子进程继承的只有环境变量才会。3 env显示出所有的环境变量上面已经展示过用法这里就不再赘述。4 set显示本地定义的 shell 变量与环境变量设置本地变量set 命令可以显示当前 shell 中定义的所有变量以及 shell 函数包括本地变量与环境变量。我们也可以使用 set 来定义本地变量但是无法定义环境变量定义环境变量需要使用 export 导入环境变量。当然set 本身还有很多其他功能大家可以自行学习。5 unset删除一个新的环境变量unset 可以删除我们自己定义的本地变量以及环境变量但是需要注意的是unset 命令无法删除那些系统上的环境变量比如 PATHHOME 等环境变量只能删除用户自定义的本地变量或者环境变量。环境变量的全局属性环境变量是一些具有特殊功能的全局变量。那么有一些环境变量比如 PATHSHELLHOME我们并没有设置过那么这些环境变量是怎么来的呢之前我们了解过其实我们运行我们自己写的程序包括那些命令都是由 bash 进程创建子进程而来也就是 bash 进程是这些进程的父进程。我们没有设置过但是可以使用就是因为我们程序的环境变量继承于父进程 bash。bash 中有这些环境变量所以 bash 通过创建子进程的方式使得我们的程序可以继承 bash 进程的环境变量。所以环境变量是可以被子进程继承的这就是环境变量的全局属性。这里我们可能还有一个问题bash 进程的环境变量是从哪里来的呢其实 bash 的环境变量一部分是继承于其父进程有一部分是从用户的配置文件里面来的如果我们仔细查看可以看到用户的家目录下存在一些配置文件如果我们打开 .profile 文件就可以看到里面定义了 PATH 环境变量其中 .bashrc 是 bash 启动时的配置文件如果我们在文件最后添加这么一句话下次再次登录 xshell 时bash 就会读取 .bashrc 文件并打印出这句话所以环境变量是可以被子进程继承的这也就是我们没有设置过环境变量就可以使用的原因这就是环境变量的全局属性。#include stdio.h #include stdlib.h #include unistd.h #include sys/types.h int main() { //在当前进程中通过 putenv 设置一个新的环境变量 int n putenv(MYENV100); if (n ! 0) { perror(putenv); return 1; } //创建子进程并且由子进程获取 MYENV 环境变量 pid_t id fork(); if (id 0) { perror(fork); return 2; } else if (id 0) { //child char* myenv getenv(MYENV); printf(MYENV 环境变量被继承, myenv: %s\n, myenv); exit(0); } return 0; }3 总结本篇文章讲解了 Linux 系统中的命令行参数与环境变量。命令行参数是指在命令行输入命令时指向其可执行程序名字及其选项的各个字符串而环境变量是一些具有特殊用途的全局变量可以被子进程所继承具有全局属性命令行参数其实也可以被子进程所继承环境变量的存在可以使得我们在执行命令时不必带路径直接输入命令就可以执行大大提高了我们使用 Linux 系统的效率。命令行参数与环境变量具有很大的用途等待以后我们去发现与挖掘他们。

更多文章