Linux 环境变量(基础)

简介: bash shell用一个叫作环境变量( environment variable)的特性来存储有关shell会话和工作环境的信息(这也是它们被称作环境变量的原因)。这项特性允许你在内存中存储数据,以便程序或shell中运行的脚本能够轻松访问到它们。这也是存储持久数据的一种简便方法。

什么是环境变量


bash shell用一个叫作环境变量( environment variable)的特性来存储有关shell会话和工作环

境的信息(这也是它们被称作环境变量的原因)。这项特性允许你在内存中存储数据,以便程序

或shell中运行的脚本能够轻松访问到它们。这也是存储持久数据的一种简便方法。

在bash shell中,环境变量分为两类:

 全局变量

 局部变量

全局变量


Linux系统在你开始bash会话时就设置了一些全局环境变量。系统环境变量基本上都是使用全大写字母,以区别于普通用户的环境变量

全局环境变量对于shell会话和所有生成的子shell都是可见的。

局部变量则只对创建它们的shell可见。


使用env或printenv查看环境变量

 ~]$ printenv
XDG_SESSION_ID=148
HOSTNAME=P1HQMSMDW01
MASTER_DATA_DIRECTORY=/gpmaster/gpseg-1
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
GPHOME=/usr/local/greenplum-db-6.15.0
USER=gpadmin
PGPORT=5432
LD_LIBRARY_PATH=/usr/local/greenplum-db-6.15.0/lib:/usr/local/greenplum-db-6.15.0/ext/python/lib
......
PGUSER=gpadmin
PGDATABASE=qmsprd
MAIL=/var/spool/mail/gpadmin
PATH=/usr/local/greenplum-cc-6.4.0/bin:/usr/local/greenplum-db-6.15.0/bin:/usr/local/greenplum-db-6.15.0/ext/python/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/local/greenplum-db-clients/bin:/home/gpadmin/.local/bin:/home/gpadmin/bin:/home/gpadmin/postgresql-9.4.24/contrib/pgbench
PWD=/home/gpadmin
LANG=en_US.UTF-8
PYTHONHOME=/usr/local/greenplum-db-6.15.0/ext/python
HISTCONTROL=ignoredups
SHLVL=1
HOME=/home/gpadmin
PYTHONPATH=/usr/local/greenplum-db-6.15.0/lib/python
LOGNAME=gpadmin
LESSOPEN=||/usr/bin/lesspipe.sh %s
GPCC_HOME=/usr/local/greenplum-cc-6.4.0
_=/bin/printenv

全局环境变量可用于进程的所有子shell


用bash命令生成一个***子shell***后,显示了HOME环境变量的当前值,这个值和父shell中的一模一样,都是/home/gpadmin

 ~]$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
gpadmin   8521  8519  0 16:31 pts/2    00:00:00 -bash
gpadmin  14673  8521  0 16:41 pts/2    00:00:00 ps -f
 ~]$ bash
 ~]$
 ~]$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
gpadmin   8521  8519  0 16:31 pts/2    00:00:00 -bash
gpadmin  14734  8521  0 16:41 pts/2    00:00:00 bash
gpadmin  14841 14734  0 16:42 pts/2    00:00:00 ps -f
 ~]$ exit
exit
 ~]$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
gpadmin   8521  8519  0 16:31 pts/2    00:00:00 -bash
gpadmin  15675  8521  0 16:43 pts/2    00:00:00 ps -f

局部变量


局部环境变量只能在***定义它们的进程中可见***。

set命令会显示为某个特定进程设置的所有环境变量,包括局部变量、全局变量

以及用户定义变量。


如果在当前shell中定义了一个变量

20210330165057747.png

~]$ set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")
BASH_VERSION='4.2.46(2)-release'
COLUMNS=233
DIRSTACK=()
EUID=1000
.......省略
_=444444
colors=/home/gpadmin/.dircolors
tmp=444444

可以看到这个变量在set中可以看得到.

当该session退出之后,该变量将消失,是因为其保存在内存中.

env、 printenv和set的区别?


命令env、 printenv和set之间的差异很细微。 set命令会显示出全局变量、局部变量以及用户定义变量。它还会按照字母顺序对结果进行排序。 env和printenv命令同set命令的区别在于前两个命令不会对变量排序,也不会输出局部变量和用户定义变量。在这种情况下, env和printenv的输出是重复的。

设置用户定义变量


设置局部用户定义变量


一旦启动了bash shell(或者执行一个shell脚本),就能创建在这***个shell进程内可见的局部变量***了。可以通过***等号***给环境变量赋值值可以是***数值***或***字符串***。

20210330165748661.png

如果有空格怎么办?

如果要给变量赋一个含有空格的字符串值,必须用单引号来界定字符串的首和尾。

20210330165913116.png

注意:

1、所有的环境变量名均使用大写字母,这是bash shell的标准惯例。

2、如果是你自己创建的局部变量或是shell脚本,请使用小写字母。

3、变量名区分大小写。在涉及用户定义的局部变量时坚持使用小写字母,这能够避免***重新定义系统环境变量可能带来的灾难***。

4、变量名、等号和值之间没有空格,这一点非常重要

如果在赋值表达式中加上了空格,

bash shell就会把值当成一个单独的命令:

这个变量能在新的shell中使用吗?

显然是不可以的.

20210330170333918.png

在这个例子中生成了一个子shell。在子shell中无法使用用户定义变量my_variable。通过命

令echo $my_variable所返回的空行就能够证明这一点。当你退出子shell并回到原来的shell时,这个局部环境变量依然可用。

类似地,如果你在子进程中设置了一个局部变量,那么一旦你退出了子进程,那个局部环境

变量就不可用。

设置全局环境变量


在设定全局环境变量的进程所创建的子进程中,该变量都是可见的。创建全局环境变量的方法是***先创建一个局部环境变量,然后再把它导出到全局环境中***


通过export 关键字来完成将局部变量变成全局变量

20210330170824740.png

bash命令启动了一个子shell。在这个子shell

中能够正确的显示出变量v1的值。该变量能够保留住它的值是因为export命令使其变成了全局环境变量

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


2021033017111635.png

在定义并导出变量v1后, bash命令启动了一个子shell。在这个子shell中能够正确显示出全局环境变量v1的值。子shell随后改变了这个变量的值。

这种改变仅在子shell中有效,并不会被反映到父shell中。

子shell无法使用export命令改变父shell中全局环境变量的值


20210330171335430.png

删除环境变量


用***unset***命令完成这个操作。在unset命令中引用环境变量时,记住不要使用$。

20210330172706828.png

问题: 什么时候该使用美元符,什么时候不该使用?


1、如果要用到变量,使用 $;

2、如果要操作变量,不使用$。

这条规则的一个例外就是使用printenv显示某个变量的值

20210330172822912.png

环境变量是严格区分大小写的.

子进程中删除了一个全局环境变量,只对子进程有效


20210330173333792.png

默认的 shell 环境变量


默认情况下, bash shell会用一些特定的环境变量来定义系统环境。这些变量在你的Linux系统上都已经设置好了,只管放心使用。 bash shell源自当初的Unix Bourne shell,因此也保留了Unix

Bourne shell里定义的那些环境变量。

最常用的的标注出来

20210330173750774.png

除了默认的Bourne的环境变量, bash shell还提供一些自有的变量

1、BASH 当前shell实例的全路径名

2、BASHPID 当前bash进程的PID

3、COLUMNS 当前bash shell实例所用终端的宽度BASH_SUBSHELL 当前子shell环境的嵌套级别(初始值是0)

4、BASH_VERSINFO 含有当前运行的bash shell的主版本号和次版本号的数组变量

5、BASH_VERSION 当前运行的bash shell的版本号

HISTFILE 保存shell历史记录列表的文件名(默认是.bash_history)

HISTFILESIZE 最多在历史文件中存多少行

设置 PATH 环境变量


当你在shell命令行界面中输入一个外部命令时, shell必须搜索系统来找到对应

的程序。 PATH环境变量定义了用于进行命令和程序查找的目录


当安装了一个新的程序,如何将其也加入环境变量中来避免每次都要输入一个绝对路径.


使用echo $PATH 可以查看当前的shell用来查找命令和程序。 PATH中的目录使用冒号分隔。

 ~]$ echo $PATH
/usr/local/greenplum-cc-6.4.0/bin:/usr/local/greenplum-db-6.15.0/bin:/usr/local/greenplum-db-6.15.0/ext/python/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/local/greenplum-db-clients/bin:/home/gpadmin/.local/bin:/home/gpadmin/bin:/home/gpadmin/postgresql-9.4.24/contrib/pgbench

最后一个pgbenc就是后来才加入的一个时PATH

20210331185345929.png

这样就可以在任当前添加bash_profile的用户下任何目录使用该命令了.

需要注意:

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

如何永久生效呢?

定位系统环境变量


在你登入Linux系统启动一个bash shell时,默认情况下bash会在几个文件中查找命令。这些

文件叫作启动文件或环境文件。 bash检查的启动文件取决于你启动bash shell的方式。启动bash

shell有3种方式

定位系统


  1. 环境变量
  2. 作为非登录shell的交互式shell
  3. 作为运行脚本的非交互shell

登录 shell


当你登录Linux系统时, bash shell会作为登录shell启动。登录shell会从5个不同的启动文件里

读取命令:

 /etc/profile

 $HOME/.bash_profile

 $HOME/.bashrc

 $HOME/.bash_login

 $HOME/.profile

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

另外4个启动文件是针对用户的,可根据个人需求定制


1./etc/profile文件

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

/etc/profile启动文件中的命令。不同的Linux发行版在这个文件里放了不同的命令

 ~]# cat /etc/profile
# /etc/profile
# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc
# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.
pathmunge () {
    case ":${PATH}:" in
        *:"$1":*)
            ;;
        *)
            if [ "$2" = "after" ] ; then
                PATH=$PATH:$1
            else
                PATH=$1:$PATH
            fi
    esac
}
if [ -x /usr/bin/id ]; then
    if [ -z "$EUID" ]; then
        # ksh workaround
        EUID=`/usr/bin/id -u`
        UID=`/usr/bin/id -ru`
    fi
    USER="`/usr/bin/id -un`"
    LOGNAME=$USER
    MAIL="/var/spool/mail/$USER"
fi
# Path manipulation
if [ "$EUID" = "0" ]; then
    pathmunge /usr/sbin
    pathmunge /usr/local/sbin
else
    pathmunge /usr/local/sbin after
    pathmunge /usr/sbin after
fi
HOSTNAME=`/usr/bin/hostname 2>/dev/null`
HISTSIZE=1000
if [ "$HISTCONTROL" = "ignorespace" ] ; then
    export HISTCONTROL=ignoreboth
else
    export HISTCONTROL=ignoredups
fi
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
# By default, we want umask to get set. This sets it for login shell
# Current threshold for system reserved uid/gids is 200
# You could check uidgid reservation validity in
# /usr/share/doc/setup-*/uidgid file
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
    umask 002
else
    umask 022
fi
for i in /etc/profile.d/*.sh /etc/profile.d/sh.local ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null
        fi
    fi
done
unset i
unset -f pathmunge

for语句。它用来迭代/etc/profile.d目录下的所有文件。

这为Linux系统提供了一个放置特定应用程序启动文件的地方,当用户登录时, shell会执行这些文件。

20210331190621427.png

大部分应用都会创建两个启动文件:

一个供bash shell使用(使用.sh扩展名)

一个供c shell使用(使用.csh扩展名)。

lang.csh和lang.sh文件会尝试去判定系统上所采用的默认语言字符集,然后设置对应的LANG

环境变量

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

剩下的启动文件都起着同一个作用:提供一个用户专属的启动文件来定义该用户所用到的环

境变量。大多数Linux发行版只用这四个启动文件中的一到两个:

 $HOME/.bash_profile

 $HOME/.bashrc

 $HOME/.bash_login

 $HOME/.profile

所以每个用户都可以编辑这些文件并添加自己的环境变

量,这些环境变量会在每次启动bash shell会话时生效。


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

$HOME/.bash_profile

$HOME/.bash_login

H O M E / . p r o f i l e 注 意 , 这 个 列 表 中 并 没 有 HOME/.profile 注意,这个列表中并没有HOME/.profile注意,这个列表中并没有HOME/.bashrc文件。这是因为该文件通常通过其他文件运行的。

Centos .bahs_profile的内容

 ~]$ more .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi
# User specific environment and startup programs
PGBENCH_HOME=/home/gpadmin/postgresql-9.4.24/contrib/pgbench
PATH=$PATH:$HOME/.local/bin:$HOME/bin:$PGBENCH_HOME
export PATH

.bash_profile启动文件会先去检查HOME目录中是不是还有一个叫**.bashrc的启动文件**。 如果有的话,会先执行启动文件里面的命令。 这也就是说 可以把pgbench这个变量放在bashrc中.

交互式shell

如果你的bash shell不是登录系统时启动的(比如是在命令行提示符下敲入bash时启动),那

么你启动的shell叫作交互式shell。交互式shell不会像登录shell一样运行,但它依然提供了命令行提示符来输入命令。

如果bash是作为交互式shell启动的,它就不会访问/etc/profile文件,只会检查用户HOME目录中的.bashrc文件。

20210331191441607.png

.bashrc文件有两个作用

1、查看/etc目录下通用的bashrc文件

2、为用户提供一个定制自己的命令别名和私有脚本函数的地方

非交互式shell


系统执行shell脚本时用的就是这种shell。不同的地方在于它没有命令行提示符(这也是平常用的最多的一种脚本执行方式,例如crontab)

但是当你在系统上运行脚本时,也许希望能够运行一些特定启动的命令。


为了处理这种情况, bash shell提供了BASH_ENV环境变量。当shell启动一个非交互式shell进

程时,它会检查这个环境变量来查看要执行的启动文件。如果有指定的文件, shell会执行该文件里的命令,这通常包括shell脚本变量设置。


那如果BASH_ENV变量没有设置, shell脚本到哪里去获得它们的环境变量呢?别忘了有些

shell脚本是通过启动一个子shell来执行的

子shell可以继承父shell导出过的变量。

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

记住由父shell设置但并未导出的变量都是局部变量。子shell无法继承局部变量。

也就是说如果在远程执行一个嵌套了脚本的脚本中定义了一个变量,该变量为局部变量,因此无法在被嵌套的shell中执行.

实例说明:

对于那些不启动子shell的脚本,变量已经存在于当前shell中了。

所以就算没有设置BASH_ENV,也可以使用当前shell的局部变量和全局变量。

环境变量持久化


全局环境变量来说( Linux系统中所有用户都需要使用的变量),可能更倾向于将新的或修

改过的变量设置放在/etc/profile文件中,但这可不是什么好主意。如果你升级了所用的发行版,

这个文件也会跟着更新,那你所有定制过的变量设置可就都没有了。


最好是在/etc/profile.d目录中创建一个以.sh结尾的文件。把所有新的或修改过的全局环境变

量设置放在这个文件中。

在大多数发行版中,存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件。

什么是外部命令?什么是内建命令?


1、外部命令,有时候也被称为文件系统命令,是存在于bash shell之外的程序。它们并不是shell

程序的一部分。外部命令程序通常位于/bin、 /usr/bin、 /sbin或/usr/sbin中。这部分就是后来安装在系统上的软件一样.例如 mysql、nginx、keepalived…

ps就是一个外部命令。你可以使用which和type命令找到它

20210331145623684.png

2、内建命令和外部命令的区别在于前者不需要使用子进程来执行。它们已经和shell编译成了一体,作为shell工具的组成部分存在。不需要借助外部程序文件来运行

20210331184012701.png

which命令只显示出了外部命令文件


目录
相关文章
|
1月前
|
存储 Linux Shell
Linux环境变量【终】
Linux环境变量【终】
|
1天前
|
Linux Shell 编译器
Linux进程——Linux环境变量
Linux进程——Linux环境变量
|
12天前
|
Linux Shell
28. 【Linux教程】删除环境变量
28. 【Linux教程】删除环境变量
14 0
|
12天前
|
Shell Linux 网络安全
27. 【Linux教程】配置环境变量
27. 【Linux教程】配置环境变量
13 0
|
13天前
|
Linux Shell
26. 【Linux教程】Linux 查看环境变量
26. 【Linux教程】Linux 查看环境变量
25 1
|
12天前
|
Linux Shell Windows
25. 【Linux教程】Linux 环境变量介绍
25. 【Linux教程】Linux 环境变量介绍
7 0
|
21天前
|
存储 Linux 网络安全
在 Linux 中通过 SSH 执行远程命令时,无法自动加载环境变量(已解决)
SSH远程执行命令时遇到“命令未找到”问题,原因是Linux登录方式不同导致环境变量加载差异。解决方案:将环境变量写入`/etc/profile.d/`下的文件,或手动在命令前加载环境变量,如`source /etc/profile`。
|
24天前
|
人工智能 Java Shell
【Linux】环境变量及相关指令
【Linux】环境变量及相关指令
|
1月前
|
存储 Unix Shell
Linux:环境变量
Linux:环境变量
32 7
|
1月前
|
Shell Linux C++
【Linux】关于环境变量——你需要知道这些原理&指令
【Linux】关于环境变量——你需要知道这些原理&指令