set -euxo pipefail
有些开发人员会用Bash来实现很复杂的功能,就像使用别的高级语言一样。他可能觉得自己很牛逼但其他人早就想锤爆他了,Bash的可读性和可维护性远远低于任何高级语言。更要命的是,Bash并没有方便的调试工具和防错机制,出了问题你要排查半天。
在Ruby或者Python等高级语言里,你很容易知道错误是哪行什么类型的错误,还有IDE的Debugger加持。而Bash只能看源码,通过打印log等非常低效的方式调试。
本文将介绍Bash中 set -euxo pipefail,它们可以帮助你写出更容易维护也更安全的脚本。这也是Bash脚本的终极调试手段,希望你以后在自己的脚本中加上这么一行,头顶也能少秃一点。
set -e
set -e 选项可以让你的脚本在出现异常时马上退出,后续命令不再执行。默认情况下Shell脚本不会因为错误而结束执行,但大多数情况是,我们希望出现异常时就不要再往下走了。假如你的if判断条件里会出现异常,这时脚本也会直接退出,但可能这并不是你期望的情况,这时你可以在判断语句后加上 || true 来阻止退出。
Before
#!/bin/bash# 'foo' is a non-existing commandfooecho "bar"# output# ------# line 4: foo: command not found# bar
After
#!/bin/bashset -e# 'foo' is a non-existing commandfooecho "bar"# output# ------# line 5: foo: command not found
阻止立即退出的例子。
#!/bin/bashset -e# 'foo' is a non-existing commandfoo || trueecho "bar"# output# ------# line 5: foo: command not found# bar
set -o pipefail
默认情况下Bash只会检查管道(pipeline)操作最后一个命令的返回值,假如最右边的命令成功那么它就认为这个语句没问题。这个行为其实是很不安全的,所以就有了set -o pipefail。这个特别的选项表示在管道连接的命令中,只要有任何一个命令失败(返回值非0),则整个管道操作被视为失败。只有管道中所有命令都成功执行了这个管道才算成功执行。
Before
#!/bin/bashset -e# 'foo' is a non-existing commandfoo | echo "a"echo "bar"# output# ------# a# line 5: foo: command not found# bar
After
#!/bin/bashset -eo pipefail# 'foo' is a non-existing commandfoo | echo "a"echo "bar"# output# ------# a# line 5: foo: command not found
set -u
set -u 比较容易理解,Bash会把所有未定义的变量视为错误。默认情况下Bash会将未定义的变量视为空,不会报错,这也是很多坑的来源。也许由于变量名的细微差别让你查半天最后骂骂咧咧。
Before
#!/bin/bashset -eo pipefailecho $aecho "bar"# output# ------## bar
After
#!/bin/bashset -euo pipefailecho $aecho "bar"# output# ------# line 5: a: unbound variable
set -x
set -x 可以让Bash把每个命令在执行前先打印出来,你可以认为这就是Bash的Debug开关。它的好处当然显而易见,方便你快速找到有问题的脚本位置,但是也坏处也有吧,就是Bash的log会格外的乱。另外,它在打印命令前会把变量先解析出来,所以你可以知道当前执行的语句的变量值是什么。纵然log可能会乱一些,总比头发乱一些好,所以建议还是打开这个开关。
#!/bin/bashset -euxo pipefaila=5echo $aecho "bar"# output# ------# + a=5# + echo 5# 5# + echo bar# bar
以上就是关于 set -euxo pipefail 的介绍,从Shell脚本的编写角度看,我十分建议所有人都应该在自己的Shell脚本里加上这么一行。但从实际情况看,如果你的Shell脚本已经超过200行,我更建议你换成高级语言来实现。比如Python或者Ruby甚至Perl,这些高级语言在Linux系统都是内置的,注意版本兼容性就好,写起来比Shell舒服太多了。
set -euxo pipefail的更多相关文章
- Bash 脚本中的 set -euxo pipefail
有些开发人员会用Bash来实现很复杂的功能,就像使用别的高级语言一样.他可能觉得自己很牛逼但其他人早就想锤爆他了,Bash的可读性和可维护性远远低于任何高级语言.更要命的是,Bash并没有方便的调试工 ...
- Linux 命令小记
1. pidof 进程名 :获取进程的pid,例如 pidof memcached 得到5333 2. unset Shell变量 :取消设置一个shell变量,从内存和shell的导出环境中删除它, ...
- 分享一例脚本发版和tomcat重启脚本
线上有个网站业务部署在tomcat上,由于频繁上线修改,需要经常启动tomcat.tomcat服务自带的bin下没有重启脚本,下面分享一例脚本发版和tomcat重启脚本: 1)现将业务代码从svn里下 ...
- Shell脚本字符串匹配及日常命令工具 - 用法总结(技巧指南)
Shell提供了很多字符串和文件处理的命令,如awk.expr.grep.sed等命令,还有文件的排序.合并和分割等一系列的操作命令.下面重点总结下Shell字符串处理.文本处理以及各类命令及函数用法 ...
- Bash 脚本 set 命令教程
http://www.ruanyifeng.com/blog/2017/11/bash-set.html set命令是 Bash 脚本的重要环节,却常常被忽视,导致脚本的安全性和可维护性出问题.本文介 ...
- bash之set命令
set命令是 Bash 脚本的重要环节,却常常被忽视,导致脚本的安全性和可维护性出问题.本文介绍它的基本用法,让你可以更安心地使用 Bash 脚本. 一.简介 我们知道,Bash 执行脚本的时候,会创 ...
- shell 脚本之set 命令(转)
服务器的开发和管理离不开 Bash 脚本,掌握它需要学习大量的细节. set命令是 Bash 脚本的重要环节,却常常被忽视,导致脚本的安全性和可维护性出问题.本文介绍它的基本用法,让你可以更安心地使用 ...
- shell脚本部署redis以及redis主从复制和redis-cluster集群
# 关于脚本: # 使用root用户执行此脚本,提前关闭selinux: # 执行脚本之前,hostsIP内的IP修改成自己的机器IP: # hostsIp内的IP数量如果有增加或者减少,for循环的 ...
- linux中的set -e 与set -o pipefail
1.set -e "Exit immediately if a simple command exits with a non-zero status." 在“set -e”之后出 ...
- shell脚本中的set -e和set -o pipefail
工作中经常在shell脚本中看到set的这两个用法,但就像生活中的很多事情,习惯导致忽视,直到出现问题才引起关注. 1. set -eset命令的-e参数,linux自带的说明如下:"Exi ...
随机推荐
- 高通ADSP USB流程
在高通平台上,ADSP(Audio Digital Signal Processor,音频数字信号处理器)可以通过 USB 接口与主机进行数据传输,以下是大致的 ADSP USB 流程: 主机发起 U ...
- vue前端开发仿钉图系列(6)左侧记事本的开发详解
在页面开发中,深深的被element组件所吸引,里面很多小组件都可以直接使用.像是记事本提示.记事本列表时间线.右侧编辑页面的form表单,编辑和查看状态的切换等等,比之前iOS原生开发所有的东西都要 ...
- 区分::after和:before中的单冒号和双冒号的作用
单冒号:一般指的是伪类,如鼠标悬停状态设置样式:选择器:hover {设置样式} 双冒号一般指伪元素,给元素的前面/后面添加内容.内容数据按堆栈数据结构存储.
- 封装 axios 拦截器
import axios from "axios"; // 自定义一个 request 实例 const request = axios.create({ baseURL: &qu ...
- ProxyPin 抓包,原来可以这么简单!
你是否还在为网络请求的抓包发愁?其实,ProxyPin 可以让抓包操作变得异常简单!不需要复杂的设置,也不用繁琐的配置,轻松几步就能实现.让我们一起来看看吧! 抓包操作常用于测试网络请求.分析接口 ...
- KubeSphere 社区双周报|2024.09.27-10.10
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...
- Kubernetes 升级不弃 Docker:KubeKey 的丝滑之道
作者:尹珉,KubeSphere Ambaasador&Contributor,KubeSphere 社区用户委员会杭州站站长. 引言 随着 Kubernetes 社区的不断发展,即将迎来 K ...
- 快速部署和测试ingress-nginx:1.9.6
点击查看代码 下载deploy文件 https://github.com/kubernetes/ingress-nginx/blob/controller-v1.9.6/deploy/static/p ...
- 我在大厂做 CR——如何体系化防控空指针异常
大家好,我是木宛哥,今天和大家分享下--代码 CR 时针对恼人的空指针异常(NullPointerException)如何做到体系化去防控: 什么是空指针异常 从内存角度看,对象的实例化需要在堆内存中 ...
- 01 Eclipse使用Maven慢的问题解决
1. Eclipse 使用的是内置的 Maven Eclipse 有可能使用了内置的 Maven,而不是独立安装的 Maven.如果使用 Eclipse 内置的 Maven,默认的 settings. ...