Linux脚本中set -eux分析

9 篇文章 1 订阅

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

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旺仔_牛奶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值