Linux环境变量

bash shell 使用环境变量 来存储 shell会话和工作环境的相关信息。
环境变量允许在内存中存储数据,使得shell中运行的程序或脚本能够轻松访问到这些数据。
因此,环境变量也是一种数据持久化的方式。
bash shell提供了2种环境变量:全局环境变量局部环境变量

局部环境变量

所谓局部环境变量,就是只对定义它的shell会话可见。
Linux系统也默认定义了一部分标准的局部环境变量。

查看局部环境变量

Linux无法只查看系统有哪些局部变量。
Linux提供了set命令,可以显示特定进程的所有环境变量(包括全局变量、局部变量、用户自定义变量和局部shell函数);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
root@smith-PC:~# set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="4" [2]="20" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")
BASH_VERSION='4.4.20(1)-release'
CLUTTER_IM_MODULE=xim
COLORTERM=truecolor
COLUMNS=80
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
DESKTOP_SESSION=ubuntu
DIRSTACK=()
DISPLAY=:0
EUID=0
GDMSESSION=ubuntu
HISTCONTROL=ignoredups:ignorespace
HISTFILE=/root/.bash_history
HISTFILESIZE=2000
HISTSIZE=1000
HOME=/root
HOSTNAME=smith-PC
HOSTTYPE=x86_64
XMODIFIERS=@im=ibus
_=/root
command_not_found_handle ()
{
if [ -x /usr/lib/command-not-found ]; then
/usr/lib/command-not-found -- "$1";
return $?;
else
if [ -x /usr/share/command-not-found/command-not-found ]; then
/usr/share/command-not-found/command-not-found -- "$1";
return $?;
else
printf "%s: command not found\n" "$1" 1>&2;
return 127;
fi;
fi
}

设置局部环境变量

用户可以直接在shell中设置变量,这些变量被称为用户自定义局部变量
使用变量名=值形式定义并赋值一个变量,值可以是数值字符串

建议1:使用小写字母定义局部变量,避免与系统环境变量同名;
注意1:在变量名、=和值之间不能有空格;
注意2:当用于赋值变量的字符串中含有空格时,需使用引号(单引号/双引号)包裹该字符串,以避免系统将空格后的单词误解析为单独的指令;

1
2
3
4
5
6
7
8
root@smith-PC:~# var0=Hellodibian
root@smith-PC:~# echo $var0
Hellodibian
root@smith-PC:~# var1=Hello dibian
dibian:未找到命令
root@smith-PC:~# var1="Hello dibian"
root@smith-PC:~# echo $var1
Hello dibian

父子进程无法访问各自定义的局部变量

局部变量只能在定义它的进程中使用,其他进程无法访问到;

  • 子进程访问父进程的局部变量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    root@smith-PC:~# num=99
    root@smith-PC:~# echo $num
    99
    root@smith-PC:~# bash
    root@smith-PC:~# echo $num

    root@smith-PC:~# exit
    exit
    root@smith-PC:~# echo $num
    99
    root@smith-PC:~#
  • 父进程访问子进程的局部变量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    root@smith-PC:~# bash
    root@smith-PC:~# var=99
    root@smith-PC:~# echo $var
    99
    root@smith-PC:~# exit
    exit
    root@smith-PC:~# echo $var

    root@smith-PC:~#
    因此,只能通过定义全局变量来让父子进程通信。

全局环境变量

所谓全局环境变量,就是对所有shell会话均可见。

全局环境变量通常使用全大写,以区别于用户自定义环境变量。

查看全局环境变量

使用envprintenv来查看全局环境变量。

1. 查看所有全局环境变量

1
2
3
4
5
6
7
8
9
10
11
root@smith-PC:~# env
CLUTTER_IM_MODULE=xim
LESSCLOSE=/usr/bin/lesspipe %s %s
XDG_MENU_PREFIX=gnome-
LANG=zh_CN.UTF-8
DISPLAY=:0
GNOME_SHELL_SESSION_MODE=ubuntu
COLORTERM=truecolor
USERNAME=root
...
_=/usr/bin/env
1
2
3
4
5
6
7
8
9
10
11
root@smith-PC:~# printenv
CLUTTER_IM_MODULE=xim
LESSCLOSE=/usr/bin/lesspipe %s %s
XDG_MENU_PREFIX=gnome-
LANG=zh_CN.UTF-8
DISPLAY=:0
GNOME_SHELL_SESSION_MODE=ubuntu
COLORTERM=truecolor
USERNAME=root
...
_=/usr/bin/printenv

2. 查看指定全局环境变量

查看指定全局变量时,需要用printenv,不能用env

1
2
root@smith-PC:~# printenv HOME
/root

3. 引用指定全局环境变量

可以使用$变量名的方式,获取变量的值。

1
2
root@smith-PC:~# echo $HOME
/root

$变量名也可以作为命令的参数来使用。

1
2
root@smith-PC:~# ls $HOME
BRF PDF snap 公共的 模板 视频 图片 文档 下载 音乐 桌面

设置全局环境变量

子进程无法访问到父进程的局部变量,因此可以通过创建全局环境变量使得该变量可见;
创建全局环境变量的方法:

  • 先创建局部变量
  • 再导出到全局环境中:使用export命令进行导出
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    root@smith-PC:~# var_parent=hello
    root@smith-PC:~# export var_parent
    root@smith-PC:~# bash
    root@smith-PC:~# echo $var_parent
    hello
    root@smith-PC:~# exit
    exit
    root@smith-PC:~# echo $var_parent
    hello
    root@smith-PC:~#

简化命令:export var_parent=hello

子进程也可以对父进程的全局变量进行修改,但不会影响到父进程的全局变量的值,仅在子进程中有效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@smith-PC:~# export var_parent=hello
root@smith-PC:~# echo $var_parent
hello
root@smith-PC:~# bash
root@smith-PC:~# echo $var_parent
hello
root@smith-PC:~# var_parent=1234
root@smith-PC:~# echo $var_parent
1234
root@smith-PC:~# exit
exit
root@smith-PC:~# echo $var_parent
hello
root@smith-PC:~#

此时,使用set命令查看环境变量是,就可以看到其中有一条var_parent=hello,就是刚刚创建的,当关闭该shell并重启一个shell时再查看,就会被自动删除。

env / printenv / set的区别

特征 env printenv set
查看变量类型 全局变量
局部变量
用户自定义变量
局部shell函数
全局变量 全局变量
是否可排序 按字母对结果排序 不可排序 不可排序

删除环境变量

使用unset 变量名可以删除环境变量,同理,子进程删除环境变量后,不影响父进程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@smith-PC:~# export var_parent=hello
root@smith-PC:~# echo $var_parent
hello
root@smith-PC:~# bash
root@smith-PC:~# echo $var_parent
hello
root@smith-PC:~# unset var_parent
root@smith-PC:~# echo $var_parent

root@smith-PC:~# exit
exit
root@smith-PC:~# echo $var_parent
hello
root@smith-PC:~#

默认的全局环境变量

bash shell 会预先设定一些环境变量来定义系统环境,由于bash shell与Unix Bourne shell兼容,因此保留了其定义的环境变量。

不是所有默认环境变量都在set命令中输出,若没有用到,默认环境变量并不要求必须有值。
系统使用的环境变量取决于bash shell版本,部分变量仅在bash shell 5或更高版本可用,可通过bash --version命令查看。

PATH环境变量

查看PATH环境变量

在shell中,我们通常会输入一个外部命令(如todesk),此时shell会搜索系统,从中找到对应的程序。
环境变量PATH就定义了用于查找命令和程序的目录。
使用$PATH命令查看PATH环境变量内容:

1
2
root@smith-PC:~# $PATH
bash: /opt/Qt5.14.2/5.14.2/gcc_64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

PATH:分隔多个目录,shell会在其中按顺序查找命令或程序。若这些目录中找不到输入的命令或程序,则会产生错误信息:

1
2
3
4
5
root@smith-PC:~# todesk
Command 'todesk' not found, did you mean:
command 'tkdesk' from deb tkdesk
Try: apt install <deb name>
root@smith-PC:~#

添加PATH环境变量(临时)

部分应用程序的可执行文件目录可能不在PATH中,此时可以:

  • 在shell中输入该程序的全路径;
  • 将该程序的所在目录的绝对路径添加到PATH环境变量中,格式为:PATH=$PATH:新目录的绝对路径,此时就可以直接输入程序名执行,但这种方式只是暂时性的,当退出或重启系统就会失效。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     root@smith-PC:~# ls /opt/apps
    app1 app2
    root@smith-PC:~# $PATH
    bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:
    root@smith-PC:~# PATH=$PATH:/opt/apps
    root@smith-PC:~# $PATH
    bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/apps
    root@smith-PC:~# app1
    爸爸的爸爸叫爷爷!
    root@smith-PC:~# app2
    爸爸的妈妈叫奶奶!

添加PATH环境变量(持久化)

bash与启动文件

当我们登录成功后启动bash shell时,bash会在几个文件中查找命令,这些文件称为启动文件或环境文件;
bash进程选择那些启动文件,取决于用户启动bash shell的方式。而启动bash shell共有3种方式:

方式 文件类型 文件路径
登录时作为默认登录shell 系统级 /etc/profile
用户级 $HOME/.bash_profile
$HOME/.bashrc
$HOME/.bash_login
$HOME/.profile
作为交互式shell,通过生成子shell启动 用户级 $HOME/.bashrc
作为运行脚本的非交互式shell

TODO-方式1:登录时作为默认登录shell

当用户登录Linux系统时,bash shell会作为登录shell启动;
登录shell通常从5个启动文件中读取命令:

  • /etc/profile(默认)
  • $HOME/.bash_profile
  • $HOME/.bashrc
  • $HOME/.bash_login
  • $HOME/.profile

TODO-方式2:作为交互式shell,通过生成子shell启动

TODO-方式3:作为运行脚本的非交互式shell

环境变量持久化

上述提到的启动文件,就可以帮助我们实现永久性保存全局变量或局部变量;
对于全局环境变量:可以放在/etc/profile中,但若系统更新,该文件也会更新,因此不推荐。建议在/etc/profile.d目录中创建一个.sh文件,将所有新增或修改的全局环境变量都放在该文件中;
对于用户环境变量:推荐写在$HOME/.bashrc文件中。

数组变量

环境变量也可以添加数组,用来存储多个值,既可以单独引用,也可以整体引用。
但是,数组在Linux使用频率相对较低,有可能不便于移植到其他shell环境中。

规则 命令 备注
设置数组环境变量 变量名=(值1 值2 值3) 值与值之间用空格隔开
修改指定索引元素 变量名[索引]=值
删除指定索引元素 unset 变量名[索引] 不建议使用
删除整个数组 unset 变量名
引用首个数组元素 echo $变量名
引用指定索引元素 echo $(变量名[索引])
引用整个数组 echo $(变量名[*])