本篇文章进行操作系统中环境变量的学习!!!
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性
环境变量分为二种:用户变量(局部变量)和系统变量(全局变量)
为什么指令可以直接运行,程序要加上路径(./ + 可执行文件)呢?
// 直接通过指令运行
[lyh_sky@localhost lesson11]$ ls
makefile test test.cpp
// 通过/usr/bin/运行
[lyh_sky@localhost lesson11]$ /usr/bin/ls
makefile test test.cpp
[lyh_sky@localhost lesson11]$ cat test.cpp
#include
#include
#include
#include
using namespace std;
int main()
{
while (1)
{
cout << "hello world!!!" << endl;
sleep(1);
}
return 0;
}
// 通过指令方式运行失败
[lyh_sky@localhost lesson11]$ test
bash: test: 未找到命令... // 执行一个可执行程序,必须先找到它
// 加上路径运行成功
[lyh_sky@localhost lesson11]$ ./test
hello world!!!
hello world!!!
....
在OS中,搜索可执行程序路径的环境变量是”PATH“!!!
OS是通过PATH环境变量里面的路径来搜索指令(可执行程序)的,该环境变量用冒号分隔路径
可以使用env指令查看OS中的全部环境变量
还可以使用echo 【$环境变量】来显示指定环境变量的值
如何将自己写的程序也能像指令一样不用带路径执行呢?
[lyh_sky@localhost lesson11]$ ls
makefile tes test.cpp
[lyh_sky@localhost lesson11]$ tes
bash: tes: 未找到命令...
[lyh_sky@localhost lesson11]$ sudo cp tes /usr/bin/
[lyh_sky@localhost lesson11]$ ls /usr/bin/tes
/usr/bin/tes
[lyh_sky@localhost lesson11]$ tes
hello world!!!
hello world!!!
...
2.方法二:将当前路径添加到PATH环境变量中
[lyh_sky@localhost lesson11]$ ls
makefile tes test.cpp
[lyh_sky@localhost lesson11]$ tes
bash: /usr/bin/tes: 没有那个文件或目录
[lyh_sky@localhost lesson11]$ pwd
/home/lyh_sky/Linux_Study/lesson11
[lyh_sky@localhost lesson11]$ export PATH=$PATH:/home/lyh_sky/Linux_Study/lesson11
[lyh_sky@localhost lesson11]$ echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/lyh_sky/.local/bin:/home/lyh_sky/bin:/home/lyh_sky/Linux_Study/lesson11
[lyh_sky@localhost lesson11]$ tes
hello world!!!
hello world!!!
...
如何删除环境变量呢?
[lyh_sky@localhost lesson11]$ export aaa=100
[lyh_sky@localhost lesson11]$ bbb=200
[lyh_sky@localhost lesson11]$ env | grep aaa
aaa=100
[lyh_sky@localhost lesson11]$ echo $bbb
200
[lyh_sky@localhost lesson11]$ unset aaa
[lyh_sky@localhost lesson11]$ env | grep aaa
[lyh_sky@localhost lesson11]$ unset bbb
[lyh_sky@localhost lesson11]$ echo $bbb
[lyh_sky@localhost lesson11]$
PATH : 指定命令的搜索路径
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL : 当前Shell,它的值通常是/bin/bash
HISTSIZE:OS中保存历史指令的最大数量
USER:当前登录OS的用户
main()函数可以带参数吗?最多可以带多少个?
很多人知道要带两个,分别是int argc和char* argv[]
通过以下代码可以得出:argc是指令+选项的有效数量,argv存储的指令和选项
[lyh_sky@localhost lesson11]$ ls
makefile Test test.c
[lyh_sky@localhost lesson11]$ cat makefile
Test:test.c
gcc test.c -o Test -std=c99
.PHONY:clean
clean:
rm -rf Test
[lyh_sky@localhost lesson11]$ cat test.c
#include
#include
int main(int argc, char* argv[])
{
for (int i = 0; i < argc; ++i)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
return 0;
}
[lyh_sky@localhost lesson11]$ ./Test
argv[0]: ./Test
[lyh_sky@localhost lesson11]$ ./Test -a
argv[0]: ./Test
argv[1]: -a
[lyh_sky@localhost lesson11]$ ./Test -a -b
argv[0]: ./Test
argv[1]: -a
argv[2]: -b
[lyh_sky@localhost lesson11]$ ./Test -a -b -c
argv[0]: ./Test
argv[1]: -a
argv[2]: -b
argv[3]: -c
每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串
获取环境变量的三种方法:
第一种方法:主函数第三个参数获取环境变量
[lyh_sky@localhost lesson11]$ ls
makefile Test test.c
[lyh_sky@localhost lesson11]$ cat makefile
Test:test.c
gcc test.c -o Test -std=c99
.PHONY:clean
clean:
rm -rf Test
[lyh_sky@localhost lesson11]$ cat test.c
#include
#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;
}
[lyh_sky@localhost lesson11]$ ./Test
libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明
[lyh_sky@localhost lesson11]$ ls
makefile Test test.c
[lyh_sky@localhost lesson11]$ cat makefile
Test:test.c
gcc test.c -o Test -std=c99
.PHONY:clean
clean:
rm -rf Test
[lyh_sky@localhost lesson11]$ cat test.c
#include
#include
int main(int argc, char* argv[], char* env[])
{
extern char** environ;
for (int i = 0; environ[i]; ++i)
{
printf("environ[%d]: %s\n", i, environ[i]);
}
return 0;
}
[lyh_sky@localhost lesson11]$ ./Test
运行结果与上面一样!!!
[lyh_sky@localhost lesson11]$ ls
makefile Test test.c
[lyh_sky@localhost lesson11]$ cat test.c
#include
#include
int main(int argc, char* argv[], char* env[])
{
const char* p = getenv("PATH");
printf("PATH: %s", p);
putchar('\n');
return 0;
}
[lyh_sky@localhost lesson11]$ cat makefile
Test:test.c
gcc test.c -o Test -std=c99
.PHONY:clean
clean:
rm -rf Test
[lyh_sky@localhost lesson11]$ ./Test
PATH: /usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/lyh_sky/.local/bin:/home/lyh_sky/bin
命令行中启动的进程,它们的父进程全都是bash进程
[lyh_sky@localhost lesson11]$ ls
makefile Test test.c
[lyh_sky@localhost lesson11]$ cat makefile
Test:test.c
gcc test.c -o Test -std=c99
.PHONY:clean
clean:
rm -rf Test
[lyh_sky@localhost lesson11]$ cat test.c
#include
#include
#include
#include
int main()
{
printf("PID: %d, PPID: %d\n", getpid(), getppid());
return 0;
}
[lyh_sky@localhost lesson11]$ ./Test
PID: 5353, PPID: 4848
[lyh_sky@localhost lesson11]$ ./Test
PID: 5360, PPID: 4848
[lyh_sky@localhost lesson11]$ ./Test
PID: 5367, PPID: 4848
为什么环境变量具有全局性呢?
[lyh_sky@localhost lesson11]$ cat test.c
#include
#include
#include
#include
int main()
{
printf("PID: %d, PPID: %d, aaa: %s\n", getpid(), getppid(), getenv("aaa"));
return 0;
}
[lyh_sky@localhost lesson11]$ cat makefile
Test:test.c
gcc test.c -o Test -std=c99
.PHONY:clean
clean:
rm -rf Test
[lyh_sky@localhost lesson11]$ set | grep aaa
GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/6faaa96d_439c_47ba_95cf_d349a16855b1
[lyh_sky@localhost lesson11]$ ./Test
PID: 5754, PPID: 4848, aaa: (null)
[lyh_sky@localhost lesson11]$ ls
makefile Test test.c
[lyh_sky@localhost lesson11]$ cat test.c
#include
#include
#include
#include
int main()
{
printf("PID: %d, PPID: %d, aaa: %s\n", getpid(), getppid(), getenv("aaa"));
return 0;
}
[lyh_sky@localhost lesson11]$ aaa=100
[lyh_sky@localhost lesson11]$ echo $aaa
100
[lyh_sky@localhost lesson11]$ ./Test
PID: 5869, PPID: 4848, aaa: (null)
[lyh_sky@localhost lesson11]$ ls
makefile Test test.c
[lyh_sky@localhost lesson11]$ cat test.c
#include
#include
#include
#include
int main()
{
printf("PID: %d, PPID: %d, aaa: %s\n", getpid(), getppid(), getenv("aaa"));
return 0;
}
[lyh_sky@localhost lesson11]$ echo $aaa
100
[lyh_sky@localhost lesson11]$ export aaa
[lyh_sky@localhost lesson11]$ env | grep aaa
GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/6faaa96d_439c_47ba_95cf_d349a16855b1
aaa=100
[lyh_sky@localhost lesson11]$ ./Test
PID: 5937, PPID: 4848, aaa: 100
总结:
所谓本地变量,本质就是在bash进程内部定义的变量,不会被子进程继承下去
环境变量能被getenv获取,因为环境变量会被子进程继承下去,所以可以获取到
在bash中启动的进程就是bash的子进程
Linux下大部分命令都是通过子进程完成的,但是有些指令是bash内部自己执行的(调用自己对应的函数来完成特定的功能),比如:echo、export等等,这种命令叫:“内建命令”