本博客内容来自《Linux命令行与shell脚本编程大全》第六章
目录
1、环境变量
查看全局环境变量
查看局部环境变量
2、设置用户定义变量
设置局部用户定义变量
设置全局环境变量
删除环境变量
3、设置PATH环境变量
添加新目录
4、定位系统环境变量
登录shell
/etc/profile文件
$HOME目录下的启动文件
交互式shell进程
非交互式shell
环境变量持久化
系统环境变量
用户自定义变量
5、数组变量
环境变量是bash shell用来存储有关shell会话与工作环境信息的特性。分为全局变量和局部变量。
全局环境变量对shell会话以及所有子shell都是可见的,局部变量只对创建它的shell可见。
Linux系统在启动bash会话时会默认设置系统环境变量,可以通过env或printenv命令查看
[root@izwz9194nuv8g0cwqfqsh3z ~]# env
XDG_SESSION_ID=515
HOSTNAME=izwz9194nuv8g0cwqfqsh3z
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=183.157.160.24 24993 22
SSH_TTY=/dev/pts/0
USER=root
......
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
SSH_CONNECTION=......
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
_=/usr/bin/env查看单个环境变量的值,使用printenv命令,如下所示(env命令无此功能)
[root@izwz9194nuv8g0cwqfqsh3z ~]# printenv HOME
/root也可以用echo命令显示变量
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $HOME
/root
很遗憾,Linux现在没有只显示局部环境变量的命令。set命令可以查看为某个进程设置的所有环境变量,包括局部变量、全局变量和用户定义变量,并对输出结果按照字母顺序排列。
[root@izwz9194nuv8g0cwqfqsh3z ~]# set
BASH=/bin/bash
......
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="2" [2]="46" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")
BASH_VERSION='4.2.46(1)-release'
COLUMNS=187
DIRSTACK=()
EUID=0
[root@izwz9194nuv8g0cwqfqsh3z ~]# my_var=hello
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $my_var
hello
[root@izwz9194nuv8g0cwqfqsh3z ~]# str_var="hello world"
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $str_var
hello world自定义变量请小写
等号定义用户变量
如果变量值中有空格,加引号
用户自定义的变量无法在新的进程或子shell中使用。
设置全局环境变量的方法是先设置用户自定义变量,再使用export命令导出为全局变量。
[root@izwz9194nuv8g0cwqfqsh3z ~]# str_var="hello world" ##设置局部变量
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $str_var
hello world
[root@izwz9194nuv8g0cwqfqsh3z ~]# export str_var ##导出为全局变量
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $str_var
hello world
[root@izwz9194nuv8g0cwqfqsh3z ~]# bash ##创建子bash
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $str_var
hello world
[root@izwz9194nuv8g0cwqfqsh3z ~]# str_var=hello ##尝试修改子bash中的全局变量
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $str_var ##子bash中的变量值被修改
hello
[root@izwz9194nuv8g0cwqfqsh3z ~]# export str_var
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $str_var
hello
[root@izwz9194nuv8g0cwqfqsh3z ~]# exit ##退出子bash
exit
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $str_var ##父bash中的变量值未改变
hello world
使用unset命令删除环境变量
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $str_var
hello world
[root@izwz9194nuv8g0cwqfqsh3z ~]# unset str_var
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $str_var
如果在子进程(子shell)中删除全局环境变量,回到父进程(父shell)后不受影响。
PATH环境变量定义了用于进行命令和程序查找的目录
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
为PATH添加新目录最简单的方法是直接引用原来的值
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@izwz9194nuv8g0cwqfqsh3z ~]# pwd
/root
[root@izwz9194nuv8g0cwqfqsh3z ~]# PATH=$PATH:/root/tast ##添加新目录
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/tast ##添加成功
[root@izwz9194nuv8g0cwqfqsh3z ~]# export PATH ##导出变量,让子shell和子程序可以使用
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/tast
启动bash shell有三种方式
登录时作为默认登录shell
作为非登录shell的交互式shell
作为运行脚本的非交互shell
登录时如果把bash shell作为默认shell,shell会从5个文件读取命令
/etc/profile ##默认主启动文件,系统每个用户登录都会执行该文件
$HOME/.bash_profile ##剩下四个是针对用户的,可根据个人需求定制
$HOME/.bashrc
$HOME/.bash_login
$HOME/.profile
bash shell默认的主启动文件,每个发行版本可能有所不同。查看文件内容:
[root@izwz9194nuv8g0cwqfqsh3z ~]# more /etc/profile
# /etc/profile# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc......
for i in /etc/profile.d/*.sh ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null
fi
fi
doneunset i
unset -f pathmunge
可以发现存在一个/etc/profile.d的目录,在目录下有很多脚本。(注意,不是所有发行版本都是该文件夹)
[root@izwz9194nuv8g0cwqfqsh3z ~]# cd /etc/profile.d
[root@izwz9194nuv8g0cwqfqsh3z profile.d]# ll
total 56
-rw-r--r-- 1 root root 771 Apr 13 2017 256term.csh
-rw-r--r-- 1 root root 841 Apr 13 2017 256term.sh
-rw-r--r--. 1 root root 196 Apr 29 2015 colorgrep.csh
-rw-r--r--. 1 root root 201 Apr 29 2015 colorgrep.sh
-rw-r--r--. 1 root root 1741 Nov 5 2016 colorls.csh
-rw-r--r--. 1 root root 1606 Nov 5 2016 colorls.sh
-rw-r--r-- 1 root root 1706 Apr 13 2017 lang.csh
-rw-r--r-- 1 root root 2703 Apr 13 2017 lang.sh
-rw-r--r--. 1 root root 123 Jul 31 2015 less.csh
-rw-r--r--. 1 root root 121 Jul 31 2015 less.sh
-rw-r--r-- 1 root root 105 Dec 22 2016 vim.csh
-rw-r--r-- 1 root root 269 Dec 22 2016 vim.sh
-rw-r--r--. 1 root root 164 Jan 28 2014 which2.csh
-rw-r--r--. 1 root root 169 Jan 28 2014 which2.sh说明:
大部分应用都提供了两个启动文件,一个供bash shell使用(.sh),一个供c shell使用(.csh)
大多数Linux发行版本只用以上提到的四个启动文件中的一到两个,以本文所用环境版本为例,就用到了两个:
[root@izwz9194nuv8g0cwqfqsh3z ~]# ll -a
total 80
dr-xr-x---. 8 root root 4096 Feb 21 17:05 .
dr-xr-xr-x. 18 root root 4096 Feb 20 14:18 ..
-rw------- 1 root root 3027 Feb 23 15:24 .bash_history
-rw-r--r--. 1 root root 18 Dec 29 2013 .bash_logout
-rw-r--r--. 1 root root 176 Dec 29 2013 .bash_profile
-rw-r--r--. 1 root root 176 Dec 29 2013 .bashrc
这些文件包含的是用户专属的变量。其中.bashrc文件有两个作用:
1.查看/etc目录下通用的bashrc文件
2.为用户提供一个定制自己命令别名和私有脚本函数的地方
以第二点为例,本文所用主机环境中查看.bashrc文件,内容如下:
[root@izwz9194nuv8g0cwqfqsh3z ~]# 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可以看出,该文件定义了rm、cp、mv三个命令的别名
如果bash shell不是登录系统时启动的,而是通过bash命令启动,启动后的shell就叫交互式shell。
交互式shell不会像登录shell一样运行,不会访问/etc/profile文件,只会检查$HOME/.bashrc文件。
当然,交互式shell也提供命令行提示符来输入命令。
系统执行shell脚本时用的就是非交互式shell。
不同于之前的两种,非交互式shell没有命令行提示符。
非交互式shell使用的环境变量可以有两种来源
1.通过父shell启动脚本,那么脚本将在子shell中运行,直接继承父shell中的变量
2.通过变量BASH_ENV设置脚本环境变量文件所处的位置
环境变量持久化可以直接将变量设置在/etc/profile文件中,但是不鼓励这种做法
最好的做法是在/etc/profile.d目录下创建以.sh结尾的脚本文件,把所有新的或者修改过的全局变量设置都放在这个文件里面。
对于个人用户,永久性存储变量的地方是$HOME/.bashrc文件,但如果设置了BASH_ENV变量,该变量指向的非交互式shell的用户变量不能是$HOME/.bashrc。
数组变量最酷的地方在于可以作为数组使用。
[root@izwz9194nuv8g0cwqfqsh3z ~]# mytest=(one two three four five) ##定义数组
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo $mytest
one
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo ${mytest[2]} ##显示某个元素
three
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo ${mytest[*]} ##显示所有元素
one two three four five
[root@izwz9194nuv8g0cwqfqsh3z ~]# mytest[2]=seven ##修改元素
[root@izwz9194nuv8g0cwqfqsh3z ~]# echo ${mytest[*]}
one two seven four five[root@izwz9194nuv8g0cwqfqsh3z ~]# unset mytest ##删除数组