Linux环境变量

什么是环境变量

bash shell使用环境变量来存储shell会话和工作环境的相关信息(这也是被称作环境变量的原因)。

bash shell中有两种环境变量。

​ ·全局变量

​ ·局部变量

全局环境变量

全局环境变量对于shell会话和所有生成的子shell都是可见的。局部环境变量则只对创建它的shell可见。

可以使用env命令或printenv命令来查看全局变量:

[root@Wesuiliye ~]# env
XDG_SESSION_ID=2998
HOSTNAME=Wesuiliye
TERM=xterm-256color
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=111.111.111.11 42623 22
SSH_TTY=/dev/pts/2
JRE_HOME=/data/jdk-19.0.2+7/jre
......
[root@Wesuiliye ~]# printenv 
XDG_SESSION_ID=2998
HOSTNAME=Wesuiliye
TERM=xterm-256color
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=111.111.111.11 42623 22
SSH_TTY=/dev/pts/2
JRE_HOME=/data/jdk-19.0.2+7/jre
USER=root

要显示个别环境变量的值,可以使用printenv命令,但不要使用env命令:

[root@Wesuiliye ~]# printenv HOME
/root     
[root@Wesuiliye ~]# env HOME
env: HOME: No such file or directory

也可以使用echo命令显示变量的值。在引用某个环境变量时,必须在该变量名前加上美元符号($):

[root@Wesuiliye ~]# echo $HOME
/root

在变量名前加上$ 它还能让变量作为其他命令的参数:

[root@Wesuiliye ~]# ll $HOME
total 20
-rw-r--r-- 1 root root    0 Apr 29 22:26 123
drwxr-xr-x 2 root root 4096 May  1 00:11 data
drwxr-xr-x 2 root root 4096 Apr 28 18:24 java
drwxr-xr-x 3 root root 4096 Apr 28 18:28 MCserver
drwxr-xr-x 3 root root 4096 Apr  9 09:55 New_dir
drwxr-xr-x 6 root root 4096 Apr 22 10:21 Nonebot

局部环境变量

顾名思义,局部环境变量只能在定义它的进程中可见。

定义自己的局部变量,这些变量被称为用户自定义局部变量

没有那条指令可以只显示局部变量,set命令可以显示特定进程的所有环境变量,既包括局部变量、全局变量,也包括用户自定义变量:

[root@Wesuiliye ~]# set | tail
{ 
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}
quote_readline () 
{ 
    local quoted;
    _quote_readline_by_ref "$1" ret;
    printf %s "$ret"
}
[root@Wesuiliye ~]# 

设置用户自定义变量

可以在bash shell中直接设置自己的变量

设置局部用户自定义变量

启动bash shell(或者执行shell脚本)之后,就能创建仅对该shell进程可见的局部用户自定义变量。可以使用等号为变量赋值,值可以是数值或字符串:

[root@Wesuiliye ~]# my_variable=Hello
[root@Wesuiliye ~]# echo $my_variable 
Hello
[root@Wesuiliye ~]# 

如果用于赋值的字符串包含空格,则必须用单引号或双引号来界定该字符串的起止:

[root@Wesuiliye ~]# my_variable=Hello World
bash: World: command not found...
[root@Wesuiliye ~]# my_variable="Hello World"
[root@Wesuiliye ~]# echo $my_variable 
Hello World
[root@Wesuiliye ~]# 

如果没有引号,则bash shell会将下一个单词[插图](World)视为另一个要执行的命令。注意,你定义的局部变量用的是小写字母,而系统环境变量用的都是大写字母。

变量名区分大小写。坚持使用小写字母命名用户自定义的局部变量,能够让你避免不小心与系统环境变量同名可能带来的灾难。

在变量名、等号和值之间没有空格。如果在赋值表达式中加上了空格,那么bash shell会将值视为单独的命令:

[root@Wesuiliye ~]# my_variable = "Hello World"
bash: my_variable: command not found...
[root@Wesuiliye ~]# 

设置好局部变量后,就能在shell进程中随意使用了。但如果又生成了另一个shell,则该变量在子shell中不可用:

[root@Wesuiliye ~]# my_variable="Hello World"
[root@Wesuiliye ~]# echo $my_variable 
Hello World
[root@Wesuiliye ~]# bash
[root@Wesuiliye ~]# echo $my_variable

[root@Wesuiliye ~]# exit
exit
[root@Wesuiliye ~]# echo $my_variable 
Hello World
[root@Wesuiliye ~]# 

如果在子进程中设置了一个局部变量,那么一旦退出子进程,该局部变量就不能用了

设置全局环境变量

全局环境变量在设置该变量的父进程所创建的子进程中都是可见的。创建全局环境变量的方法是先创建局部变量,然后再将其导出到全局环境中。

这可以通过export命令以及要导出的变量名(不加$符号)来实现:

[root@Wesuiliye ~]# my_variable="I am Global now"
[root@Wesuiliye ~]# export my_variable
[root@Wesuiliye ~]# echo $my_variable 
I am Global now
[root@Wesuiliye ~]# bash
[root@Wesuiliye ~]# echo $my_variable 
I am Global now
[root@Wesuiliye ~]# exit
exit
[root@Wesuiliye ~]# echo $my_variable 
I am Global now
[root@Wesuiliye ~]# 

以将设置变量和导出变量放在一个命令里完成。

[root@Wesuiliye ~]# export my_variable="I am Global now"
[root@Wesuiliye ~]# echo $my_variable 
I am Global now
[root@Wesuiliye ~]# 

修改子shell中的全局环境变量并不会影响父shell中该变量的值:

[root@Wesuiliye ~]# export my_variable="I am Global now"
[root@Wesuiliye ~]# echo $my_variable 
I am Global now
[root@Wesuiliye ~]# 
[root@Wesuiliye ~]# bash
[root@Wesuiliye ~]# echo $my_variable 
I am Global now
[root@Wesuiliye ~]# my_variable="NULL"
[root@Wesuiliye ~]# echo $my_variable 
NULL
[root@Wesuiliye ~]# exit
exit
[root@Wesuiliye ~]# echo $my_variable 
I am Global now
[root@Wesuiliye ~]# 

这种改变仅在子shell中有效,并不会反映到父shell环境中。子shell甚至无法使用export命令改变父shell中全局环境变量的值

删除环境变量

既然可以创建新的环境变量,自然也能删除已有的环境变量。可以用unset命令来完成这个操作。在unset命令中引用环境变量时,记住不要使用$。

[root@Wesuiliye ~]# export my_variable="I am Global now"
[root@Wesuiliye ~]# echo $my_variable 
I am Global now
[root@Wesuiliye ~]# unset my_variable 
[root@Wesuiliye ~]# echo $my_variable

[root@Wesuiliye ~]#

提示 在涉及环境变量名时,什么时候该使用$,什么时候不该使用$,实在让人摸不着头脑。只需记住一点:如果要用到(doing anything with)变量,就使用$;如果要操作(doing anything to)变量,则不使用$。这条规则的一个例外是使用printenv显示某个变量的值。

如果是在子进程中删除了一个全局环境变量,那么该操作仅对子进程有效。该全局环境变量在父进程中依然可用:

[root@Wesuiliye ~]# export my_variable="i am Global now"
[root@Wesuiliye ~]# echo $my_variable 
i am Global now
[root@Wesuiliye ~]# bash
[root@Wesuiliye ~]# echo $my_variable 
i am Global now
[root@Wesuiliye ~]# unset my_variable 
[root@Wesuiliye ~]# echo $my_variable 

[root@Wesuiliye ~]# exit
exit
[root@Wesuiliye ~]# echo $my_variable 
i am Global now
[root@Wesuiliye ~]# 

和修改变量一样,在子shell中删除全局变量后,无法将效果反映到父shell中。

默认的shell环境变量

查看bash版本

bash --version
或
echo $BASH_VERSION

当前bash进程号

echo $BASHPID

当前用户的有效用户ID

echo $EUID

shell查找命令时使用的目录列表

echo $PATH

设置PATH环境变量

当你在shell CLI中输入一个外部命令时,shell必须搜索系统,从中找到对应的程序。PATH环境变量定义了用于查找命令和程序的目录。

[root@Wesuiliye ~]# echo $PATH
/data/jdk-19.0.2+7/bin:/data/python38/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/.local/bin:/root/bin:/root/.local/bin

如果命令或者程序所在的位置没有包括在PATH变量中,那么在不使用绝对路径的情况下,shell是无法找到的。

添加到现有的PATH环境变量中,无须从头定义。PATH中各个目录之间以冒号分隔。只需引用原来的PATH值,添加冒号(:),然后再使用绝对路径输入新目录即可。

[root@Wesuiliye ~]# PATH=$PATH:/root/123 
[root@Wesuiliye ~]# echo $PATH
/data/jdk-19.0.2+7/bin:/data/python38/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/.local/bin:/root/bin:/root/.local/bin:/root/.local/bin:/root/123

1.如果希望程序位置也可用于子shell,则务必确保将修改后的PATH环境变量导出。

2.对于PATH变量的修改只能持续到退出或重启系统。这种效果并不能一直奏效

定位系统环境变量

当登录Linux系统启动bash shell时,默认情况下bash会在几个文件中查找命令。这些文件称作启动文件环境文件。bash进程的启动文件取决于你启动bash shell的方式。

启动bash shell有以下3种方式:

​ ·登录时作为默认登录shell;

​ ·作为交互式shell,通过生成子shell启动;

​ ·作为运行脚本的非交互式shell。

登录shell

bash shell会作为登录shell启动。登录shell通常会从5个不同的启动文件中读取命令。

·/etc/profile
·$HOME/.bash_profile
·$HOME/.bashrc
·$HOME/.bash_login
·$HOME/.profile

/etc/profile文件是系统中默认的bash shell的主启动文件。系统中的每个用户登录时都会执行这个启动文件。

1./etc/profile文件

/etc/profile文件是bash shell默认的主启动文件。只要登录Linux系统,bash就会执行/etc/profile启动文件中的命令。

[root@Wesuiliye ~]# cat /etc/profile | tail


PATH=/data/python38/bin:$PATH
export PATH

export JAVA_HOME=/data/jdk-19.0.2+7
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

[root@Wesuiliye ~]# cat /etc/profile | ta
tabs        tail        tapestat    targetcli   targetctl   
tac         tailf       tar         targetclid  taskset     
[root@Wesuiliye ~]# cat /etc/profile | tail


PATH=/data/python38/bin:$PATH
export PATH

export JAVA_HOME=/data/jdk-19.0.2+7
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

2.$HOME目录下的启动文件

其余的启动文件都用于同一个目的:提供用户专属的启动文件来定义该用户所用到的环境变量。

·$HOME/.bash_profile
·$HOME/.bashrc
·$HOME/.bash_login
·$HOME/.profile

注意,这些文件都以点号开头,说明属于隐藏文件(不会出现在一般的ls命令输出中)。

shell会按照下列顺序执行第一个被找到的文件,余下的则被忽略。

·$HOME/.bash_profile
·$HOME/.bash_login
·$HOME/.profile

1.Linux发行版在环境文件方面存在的差异非常大。$HOME文件下的那些文件并非每个用户都有。例如,有些用户可能只有一个$HOME/.bash_profile文件。这很正常。

2..bash_profile启动文件会先检查$HOME目录中是不是还有一个名为.bashrc的启动文件。如果有,就先执行该文件中的命令。

交互式shell进程

如果不是在登录系统时启动的bash shell(比如在命令行中输入bash),那么这时的shell称作交互式shell。

作为交互式shell启动的bash并不处理/etc/profile文件,只检查用户$HOME目录中的.bashrc文件。

[root@Wesuiliye ~]# cat .bashrc 
# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# Created by `pipx` on 2023-04-08 08:09:13
export PATH="$PATH:/root/.local/bin"

.bashrc文件会做两件事:首先,检查/etc目录下的通用bashrc文件;其次,为用户提供一个定制自己的命令别名和脚本函数的地方。

非交互式shell

最后一种shell是非交互式shell。系统执行shell脚本时用的就是这种shell。不同之处在于它没有命令行提示符。

脚本能以不同的方式执行。只有部分执行方式会启动子shell。

为了处理这种情况,bash shell提供了BASH_ENV环境变量。当shell启动一个非交互式shell进程时,会检查这个环境变量以查看要执行的启动文件名。如果有指定的文件,则shell会执行该文件里的命令,这通常包括shell脚本变量设置。

如果父shell是登录shell,在/etc/profile文件、/etc/profile.d/*.sh文件和$HOME/.bashrc文件中设置并导出了变量,那么用于执行脚本的子shell就能继承这些变量。

任何由父shell设置但未导出的变量都是局部变量,不会被子shell继承。

环境变量持久化

/etc/profile.d目录中创建一个以.sh结尾的文件。把所有新的或修改过的全局环境变量设置都放在这个文件中。

保存个人用户永久性bash shell变量的最佳地点是$HOME/.bashrc文件。

数组变量

数组是能够存储多个值的变量。这些值既可以单独引用,也可以作为整体引用。

要为某个环境变量设置多个值,可以把值放在圆括号中,值与值之间以空格分隔:

[root@Wesuiliye ~]# mytest=(zero ont two three four)
[root@Wesuiliye ~]# echo $mytest 
zero
[root@Wesuiliye ~]# 

以上代码只显示了数组的第一个值。要引用单个数组元素,必须使用表示其在数组中位置的索引。索引要写在方括号中,$符号之后的所有内容都要放入花括号中。

[root@Wesuiliye ~]# echo ${mytest[2]} 
two
[root@Wesuiliye ~]# 

环境变量数组的索引都是从0开始的。

要显示整个数组变量,可以用通配符*作为索引:

[root@Wesuiliye ~]# echo ${mytest[*]} 
zero ont two three four
[root@Wesuiliye ~]# 

也可以改变某个索引位置上的值:

[root@Wesuiliye ~]# mytest[2]=seven
[root@Wesuiliye ~]# echo ${mytest[*]} 
zero ont seven three four
[root@Wesuiliye ~]# 

用unset命令来删除数组中的某个值

[root@Wesuiliye ~]# unset mytest[2]
[root@Wesuiliye ~]# echo ${mytest[*]} 
zero ont three four
[root@Wesuiliye ~]# echo ${mytest[2]}

[root@Wesuiliye ~]# echo ${mytest[3]}
three
[root@Wesuiliye ~]# 

显示整个数组变量,看上去是填充了2的位置,但是专门显示索引2位置上的值时,你会发现这个位置是空的。

可以在unset命令后跟上数组名来删除整个数组:

[root@Wesuiliye ~]# unset mytest 
[root@Wesuiliye ~]# echo ${mytest[*]} 

[root@Wesuiliye ~]# 
posted @ 2023-05-23 14:44  0x1e61  阅读(20)  评论(0编辑  收藏  举报