export 可以查看(显示)Shell 环境变量。我们直接进入正题,先来看看执行 export 会输出什么内容:
[roc@roclinux ~]$ export declare -x CVS_RSH="ssh" declare -x GEM_HOME="/usr/local/rvm/gems/ruby-2.2.3" declare -x GEM_PATH="/usr/local/rvm/gems/ruby-2.2.3:/usr/local/rvm/gems/ruby-2.2.3@global" declare -x GOROOT="/home/roc/program/go" declare -x G_BROKEN_FILENAMES="1" declare -x HISTCONTROL="ignoredups" declare -x HISTSIZE="1000" declare -x HOME="/home/roc" declare -x HOSTNAME="roclinux" declare -x IRBRC="/usr/local/rvm/rubies/ruby-2.2.3/.irbrc" declare -x JAVA_HOME="/usr/lib/jvm/jre-1.7.0-openjdk.x86_64" declare -x LANG="zh_CN.gb2312" declare -x LC_ALL="zh_CN.gb2312" declare -x LESSOPEN="|/usr/bin/lesspipe.sh %s" declare -x LOGNAME="roc" declare -x LS_COLORS="rs=0:di=38;5;27:ln=38;5;51:mh=44;38;5;15:pi=40;38;5;11:so=38;5;13:do=38;5;5:bd=48;5;232;38;5;11:cd=48;5;232;38;5;3:or=48;5;232;38;5;9:mi=05;48;5;232;38;5;15:su=48;5;196;38;5;15:sg=48;5;11;38;5;16:ca=48;5;196;38;5;226:tw=48;5;10;38;5;16:ow=48;5;10;38;5;21:st=48;5;21;38;5;15:ex=38;5;34:*.tar=38;5;9:*.tgz=38;5;9:*.arj=38;5;9:*.taz=38;5;9:*.lzh=38;5;9:*.lzma=38;5;9:*.tlz=38;5;9:*.txz=38;5;9:*.zip=38;5;9:*.z=38;5;9:*.Z=38;5;9:*.dz=38;5;9:*.gz=38;5;9:*.lz=38;5;9:*.xz=38;5;9:*.bz2=38;5;9:*.tbz=38;5;9:*.tbz2=38;5;9:*.bz=38;5;9:*.tz=38;5;9:*.deb=38;5;9:*.rpm=38;5;9:*.jar=38;5;9:*.rar=38;5;9:*.ace=38;5;9:*.zoo=38;5;9:*.cpio=38;5;9:*.7z=38;5;9:*.rz=38;5;9:*.jpg=38;5;13:*.jpeg=38;5;13:*.gif=38;5;13:*.bmp=38;5;13:*.pbm=38;5;13:*.pgm=38;5;13:*.ppm=38;5;13:*.tga=38;5;13:*.xbm=38;5;13:*.xpm=38;5;13:*.tif=38;5;13:*.tiff=38;5;13:*.png=38;5;13:*.svg=38;5;13:*.svgz=38;5;13:*.mng=38;5;13:*.pcx=38;5;13:*.mov=38;5;13:*.mpg=38;5;13:*.mpeg=38;5;13:*.m2v=38;5;13:*.mkv=38;5;13:*.ogm=38;5;13:*.mp4=38;5;13:*.m4v=38;5;13:*.mp4v=38;5;13:*.vob=38;5;13:*.qt=38;5;13:*.nuv=38;5;13:*.wmv=38;5;13:*.asf=38;5;13:*.rm=38;5;13:*.rmvb=38;5;13:*.flc=38;5;13:*.avi=38;5;13:*.fli=38;5;13:*.flv=38;5;13:*.gl=38;5;13:*.dl=38;5;13:*.xcf=38;5;13:*.xwd=38;5;13:*. yuv=38;5;13:*.cgm=38;5;13:*.emf=38;5;13:*.axv=38;5;13:*.anx=38;5;13:*.ogv=38;5;13:*.ogx=38;5;13:*.aac=38;5;45:*.au=38;5;45:*.flac=38;5;45:*.mid=38;5;45:*.midi=38;5;45:*.mka=38;5;45:*.mp3=38;5;45:*.mpc=38;5;45:*.ogg=38;5;45:*.ra=38;5;45:*.wav=38;5;45:*.axa=38;5;45:*.oga=38;5;45:*.spx=38;5;45:*.xspf=38;5;45:" declare -x MAIL="/var/spool/mail/roc" declare -x MY_RUBY_HOME="/usr/local/rvm/rubies/ruby-2.2.3" declare -x OLDPWD="/home/roc/test/20160403" declare -x PATH="/usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin:/home/roc/program/yii/framework/:/home/roc/program/php/bin:/home/roc/bin:/home/roc/program/thrift/bin:/home/roc/program/go/bin:/home/roc/program/vim/bin:/home/roc/program/git/bin:/home/roc/bin:/usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin:/home/roc/program/yii/framework/:/home/roc/program/php/bin:/home/roc/bin:/home/roc/program/thrift/bin:/home/roc/program/go/bin:/home/roc/program/vim/bin:/home/roc/program/git/bin:/usr/local/rvm/gems/ruby-2.2.3/bin:/usr/local/rvm/gems/ruby-2.2.3@global/bin:/usr/local/rvm/rubies/ruby-2.2.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/www/wdlinux/mysql/bin:/usr/local/rvm/bin:/home/roc/bin:/www/wdlinux/mysql/bin:/home/roc/bin" declare -x PWD="/home/roc" declare -x RUBY_VERSION="ruby-2.2.3" declare -x SHELL="/bin/bash" declare -x SHLVL="2" declare -x SSH_CLIENT="111.193.210.134 52932 22000" declare -x SSH_CONNECTION="123.123.56.192 11887 116.255.245.206 22000" declare -x SSH_TTY="/dev/pts/1" declare -x TERM="screen-256color" declare -x TMUX="/tmp/tmux-1001/default,35631,0" declare -x TMUX_PANE="%25" declare -x USER="roc" declare -x _system_arch="x86_64" declare -x _system_name="CentOS" declare -x _system_type="Linux" declare -x _system_version="6" declare -x rvm_alias_expanded declare -x rvm_bin_flag declare -x rvm_bin_path="/usr/local/rvm/bin" declare -x rvm_delete_flag declare -x rvm_docs_type declare -x rvm_file_name declare -x rvm_gemstone_package_file declare -x rvm_gemstone_url declare -x rvm_hook declare -x rvm_niceness declare -x rvm_nightly_flag declare -x rvm_only_path_flag declare -x rvm_path="/usr/local/rvm" declare -x rvm_prefix="/usr/local" declare -x rvm_proxy declare -x rvm_quiet_flag declare -x rvm_ruby_alias declare -x rvm_ruby_bits declare -x rvm_ruby_configure declare -x rvm_ruby_file declare -x rvm_ruby_global_gems_path declare -x rvm_ruby_make declare -x rvm_ruby_make_install declare -x rvm_ruby_mode declare -x rvm_ruby_string declare -x rvm_ruby_url declare -x rvm_script_name declare -x rvm_sdk declare -x rvm_silent_flag declare -x rvm_sticky_flag declare -x rvm_system_flag declare -x rvm_use_flag declare -x rvm_user_flag declare -x rvm_version="1.26.11 (master)" declare -x rvm_wrapper_name
export 输出的内容就是 bash 的所有环境变量了,满满的两页看来还真是不少呀。
在 Linux 系统中,除了 export 之外,env、set 和 declare 这三个命令也可以显示 Shell 中的变量。那这四个命令有什么区别呢?
这个问题,我们需要从 Shell 变量说起。Shell 的变量,可以分为“环境变量”和“自定义变量”两种类型,两者的区别在于作用范围不同。环境变量可以在其进程的子进程中继续有效,而自定义变量的势力范围则无法延伸到其进程的子进程中。
好了,知道了环境变量和自定义变量的区别,我们正式开始介绍 export/env/set/declare 的区别:
根据上面的说明,我们可以得出下面的结论:
我们以 set 和 declare 为例,来看一下是否真的是这样:
[roc@roclinux ~]$ set > set.txt [roc@roclinux ~]$ declare > declare.txt [roc@roclinux ~]$ diff set.txt declare.txt 54c54 < _=clear --- > _=set
可以看到,set 和 declare 的输出几乎是一样的。唯一的区别就在于这个“下划线变量”。下划线变量(_)表示用户上一次输入的命令的最后一个参数。上面两条命令之所以出现不同,是因为在执行 set 前执行了 clear 命令,而在执行 declare 之前,执行了 set 命令。
$PATH 环境变量是 Linux 系统中最常用的变量之一,我们先来看一下这个变量的内容:
[root@roclinux ~]# echo $PATH /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
相信细心的同学已经观察到了,$PATH 变量的值是由多个路径所组成的,并且用冒号进行了分隔。那么,问题来了,这些路径的作用是什么呢?
当用户在 Linux 系统中直接输入一个命令(如 date 命令),而没有指定其绝对路径时,Linux 就会求助于 $PATH 啦,Linux 会依次进入到 $PATH 变量所指定的各个路径中,去寻找是否存在此命令(date 命令),如果找到了,就执行该命令;如果没有找到,就直接退出,并提示用户未找到该命令。
在运维工作中,用好 $PATH 变量是可以大大提升工作效率的。假如 /home/roc/operation_tools 文件夹下存放着我们自制的各种运维小工具,每次使用这些小工具时又不想总指定其绝对路径,那么,我们应该怎么办呢?没错,我们应该把这个路径追加到 $PATH 变量中去,具体的做法是这样:
export PATH=$PATH:/home/roc/operation_tools
上述命令执行成功后,我们的运维小工具就可以直接被 Linux 系统找到了。从此以后,当我们想使用这些运维小工具时,就再也不用指定绝对路径啦。
不知道你是否注意到上面例子中的一个细节,那就是我们在设置 $PATH 环境变量时,使用了 export 命令。如果没有使用 export,会有什么问题吗?
这个问题问得很好,这正好引出 export 的作用,那就是,使用 export 设置的变量就成为了环境变量,而没有使用 export 设置的则是自定义变量。
下面我们通过一个示例来看一下:
#我们在当前Shell进程中指定了var1变量 [roc@roclinux ~]$ var1="hello" [roc@roclinux ~]$ echo $var1 hello #我们在当前Shell进程中又指定了var2变量 [roc@roclinux ~]$ var2="world" [roc@roclinux ~]$ echo $var2 world #我们通过export发布var1 [roc@roclinux ~]$ export var1 #我们进入到一个bash子进程中 [roc@roclinux ~]$ bash #var1变量仍然有效, 而var2变量已经无效了 [roc@roclinux ~]$ echo $var1 # 输出变量的值 hello [roc@roclinux ~]$ echo $var2 # 什么也没有输出
通过上面的示例,我们可以清楚地看到:环境变量可以在其进程的子进程中继续有效,而自定义变量则无效。
“哎呀,不好了,我的 Linux 系统出问题了,我竟然连 cat 命令都没办法运行了,执行时总是提示我找不到命令,这是怎么回事?我只是按照上面的示例执行了一下命令,就成这个样子了,我该怎么办啊?”
“同学,让我看看你到底执行的是什么命令?”
“我执行的命令,很简单,就是这个:”
$ export PATH=/home/to/operation_tools
“额,问题找到了,你的命令输错啦,来看正确的用法吧。
$ export PATH=$PATH:/home/to/operation_tools
再对比一下你的命令,你的命令中缺少了 $PATH,这样会清空原来 $PATH 的内容,$PATH 中没有了系统指定的路径 Linux 就无法找到要执行的命令。这是一个多么可怕的误操作啊!大家一定要记住这个教训呀,在设置 PATH 环境变量时要格外小心哦。