set命令

-- TOC --

set命令是 Bash 脚本的重要环节,却常常被忽视,导致脚本的安全性和可维护性出问题。

set是一个bash builtin命令,查看帮助 help set。参数用-表示打开,+表示关闭!

Set or unset values of shell options and positional parameters. Change the value of shell attributes and positional parameters, or display the names and values of shell variables.

在命令行直接使用set命令,不仅仅可以看到所有的环境变量,还能看到所有全局定义,比如shell函数。(如果只看环境变量,用env命令或printenv命令)

查看$-

$ echo $-

显示出来的字符串中的每一个字符,就是当前bash的set配置项!

-u

-u Treat unset variables as an error when substituting.

默认bash脚本在执行时,遇到不存在的变量,会忽略,继续执行后面的脚本代码。这样的行为模式有时并不是我们所希望的,我们希望像真正的代码那样,遇到不存在的变量,报错!此时,就需要使用 set -u

$ echo $ABCD
  # a blank line here
$ set -u
$ echo $ABCD
-bash: ABCD: unbound variable

set -u 放在.sh文件的前面,可以更容易发现脚本的错误。

等价的写法: set -o nounset

-x

-x Print commands and their arguments as they are executed.

默认情况下,脚本的执行只输出运行打印,而没有其它内容。如果连续多个命令执行,产生了很多输出,我们会难以分清哪些输出对应哪个命令,解决这个问题的方法,就是 set -x,然后在执行每一条命令的时候,会自动输出命令本身。

另外,还可以通过bash的命令行参数,来实现相同的功能:

$ bash -x <script>

-e

-e Exit immediately if a command exits with a non-zero status.

默认情况,bash脚本在执行过程中,如果某个命令执行失败,其返回为非0,脚本会继续执行,不会停下来。很多时候,我们都需要自己用 echo $? 或者 ret=$? 来判断上一个命令返回的状态,这就像在代码中判断一个函数的返回值一样。

如果希望改变这种模式,任何命令如果执行失败,整个脚本就停下来,就使用 set -e

当然,也有些命令的返回为非0,并不表示失败,这种情况在脚本中,可以这样来处理:

set -e  # non-zero stop
command1
command2
set +e  # return to default non-zero non-stop
command3
command4
set -e

调试shell脚本必备:set -uex

-o pipefail

set -e的一个例外情况是管道,就算设置了set -e,bash也只会把管道最后一个子命令的返回值,作为整个命令的返回值,因此,如果管道前面的命令执行失败,但是最后的子命令成功,整个命令还是成功,set -e就失效了!

解决这种情况,需要设置 set -o pipefail。结合-e,在脚本中,可以有这么一行:

set -eo pipefail

-o vi

命令行功能强大,可以很复杂很长,行编辑功能是long-command-line-life-saver。

默认命令行编辑的快捷键都是emacs风格,用这个命令set -o vi可以将快捷键设置为vi风格,输入命令按Esc后,对这一行的编辑就如同使用vi。

有人说他特别喜欢b键功能(按单词向后退),我还喜欢w键功能(按单词前进),当要修改很长的命令行时,这样的功能非常方便。

上下切换历史命令,也变成了jk0移动光标到开始,$移动光标到末尾。

D:从光标位置开始,向后删除所有;

d0:从光标位置开始,向前删除所有;

我有一篇专门收集Vim使用技巧的文章。

当行编辑处于vi模式下的时候,在vi的命令模式下,Ctrl-L快捷键的效果,有点像clear命令,但这个快捷键不是清除屏幕,而是将当前行顶到最上面,也是清屏的效果,但还可以向上滚动查看历史信息。

切回默认:set -o emacs

-n

set -n:等同于set -o noexec,不运行命令,只检查脚本的语法是否正确。

此功能也可以用bash的参数启动:

$ bash -n <script>

unset

删除某个shell变量,不管是环境变量,还是自定义的:unset varName

删除shell函数:unset -f functionName

-m

开启job control,具体请参考:Job Control

-f

-f Disable file name generation (globbing).

关闭命令行的glob功能,或者set -o noglob

设置位置参数

set positional parameters

用如下方式设置位置参数:

$ set 1 2 a b
$ echo $# $1 $2 $3 $4
4 1 2 a b

unset所有位置参数:

$ echo $# $1 $2 $3 $4
4 1 2 a b
$ set --
$ echo $# $1 $2 $3 $4
0

设置位置参数的同时,关闭-x和-v:$ set - 1 2 3,不知道有什么用?

本文链接:https://cs.pynote.net/sf/linux/shell/202110305/

-- EOF --

-- MORE --