set命令
语法
# 语法
set [+-abCdefhHklmnpPtuvx]
# 参数
-a 标示已修改的变量,以供输出至环境变量。
-b 使被中止的后台程序立刻回报执行状态。
-C 转向所产生的文件无法覆盖已存在的文件。
-d Shell预设会用杂凑表记忆使用过的指令,以加速指令的执行。使用-d参数可取消。
-e 若指令传回值不等于0,则立即退出shell。
-f 取消使用通配符。
-h 自动记录函数的所在位置。
-H Shell 可利用"!"加<指令编号>的方式来执行history中记录的指令。
-k 指令所给的参数都会被视为此指令的环境变量。
-l 记录for循环的变量名称。
-m 使用监视模式。
-n 只读取指令,而不实际执行。
-p 启动优先顺序模式。
-P 启动-P参数后,执行指令时,会以实际的文件或目录来取代符号连接。
-t 执行完随后的指令,即退出shell。
-u 当执行时使用到未定义过的变量,则显示错误信息。
-v 显示shell所读取的输入值。
-x 执行指令后,会先显示该指令及所下的参数。
+<参数> 取消某个set曾启动的参数。
# 我们经常见到很多设立了脚本 打头会写如下
set -e
set -ex
set -eux
set -u
# 当使用-u后,如果使用了未定义的变量,就会报错,shell默认会把未定义的变量输出的时候为空行
[root@jiayu ~]# cat test.sh
#!/bin/bash
set -u
echo $test
[root@jiayu ~]# bash test.sh
test.sh: line 3: test: unbound variable
[root@jiayu ~]# cat test.sh
#!/bin/bash
set -u
test=1
echo $test
[root@jiayu ~]# bash test.sh
1
set -x
默认情况下,脚本执行后,屏幕只显示运行结果,没有其他内容。如果多个命令连续执行,它们的运行结果就会连续输出。有时会分不清,某一段内容是什么命令产生的
# 可以看到,执行echo bar之前,该命令会先打印出来,行首以+表示。这对于调试复杂的脚本是很有用的
[root@jiayu ~]# cat test.sh
#!/bin/bash
set -x
test=1
echo $test
[root@jiayu ~]# bash test.sh
+ test=1
+ echo 1
1
set -e
上面这些写法多少有些麻烦,容易疏忽。set -e从根本上解决了这个问题,它使得脚本只要发生错误,就终止执行
# 可以发现,当执行到foo后,由于没有该命令,后续不会执行了
[root@jiayu ~]# cat test.sh
#!/bin/bash
set -e
foo
echo bar
[root@jiayu ~]# bash test.sh
test.sh: line 3: foo: command not found
-e根据返回值来判断,一个命令是否运行失败。但是,某些命令的非零返回值可能不表示失败,或者开发者希望在命令失败的情况下,脚本继续执行下去。这时可以暂时关闭set
# -e,该命令执行结束后,再重新打开set -e
set +e
command1
command2
set -e
# 上面代码中,set +e表示关闭-e选项,set -e表示重新打开-e选项
# 还有一种方法是使用command || true,使得该命令即使执行失败,脚本也不会终止执行
[root@jiayu ~]# cat test.sh
#!/bin/bash
set -e
foo &>/dev/null || true
echo bar
[root@jiayu ~]# bash test.sh
bar
set -o pipefail
set -e有一个例外情况,就是不适用于管道命令
,所谓管道命令,就是多个子命令通过管道运算符(|)组合成为一个大的命令。会把最后一个子命令的返回值,作为整个命令的返回值
。也就是说,只要最后一个子命令不失败,管道命令总是会执行成功,因此它后面命令依然会执行
,set -e就失效了
# 下面代码中,foo是一个不存在的命令,但是foo | echo a这个管道命令会执行成功,导致后面的echo bar会继续执行
[root@jiayu ~]# cat test.sh
#!/bin/bash
set -e
foo | echo 1
echo bar
[root@jiayu ~]# bash test.sh
test.sh: line 3: foo: command not found
1
bar
# set -o pipefail用来解决这种情况,只要一个子命令失败,整个管道命令就失败,脚本就会终止执行,可看到echo bar并没有被执行
[root@jiayu ~]# cat test.sh
#!/bin/bash
set -eo pipefail
foo | echo 1
echo bar
[root@jiayu ~]# bash test.sh
test.sh: line 3: foo: command not found
1
参考博客
https://blog.csdn.net/weixin_29323493/article/details/116579248?utm_source=app&app_version=4.17.0