Shell脚本的命令常常会使用到
环境变量
进行信息传递,因此非常有必要对环境变量
知识做个基础了解。
环境变量
相关命令 :export
、env
、set
- 重要的
环境变量
:PATH
、HOME
、RANDOM
- 环境变量配置文件:
/etc/profile
、~/.bash_profile
、~/.bashrc
环境变量相关命令
export
: Bash内建命令,用于导出当前Shell环境变量的name
变量到后续执行的命令的环境中,如果没有指定name
或设置了-p
参数将打印输出当前Shell的所有被导出
的变量名称和变量值。用法:export -fn [name[=word]]
或export -p
。常用在多个子脚本之间
的环境变量信息传递。env
: 独立系统命令,在重建
的Shell环境中运行命令程序,如果无任何参数则打印输出当前环境变量信息,用法:env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
。set
: Bash内建命令,用于设置Shell
的属性
,注意到这个并不是用来设置环境变量的命令,但是无参数时可以输出显示当前Shell
的所有变量名称和变量值信息,比export
输出内容更多(包含没有被导出的变量)。
示例,您可以预测一下执行下面脚本后的输出结果:
#!/bin/bash
name="Bob"
echo "Hello $name"
sh -c 'echo "Hello $name"'
env name="Jim" echo "Hello $name"
env name="Jim" sh -c 'echo Hello $name'
echo "Hello $name"
export name="Tom"
echo "Hello $name"
sh -c 'echo "Hello $name"'
env sh -c 'echo Hello $name'
执行输出结果:
$ sh ./a.sh
Hello Bob
Hello
Hello Bob
Hello Jim
Hello Bob
Hello Tom
Hello Tom
Hello Tom
跟您预测的结果一致么? 我们来分析一下。
第一条命令name="Bob"
是在a.sh
脚本内部设置环境变量name
,但生效范围仅限当前的脚本中,
第二条命令echo "Hello $name"
,name
变量值为"Bob",输出结果为"Hello Bob"。
第三条命令sh -c 'echo "Hello $name"'
是在新建的子Shell环境中执行'echo "Hello $name"'
命令,您可能注意到了这里命令两边用了单引号,目的防止在a.sh
脚本执行子shell进程的参数传递时对name
变量进行解析,应该将name
放到子Shell中进行解析,因此输出结果是Hello
,因为子Shell中并没有设置name
环境变量。
第四条命令env name="Jim" echo "Hello $name"
,虽然设置了name
变量,但是由于没有使用单引号
括起来导致在env
命令新生成的Shell环境中执行的命令是echo "Hello Bob"
,而不是echo "Hello $name"
,因此输出结果分别为"Hello Bob"。
第五条命令env name="Jim" sh -c 'echo Hello $name
解决了上一条命令的问题,因此输出结果为"Hello Jim"。
第六条命令echo "Hello $name"
的目的是用来说明env
命令内设置的环境变量不会对当前Shell脚本的环境变量产生影响,输出结果为"Hello Bob"。
第七条命令export name="Tom"
,导出了name
变量,这意味着此命令之后生成的其他子Shell的环境变量中会携带name
变量,因此最后的三条命令输出的都是"Hello Tom"。
如果您在以后编写脚本时还会遇到此类环境变量显示不正确或者与预期不符合时,您可以回来再仔细的想一想上面的示例,相信会帮到您的。
set使用介绍
由于
set
命令在Shell
脚本中可以改变脚本的执行结果和状态,对于编写、调试脚本都比较重要,所以单独的说明一下。
使用方法: set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
常用的参数:
-a
:-o allexport
自动将设置的变量导出,相当于默认每个变量都使用了export
进行导出。-e
:-o errexit
当脚本中的命令执行返回结果为非0值时,脚本立即退出。也就是执行错误后不再继续向下执行,避免更多的错误结果。-n
:-o noexec
只读取命令,并不执行。常用于语法检测,通常使用sh -n script.sh
方法检查脚本语法正确性。-u
:-o nounset
遇到未定义的变量时报错退出执行,而不是默默的忽略继续执行。-v
:-o verbose
在读取输入的同时打印出来。-x
:-o xtrace
跟踪调试脚本,并显示PS4
的值。通常使用sh -x script.sh
作为调试
查看脚本执行过程中变量值的真实情况。-o vi
: 使用vi
样式的命令行编辑操作方式,如果你比较喜欢使用vi
的操作方式就可以这样设置了。-o emacs
: 使用emacs
样式的命令行编辑操作方式,这是Bash
的默认方式。
值得说的是,当我们想要
关闭
某个选项时,可以把减号-
替换成加号+
执行一下就可以了,例如set +x
就可以关闭xtrace
跟踪调试功能。这样我们就可以非常灵活的使用这些shell
属性了。
重要的环境变量
PATH
: 定义了Shell中执行的命令的搜索路径列表。目录之间用冒号(:
)分割,格式如“/path/to/bin1:/path/to/bin2:.:/usr/bin”,当执行ls
时会按先后顺序逐个查找$PATH变量中的目录,找到后停止继续查找,如果找不到会提示命令找不到"ls: command not found"。HOME
: 当前用户的个人目录;内建命令cd
的默认参数。在执行波浪线(~
)扩展时也用到这个变量。RANDOM
: 每次引用这个参数时,都会产生一个 0 到 32767 之间的随机整数。可以通过向RANDOM
赋值来初始化随机数序列。如果取消了 RANDOM 的定义,它就失去了特殊的意义,即使后来重新定义它。HISTFILE
: 保存命令历史的文件名。默认值是~/.bash_history
。如果取消定义,在交互式 shell 退出时 命令历史将不会保存。HISTFILESIZE
: 历史文件中包含的最大行数。默认值是 500。PS1
: 交互终端光标前的提示符串设置的变量。 默认值是\s-\v\$
。设置方法可以在man bash
文档中的PROMPTING
小节找到详细说明。PS2
: 这个参数的值同 PS1 一起被扩展,用作次提示符字符串。默认值是>
。PS3
: 这个参数的值被用作内建命令 select 的提示符。PS4
: 跟踪shell
脚本或者交互界面执行过程的细节前缀提示符,PS4
的第一个字符会被复制多次,来指示 indirection 的层数
。默认值是加号后携带一个空格+
。
PATH
变量在Shell中是非常重要的,比如配置JAVA开发环境,我们将JDK环境
保存路径为 /prod/jdk ,如果想要在shell中可以直接使用java
命令,做法是在 PATH 变量中添加 /prod/jdk/bin 目录即可,但是为了保证这个配置以后也一直有效,就可以将export PATH=/prod/jdk/bin:$PATH
添加到 ~/.bashrc 环境变量文件中。
环境变量配置文件
在Linux系统中,每个进程都有其各自的环境变量设置。 缺省情况下, 当一个进程被创建时, 除了创建过程中的明确更改外,它继承了其父进程的绝大部分环境设置。
Linux系统的环境变量设置是通过一些默认(疑问1?)的文件定义的,下面是我们经常使用的默认Bash
环境变量设置文件。
/etc/profile
: 系统范围的初始化文件,登录 shell 会执行它,登录桌面时执行一次。~/.bash_profile
: 个人初始化文件,登录 shell 会执行它,登录桌面时执行一次。~/.bashrc
: 个人的每个交互式 shell 启动时执行的文件,每次打开新窗口会执行一次。~/.bash_logout
: 个人的登录 shell 清理文件,当一个登录shell
退出时会执行一次。~/.inputrc
: 个人的readline
初始化文件。
修改后的环境变量文件如何生效呢?
这要依赖我们修改的是哪个配置文件,比如/etc/profile
被修改后会在下次重新登录时生效,而~/.bashrc
在我们打开新的shell
终端窗口时就会生效。
知道了不同环境变量文件的作用,就不会随意乱修改配置文件,导致在不应该修改的位置修改了,看似有效实则扩大了影响的范围,有可能会对服务器上运行的其他应用造成错误影响。
当然我们可以通过手动
执行配置文件来立即生效,方法如下:
. ~/.bashrc
: 注意文件前面有个点符号(.
),在当前shell环境
中执行~/.bashrc
中的命令。source ~/.bashrc
: 读取并在当前shell环境
中执行~/.bashrc
中的命令,返回最后一个命令的返回状态。
通常以上两种方式常常会在脚本中见到,这样可以帮助脚本执行时保证能够提供脚本需要的环境变量信息,例如使用cron
调度脚本时或者远程ssh
执行脚本时。
疑问1: 默认的文件是谁执行的?
答案: 是我们的默认Shell执行的,也就是 grep whoami
/etc/passwd 中配置的默认shell的默认环境变量文件。
疑问2: 如何知道有哪些默认环境变量文件呢?
答案: 查看man bash
文档,在最后有Files
一节内容,列举出了相关文件及作用信息,例如我们修改了默认shell为/usr/bin/zsh,那么每次打开新Terminal窗口执行的默认的环境变量文件就变成了~/.zshrc
。与之对应的默认环境变量文件如下:
$ZDOTDIR/.zshenv
$ZDOTDIR/.zprofile
$ZDOTDIR/.zshrc
$ZDOTDIR/.zlogin
$ZDOTDIR/.zlogout
关于环境变量文件内容就介绍到这里。
喜欢Linux相关内容可以关注我、点赞、留言。