简介
我们知道,Bash 执行脚本的时候,会创建一个新的 Shell,这个 Shell 就是脚本的执行环境,Bash 默认给定了这个环境的各种参数。set命令用来修改 Shell 环境的运行参数,也就是可以定制环境。
语 法
补充说明
用set 命令可以设置各种shell选项或者列 出shell变量.单个选项设置常用的特性.在某些选项之后
-o参数将特殊特性打开.在某些选项之后使用
+o参数将关闭某些特性,不带任何参数的set命令将显示shell的全部变量.除非遇到非法的选项,否则set总是返回true
参数说明
allexport -a 从设置开始标记所有新的和修改过的用于输出的变量
braceexpand -B 允许符号扩展,默认选项
emacs 在进行命令编辑的时候,使用内建的emacs编辑器, 默认选项
errexit -e 如果一个命令返回一个非0退出状态值(失败),就退出.
histexpand -H 在做临时替换的时候允许使用!和!! 默认选项
history 允许命令行历史,默认选项
ignoreeof 禁止coontrol-D的方式退出shell,必须输入exit。
interactive-comments 在交互式模式下, #用来表示注解
keyword -k 为命令把关键字参数放在环境中
monitor -m 允许作业控制
noclobber -C 保护文件在使用重新动向的时候不被覆盖
noexec -n 在脚本状态下读取命令但是不执行,主要为了检查语法结构。
noglob -d 禁止路径名扩展,即关闭通配符
notify -b 在后台作业以后通知客户
nounset -u 在扩展一个没有的设置的变量的时候,显示错误的信息
onecmd -t 在读取并执行一个新的命令后退出
physical -P 如果被设置,则在使用pwd和cd命令时不使用符号连接的路径 而是物理路径
posix 改变shell行为以便符合POSIX要求
privileged 一旦被设置,shell不再读取.profile文件和env文件 shell函数也不继承任何环境
verbose -v 为调试打开verbose模式
vi 在命令行编辑的时候使用内置的vi编辑器
xtrace -x 打开调试回响模式
对于不知道某些选项是否开启,可以使用以下的指令:
set -o
查看各个参数的默认状态:
$ set -o
allexport off
braceexpand on
emacs on
errexit off
errtrace off
functrace off
hashall on
histexpand on
history on
示例1. set -e
若程序 异常(返回 非 true)值, 程序会继续向下执行。
errexit -e 如果一个命令返回一个非0退出状态值(失败),就退出.
#! /bin/bash
set -e
#set -o errexit 另一种写法
foo
echo bar
示例2. set -x
默认情况下,脚本执行后,屏幕只显示运行结果,没有其他内容。如果多个命令连续执行,它们的运行结果就会连续输出。有时会分不清,某一段内容是什么命令产生的。
set -x用来在运行结果之前,先输出执行的那一行命令。
#! /bin/bash
set -x # 执行指令前,先输出指令
#set -o xtrace # 另一种写法
echo hello
示例3. set -u
对于一些变量 APP= 若忘记设置值,可能会导致 rm -rf /${APP} 变为 rm -rf /. 这是非常危险的操作。
nounset -u 在扩展一个没有的设置的变量的时候, 显示错误的信息
执行脚本时,与到不存在变量,bash报错并停止
! /bin/bash
set -u # 注释与不注释执行结果不同
#set -o nounset #另一种写法
echo $a
echo hello
示例4. set -o pipefail
set -e有一个例外情况,就是不适用于管道命令。
所谓管道命令,就是多个子命令通过管道运算符(|)组合成为一个大的命令。Bash 会把最后一个子命令的返回值,作为整个命令的返回值。也就是说,只要最后一个子命令不失败,管道命令总是会执行成功,因此它后面命令依然会执行,set -e就失效了。
请看下面这个例子
#!/bin/bash
set -e
foo | echo a
echo bar
执行结果如下。
$ bash script.sh
a
script.sh:行4: foo: 未找到命令
bar
上面代码中,foo是一个不存在的命令,但是foo | echo a这个管道命令会执行成功,导致后面的echo bar会继续执行。
set -o pipefail用来解决这种情况,只要一个子命令失败,整个管道命令就失败,脚本就会终止执行。
set -eo pipefail
foo | echo a
echo bar
运行后,结果如下
$ bash script.sh
a
script.sh:行4: foo: 未找到命令
可以看到,echo bar没有执行。
总结
set命令的上面这四个参数,一般都放在一起使用。
# 写法一 set -euxo pipefail
# 写法二 set -eux
set -o pipefail
这两种写法建议放在所有 Bash 脚本的头部。
另一种办法是在执行 Bash 脚本的时候,从命令行传入这些参数。
$ bash -euxo pipefail script.sh