Appearance
使用Linux环境变量
可以帮助提升Linuxshell的使用体验, 很多程序以及脚本都可以使用环境变量来获取系统信息, 存储临时的数据以及配置
什么是环境变量
bash shell用一个环境变量的特性来储存有关shell会话和工作环境的信息, 允许你在内存中存储数据, 以便程序、脚本可以找到
有两种环境变量
- 全局变量
- 局部变量
不同版本的Linux可能会有不同的环境变量, 可以从发行版文档上查看
全局环境变量
全局环境变量对于shell会话和所有的shell都是可见的, 局部变量则只是创建他的shell可见, 对于创建子shell需要父shell信息的时候有用
有很多的变量是在登陆的时候设置的, 登录的方式也会有影响
查看全局变量:
bash
$ printenv
$ env
要显示个别的环境变量可以使用printenv
命令
C
jiao@jiao-virtual-machine:~/桌面$ printenv HOME
/home/jiao
jiao@jiao-virtual-machine:~/桌面$ env HOME
env: “HOME”: 没有那个文件或目录
也可以使用echo来显示某一个环境变量的值, 在变量名字之前加上$
bash
jiao@jiao-virtual-machine:~/桌面$ echo $HOME
/home/jiao
加上一个$可以让环境变量的值变成命令的参数
bashjiao@jiao-virtual-machine:~/桌面$ ls $HOME 01_Python 公共的 模板 视频 图片 文档 下载 音乐 桌面 Makefile snap
局部环境变量
局部变量只有在设置的进程可见, Linux定义了标准的环境变量, 但是你可以设置属于自己的局部变量, 叫做用户定义局部变量
没有专门显示局部变量的命令, set命令显示所有某一个特定进程的所有环境变量, 全局变量+局部变量+用户定义局部变量
说明命令env、printenv和set之间的差异很细微。set命令会显示出全局变量、局部变量以及用户定义变量。它还会按照字母顺序对结果进行排序。env和printenv命令同set命令的区别在于前两个命令不会对变量排序,也不会输出局部变量和用户定义变量。在这种情况下,env和printenv的输出是重复的。不过env命令有一个printenv没有的功能,这使得它要更有用一些
设置用户定义变量
可以直接在bash之中设置自己的变量
设置局部用户定义变量
一旦启动bash shell或一个bash脚本, 就能创建在这个进程shell内部可见的局部变量, 使用等号进行赋值, 可以是数字或字符串
bash
jiao@jiao-virtual-machine:~/桌面$ echo $my_varible
jiao@jiao-virtual-machine:~/桌面$ my_varible=Hello
jiao@jiao-virtual-machine:~/桌面$ echo $my_varible
Hello
只要使用$my_varible就可以使用
如果要给他一个有空格的字符串, 就要用双引号, 否则就会把第二个当做新的命令
bash
jiao@jiao-virtual-machine:~/桌面$ my_varible=hello ls
1.py algorithm begin.txt c_langage helloworld helloworld_1.0_i386.deb linux-shell ll_env
所有的环境变量都使用大写, 但是在创建局部变量或者shell脚本的时候要使用小写
**注:**变量名、等号和值之间没有空格
设置的局部变量在子shell之中不能使用
设置全局的环境变量
设置的全局变量在所有的子程序之中都可以使用
设置的方法: 首先设置一个局部变量, 然后导出到全局变量, 使用export命令
bash
jiao@jiao-virtual-machine:~/桌面$ my_variable="I an jhy"
jiao@jiao-virtual-machine:~/桌面$ export my_variable
jiao@jiao-virtual-machine:~/桌面$ dash
$ echo my_variable
my_variable
$ echo $my_variable
I an jhy
$ exit
修改子shell中全局环境变量并不会影响到父shell中该变量的值
子shell甚至无法使用export命令改变父shell中全局环境变量的值
bashjiao@jiao-virtual-machine:~$ my_variable="I am JHY" jiao@jiao-virtual-machine:~$ export my_variable //全局变量 jiao@jiao-virtual-machine:~$ bash //进入子shell jiao@jiao-virtual-machine:~$ ps --forest PID TTY TIME CMD 2331 pts/0 00:00:00 bash 2372 pts/0 00:00:00 \_ bash 2379 pts/0 00:00:00 \_ ps jiao@jiao-virtual-machine:~$ echo $my_variable //可以读取 I am JHY jiao@jiao-virtual-machine:~$ my_variable="NULL" //更改 jiao@jiao-virtual-machine:~$ echo $my_variable NULL jiao@jiao-virtual-machine:~$ export my_variable //设置为全局 jiao@jiao-virtual-machine:~$ exit exit jiao@jiao-virtual-machine:~$ echo $my_variable I am JHY
删除环境变量
bash
jiao@jiao-virtual-machine:~$ echo $my_variable
I am JHY
jiao@jiao-virtual-machine:~$ unset my_variable
jiao@jiao-virtual-machine:~$ echo $my_variable
如果要用到变量,使用$;如果要操作变量,不使用$。这条规则的一个例外就是使用printenv显示某个变量的值
在处理全局环境变量时,如果你是在子进程中删除了一个全局环境变量,这只对子进程有效。该全局环境变量在父进程中依然可用。
默认的环境变量
有部分的环境变量和之前的Unix Bourne shell 兼容
还有一些自有的变量
不是每一个都会在set的时候列出, 也不是每一个都有对应的值
设置PATH环境变量
在shell输入一个外部命令的时候, shell搜索系统来找到对应的程序, PATH定义的路径就是查找的路径
bash
jiao@jiao-virtual-machine:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
使用冒号分割, 如果命令或者程序没有保存在对应的路径, 就必须使用绝对路径来查找
bash
jiao@jiao-virtual-machine:~$ PATH=$PATH:/home/jiao/桌面
jiao@jiao-virtual-machine:~$ PATH=$PATH:.
把桌面以及当前目录加入到搜索列表
定位系统环境变量
已经知道了怎么实质环境变量, 下一步是进行永久保存
当你登陆一个Linux系统的时候, 默认情况下bash会在几个文件夹中查找命令, 这些文件夹叫启动文件夹或者环境文件, 检查的文件取决于登录的方式
- 登录时作为默认登录的shell
- 作为非登录的交互式shell
- 作为运行脚本的非交互shell
登录shell
登陆的时候启动的bash shell会从五个不同的文件夹读取数据
- /etc/profile
- $HOME/.bash_profile
- $HOME/.bashrc
- $HOME/.bash_login
- $HOME/.profile
/etc/profile是默认的bash shell主启动文件, 每一个用户都会调用
要留意的是有些Linux发行版使用了可拆卸式认证模块(Pluggable Authentication Modules ,PA M)。在这种情况下,PA M文件会在bash shell启动之前处理,这些文件中可能会包含环境变量。PA M文件包括/etc/environment文件和$HOME/.pam_environment文件。PA M更多的相关信息可以在http://linux-pam.org中找到
另外的四个文件是针对用户的, 可根据个人需求定制
/etc/profile文件
只要你登录就会执行其中的命令
启动文件中会使用for语句来迭代/etc/profile.d目录下的所有文件, 这为Linux系统提供了一个放置特定应用程序启动文件的地方
bash
jiao@jiao-virtual-machine:~/桌面$ ls /etc/profile.d/ -hl
总用量 40K
-rw-r--r-- 1 root root 96 2月 26 2021 01-locale-fix.sh
-rw-r--r-- 1 root root 835 10月 8 2021 apps-bin-path.sh
-rw-r--r-- 1 root root 726 9月 3 2020 bash_completion.sh
-rw-r--r-- 1 root root 1003 8月 13 2019 cedilla-portuguese.sh
-rw------- 1 root root 241 10月 13 2021 debuginfod.csh
-rw------- 1 root root 132 10月 13 2021 debuginfod.sh
-rw-r--r-- 1 root root 349 12月 18 2020 im-config_wayland.sh
-rw-r--r-- 1 root root 1.4K 6月 27 2021 vte-2.91.sh
-rw-r--r-- 1 root root 967 6月 27 2021 vte.csh
-rw-r--r-- 1 root root 954 9月 21 2021 xdg_dirs_desktop_session.sh
有些文件与系统中的特定应用有关。大部分应用都会创建两个启动文件:一个供bash shell使用(使用.sh扩展名),一个供c shell使用(使用.csh扩展名)
$HOME目录下的启动文件
剩下的启动文件都起着同一个作用, 提供一个用户的专属启动文件, 定义用户专用的环境变量
大多数的Linux只用四个启动文件的一到两个
- $HOME/.bash_profile
- $HOME/.bashrc
- $HOME/.bash_login
- $HOME/.profile
启动的顺序, 找到一个剩下的忽略
$HOME/.bash_profile
$HOME/.bash_login
$HOME/.profile
没有$HOME/.bashrc, 因为该文件通常通过其他文件来运行
交互式shell
不是系统启动的时候启动的shell, 那么你启动的shell叫做交互式shell, 他不会像登录的shell一样运行, 但是提供了命令行提示符来输入命令
如果是交互式shell启动的文件, 就不会访问/etc/profile只会检查用户HOME目录中的.bashrc文件
非交互式shell
系统执行shell脚本的时候, 没有命令提示符, 当你在系统上运行脚本时,也许希望能够运行一些特定启动的命令
为了处理这种情况,bash shell提供了BASH_ENV环境变量, 它会检查这个环境变量来查看要执行的启动文件, 这通常包括shell脚本变量设置
如果没有, 脚本的变量会来自, 父shell设置的变量
父shell设置但是没有导出的都是局部变量, 不能被继承
环境变量持久化
放在/etc/profile中会在系统升级的时候更改
最好在/etc/profile.d目录中创建一个.sh结尾的文件
储存个人用户的shell变量是~/.bashrc文件, 但如果设置了BASH_ENV变量,那么记住,除非它指向的是$HOME/.bashrc,否则你应该将非交互式shell的用户变量放在别的地方
图形化界面组成部分(如GUI客户端)的环境变量可能需要在另外一些配置文件中设置,这和设置bash shell环境变量的地方不一样
数组变量
环境变量可以当做数组使用, 数组可以存储多个变量, 这些值可以单独引用也可以整个使用
bash
jiao@jiao-virtual-machine:/home$ mytest=(one two three four five)
jiao@jiao-virtual-machine:/home$ echo ${mytest[2]}
three
可以使用通配符*, 显示所有的值
bash
jiao@jiao-virtual-machine:/home$ echo ${mytest[*]}
one two three four five
可以使用索引改变某一个位置的值
bash
jiao@jiao-virtual-machine:/home$ mytest[2]=seven
jiao@jiao-virtual-machine:/home$ echo ${mytest[2]}
seven
可以使用unset删除某个位置的值
bash
jiao@jiao-virtual-machine:/home$ unset mytest[2]
jiao@jiao-virtual-machine:/home$ echo ${mytest[*]}
one two four five
jiao@jiao-virtual-machine:/home$ echo ${mytest[2]}
jiao@jiao-virtual-machine:/home$