环境变量是存储有关shell会话和工作环境的信息,环境变量允许脚本轻松访问他们,环境变量分为全局变量
和局部变量
。
全局环境变量对于shell会话和所有生成的子shell都是有效的,局部变量则只对变量创建的shell有效。要查看全局变量可以使用env
或者printenv
命令。
aitian@aitian-CW65S:~/at/shell$ printenv
LC_PAPER=zh_CN.UTF-8
XDG_VTNR=7
ORBIT_SOCKETDIR=/tmp/orbit-aitian
XDG_SESSION_ID=c2
LC_ADDRESS=zh_CN.UTF-8
CLUTTER_IM_MODULE=xim
IBUS_DISABLE_SNOOPER=1
TERMINATOR_UUID=urn:uuid:08541795-c8ff-4ab7-8692-dcb8925f822f
LC_MONETARY=zh_CN.UTF-8
如果想要查看指定的变量:
aitian@aitian-CW65S:~/at/shell$ printenv HOME
/home/aitian
aitian@aitian-CW65S:~/at/shell$ echo $HOME
/home/aitian
局部环境变量只能在定义它们的进程中可见,set命令会显示进程设置的所有环境变量,包括全局环境变量,局部环境变量和用户自定义变量。比如输入:
aitian@aitian-CW65S:~/at/shell$ a=xiangcunaiqing
aitian@aitian-CW65S:~/at/shell$ set|grep xiangcunaiqing
a=xiangcunaiqing
aitian@aitian-CW65S:~/at/shell$ env|grep xiangcunaiqing
aitian@aitian-CW65S:~/at/shell$
set命令会显示出全局变量,局部变量和用户自定义变量,同时set命令会对结果进行排序,不过env和printenv不会对结果进行排序,也不会输出局部变量和用户自定义变量
。
可以在shell中设置变量,比如创建当前shell进程内有效的局部变量,比如:
aitian@aitian-CW65S:~$ echo $variable
aitian@aitian-CW65S:~$ variable=str_test
aitian@aitian-CW65S:~$ echo $variable
str_test
这个局部变量只能在当前的shell中有效,在其他的shell中无法访问。比如:
aitian@aitian-CW65S:~$ var=xiangcun
aitian@aitian-CW65S:~$ echo $var
xiangcun
aitian@aitian-CW65S:~$ bash
aitian@aitian-CW65S:~$ echo $var
父进程设置的局部变量在子进程中是无法访问的,子进程设置的局部变量在父进程也是无法访问的。如果想要父进程的变量在子进程也可以访问,那么必须使用全局变量,使用export导出全局变量。
aitian@aitian-CW65S:~$ variable1="xiang cun ai qing"
aitian@aitian-CW65S:~$ echo $variable
str_test
aitian@aitian-CW65S:~$ export variable
aitian@aitian-CW65S:~$ bash
aitian@aitian-CW65S:~$ echo $variable
str_test
aitian@aitian-CW65S:~$ exit
exit
aitian@aitian-CW65S:~$ echo $variable
str_test
要注意,在父进程导出的全局变量,子进程可以访问,但是如果在子进程修改这个全局变量的值,不会影响父进程中该全局变量的值。比如:
aitian@aitian-CW65S:~$ var2="liu lao gen"
aitian@aitian-CW65S:~$ echo $var2
liu lao gen
aitian@aitian-CW65S:~$ export var2
aitian@aitian-CW65S:~$ bash
aitian@aitian-CW65S:~$ echo $var2
liu lao gen
aitian@aitian-CW65S:~$ var2="gen lao liu"
aitian@aitian-CW65S:~$ echo $var2
gen lao liu
aitian@aitian-CW65S:~$ exit
exit
aitian@aitian-CW65S:~$ echo $var2
liu lao gen
可以看出子进程修改了全局环境变量的值,但是父进程该全局变量的值并没有改变。这是因为实际上,全局变量是父进程继承给子进程的,可以理解子进程的内存空间里面也有这个值,并且其初始值就是父进程中设置的值。所以说,这个全局变量是继承的。如果我们重新打开一个新的shell,是无法访问其他shell export出来的变量的,因为这之间没有继承关系。
如果在子进程中export
一个全局变量,在父进程中无法访问这个全局变量,因为父进程无法继承子进程中的变量。
aitian@aitian-CW65S:~$ echo $var
aitian@aitian-CW65S:~$ bash
aitian@aitian-CW65S:~$ var=123
aitian@aitian-CW65S:~$ export var
aitian@aitian-CW65S:~$ echo $var
123
aitian@aitian-CW65S:~$ exit
exit
aitian@aitian-CW65S:~$ echo $var
全局变量也可以删除,使用unset命令,比如:
aitian@aitian-CW65S:~$ var=123
aitian@aitian-CW65S:~$ export var
aitian@aitian-CW65S:~$ printenv var
123
aitian@aitian-CW65S:~$ unset var
aitian@aitian-CW65S:~$ printenv var
aitian@aitian-CW65S:~$
当在shell中输入一个外部命令的时候,shell怎么去找这个程序在哪里呢?PATH环境变量定义了用于进行程序查找的目录,比如:
aitian@aitian-CW65S:~$ printenv PATH|sed -n 's/:/\n/g p'
/opt/ros/kinetic/bin
/usr/lib/jvm/java-8-openjdk-amd64/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/home/aitian/GoProject
/usr/local/go/bin
这里面的路径用冒号分隔开,这里使用了sed命令换行显示。可以把某个目录加到PATH环境变量中,比如:
aitian@aitian-CW65S:~$ printenv PATH|sed -n 's/:/\n/g p'
/opt/ros/kinetic/bin
/usr/lib/jvm/java-8-openjdk-amd64/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/home/aitian/GoProject
/usr/local/go/bin
aitian@aitian-CW65S:~$ PATH=$PATH:/home/root
aitian@aitian-CW65S:~$ printenv PATH|sed -n 's/:/\n/g p'
/opt/ros/kinetic/bin
/usr/lib/jvm/java-8-openjdk-amd64/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/home/aitian/GoProject
/usr/local/go/bin
/home/root