文章目录


官方手册:https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html

一、常用set命令属性

​set -o​​​可以查看所有属性
set命令详解_html
set命令详解_hash表_02

二、set -e

​说明​

"Exit immediately if a simple command exits with a non-zero status."
也就是说,在"set -e"之后出现的代码,一旦出现了返回值非零,整个脚本就会立即退出。

​示例​

#!/bin/bash

set -e
ls a.txt | echo "hi" >/dev/null
echo $?
echo "test"

执行结果:
set命令详解_linux_03
没有a.txt文件,但是ls a.txt | echo “hi” >/dev/null的返回码是0,因为set -e只捕获最后一个管道命令的返回值,从而导致遇错不退出脚本,依然执行后面的echo “test”

更好的方法是使用set -o pipefail

三、set -o pipefail

​说明​

"If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a  non-zero  status,or zero if all commands in the pipeline exit successfully.  This option is disabled by default."

设置了这个选项以后,包含管道命令的语句的返回值,会变成最后一个返回非零的管道命令的返回值

​示例​

#!/bin/bash

set -o pipefail
ls a.txt | echo "hi" >/dev/null
[[ $? -ne 0 ]] && exit 1
echo "test"

执行结果:
set命令详解_hash表_04
set -o pipefail是去捕获最后一个返回非零的管道命令的返回值,也就是ls a.txt的返回值;
没有a.txt文件,返回值为非0,因此[[ $? -ne 0 ]]条件成立,脚本退出,不执行echo “test”

四、set +h

​hashall​​​可以让Bash记录执行过的命令路径,并保存到一个内存的​​Hash表​​中,当再次执行相同命令时就不需要再通过PATH变量查找该命令的路径,这样可以提高效率。

但有时,程序的路径发生了变化,因为有Hash记录的存在反而会导致命令执行失败

[root@localhost ~]# hash
命中 命令
7 /usr/bin/openssl
1 /usr/bin/date
1 /usr/bin/tr
1 /usr/bin/uuidgen
1 /usr/bin/strings
4 /usr/bin/md5sum

如果将md5sum命令移动到/usr/local/bin/目录,此时系统依然根据Hash表记录的位置执行命令,就无法找到md5sum命令

[root@localhost ~]# mv /usr/bin/md5sum /usr/local/bin/
[root@localhost ~]# md5sum
-bash: /usr/bin/md5sum: 没有那个文件或目录

可以使用​​hash -d​​​删除某个记录信息,或者使用​​hash -r​​​清空整个Hash表,再或者使用​​set +h​​禁用hash表来解决这个问题

[root@localhost ~]# set +h    #禁用hash表
[root@localhost ~]# hash
-bash: hash: 哈希已禁用
[root@localhost ~]# md5sum /etc/passwd #命令可以正常使用
6322f6fcbc6e157963f5aa74f9e35039 /etc/passwd

五、set -u

开启​​nounset​​属性可以有效防止变量未定义的错误

a.sh脚本:

#!/bin/bash

set -u
useradd $1

执行结果:没有给$1赋值,会报错

[root@localhost shell]# bash a.sh
a.sh:行4: $1: 为绑定变量

六、set -x

打开脚本调试功能,也可以通过bash -x ***.sh打开

如果输出结果以双加号(++)开头则表示命令在子Shell中执行

七、set -n

检查shell语法,但不会执行,等同于bash -n xxx.sh