Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Bash 脚本 set 命令教程

Bash 脚本 set 命令教程

作者头像
ruanyf
发布于 2018-04-12 09:43:51
发布于 2018-04-12 09:43:51
2K0
举报

服务器的开发和管理离不开 Bash 脚本,掌握它需要学习大量的细节。

set命令是 Bash 脚本的重要环节,却常常被忽视,导致脚本的安全性和可维护性出问题。本文介绍它的基本用法,让你可以更安心地使用 Bash 脚本。

一、简介

我们知道,Bash 执行脚本的时候,会创建一个新的 Shell。

$ bash script.sh

上面代码中,script.sh是在一个新的 Shell 里面执行。这个 Shell 就是脚本的执行环境,Bash 默认给定了这个环境的各种参数。

set命令用来修改 Shell 环境的运行参数,也就是可以定制环境。一共有十几个参数可以定制,官方手册有完整清单,本文介绍其中最常用的四个。

顺便提一下,如果命令行下不带任何参数,直接运行set,会显示所有的环境变量和 Shell 函数。

$ set

二、set -u

执行脚本的时候,如果遇到不存在的变量,Bash 默认忽略它。

#!/usr/bin/env bash echo $a echo bar

上面代码中,$a是一个不存在的变量。执行结果如下。

$ bash script.sh bar

可以看到,echo $a输出了一个空行,Bash 忽略了不存在的$a,然后继续执行echo bar。大多数情况下,这不是开发者想要的行为,遇到变量不存在,脚本应该报错,而不是一声不响地往下执行。

set -u就用来改变这种行为。脚本在头部加上它,遇到不存在的变量就会报错,并停止执行。

#!/usr/bin/env bash set -u echo $a echo bar

运行结果如下。

$ bash script.sh bash: script.sh:行4: a: 未绑定的变量

可以看到,脚本报错了,并且不再执行后面的语句。

-u还有另一种写法-o nounset,两者是等价的。

set -o nounset

三、set -x

默认情况下,脚本执行后,屏幕只显示运行结果,没有其他内容。如果多个命令连续执行,它们的运行结果就会连续输出。有时会分不清,某一段内容是什么命令产生的。

set -x用来在运行结果之前,先输出执行的那一行命令。

#!/usr/bin/env bash set -x echo bar

执行上面的脚本,结果如下。

$ bash script.sh + echo bar bar

可以看到,执行echo bar之前,该命令会先打印出来,行首以+表示。这对于调试复杂的脚本是很有用的。

-x还有另一种写法-o xtrace

set -o xtrace

四、Bash 的错误处理

如果脚本里面有运行失败的命令(返回值非0),Bash 默认会继续执行后面的命令。

#!/usr/bin/env bash foo echo bar

上面脚本中,foo是一个不存在的命令,执行时会报错。但是,Bash 会忽略这个错误,继续往下执行。

$ bash script.sh script.sh:行3: foo: 未找到命令 bar

可以看到,Bash 只是显示有错误,并没有终止执行。

这种行为很不利于脚本安全和除错。实际开发中,如果某个命令失败,往往需要脚本停止执行,防止错误累积。这时,一般采用下面的写法。

command || exit 1

上面的写法表示只要command有非零返回值,脚本就会停止执行。

如果停止执行之前需要完成多个操作,就要采用下面三种写法。

# 写法一 command || { echo "command failed"; exit 1; } # 写法二 if ! command; then echo "command failed"; exit 1; fi # 写法三 command if [ "$?" -ne 0 ]; then echo "command failed"; exit 1; fi

另外,除了停止执行,还有一种情况。如果两个命令有继承关系,只有第一个命令成功了,才能继续执行第二个命令,那么就要采用下面的写法。

command1 && command2

五、 set -e

上面这些写法多少有些麻烦,容易疏忽。set -e从根本上解决了这个问题,它使得脚本只要发生错误,就终止执行。

#!/usr/bin/env bash set -e foo echo bar

执行结果如下。

$ bash script.sh script.sh:行4: foo: 未找到命令

可以看到,第4行执行失败以后,脚本就终止执行了。

set -e根据返回值来判断,一个命令是否运行失败。但是,某些命令的非零返回值可能不表示失败,或者开发者希望在命令失败的情况下,脚本继续执行下去。这时可以暂时关闭set -e,该命令执行结束后,再重新打开set -e

set +e command1 command2 set -e

上面代码中,set +e表示关闭-e选项,set -e表示重新打开-e选项。

还有一种方法是使用command || true,使得该命令即使执行失败,脚本也不会终止执行。

#!/bin/bash set -e foo || true echo bar

上面代码中,true使得这一行语句总是会执行成功,后面的echo bar会执行。

-e还有另一种写法-o errexit

set -o errexit

六、set -o pipefail

set -e有一个例外情况,就是不适用于管道命令。

所谓管道命令,就是多个子命令通过管道运算符(|)组合成为一个大的命令。Bash 会把最后一个子命令的返回值,作为整个命令的返回值。也就是说,只要最后一个子命令不失败,管道命令总是会执行成功,因此它后面命令依然会执行,set -e就失效了。

请看下面这个例子。

#!/usr/bin/env bash set -e foo | echo a echo bar

执行结果如下。

$ bash script.sh a script.sh:行4: foo: 未找到命令 bar

上面代码中,foo是一个不存在的命令,但是foo | echo a这个管道命令会执行成功,导致后面的echo bar会继续执行。

set -o pipefail用来解决这种情况,只要一个子命令失败,整个管道命令就失败,脚本就会终止执行。

#!/usr/bin/env bash set -eo pipefail foo | echo a echo bar

运行后,结果如下。

$ bash script.sh a script.sh:行4: foo: 未找到命令

可以看到,echo bar没有执行。

七、总结

set命令的上面这四个参数,一般都放在一起使用。

# 写法一 set -euxo pipefail # 写法二 set -eux set -o pipefail

这两种写法建议放在所有 Bash 脚本的头部。

另一种办法是在执行 Bash 脚本的时候,从命令行传入这些参数。

$ bash -euxo pipefail script.sh

八、参考链接

(完)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017年11月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Shell 脚本调试终极技巧:set -x 之外你还需要知道这些
我一开始写 shell 脚本的时候,基本靠“echo 大法”调试。加上 set -x,自以为天下无敌。直到有一次,脚本执行后变量莫名其妙为空、某个 if 判断永远不成立、死循环打爆了机器……
Echo_Wish
2025/07/12
510
Shell 脚本调试终极技巧:set -x 之外你还需要知道这些
季更48/90
编程随想 Python列表 list=["a","b","c"] //遍历列表 for item in list: print(item) Python字典 dic={"Baotou":"蒙B","Huhehaote":"蒙A"}print(dic["Huhehaote"]) //遍历字典 for key,value in dic.items(): print(key) print(value) Python面向对象 //定义对象 class Song(): def __in
编程随想曲
2022/04/21
2790
编写快速安全Bash脚本的建议
作者:oschina 来源:https://www.oschina.net/translate/bash-scripting-quirks-safety-tips?print 昨天我和一些朋友聊起Ba
小小科
2018/05/02
2.1K0
编写快速安全Bash脚本的建议
Linux 命令(230)—— set 命令(builtin)
set 命令主要用于查看和修改 Shell 环境的运行参数,可以定制 Shell 脚本的运行环境。
恋喵大鲤鱼
2022/12/24
4.7K0
linux26-命令除错不完全指南
Date : [[2022-02-10_Thu]] 微信公众号 : 北野茶缸子 Tags : #linux/index/01 #linux/linux编程 参考: Bash 脚本中的错误处理 | 《
北野茶缸子
2022/12/10
1K0
两分钟学会Shell常用的知识点
set是BASH内置的命令,如果不提供选项给set,默认情况下会打印所有的变量和函数的名称和值。
公众号: 云原生生态圈
2021/11/15
4670
[翻译]15分钟bash进阶
需要注意的是,有些Linux命令可以使用一些选项来强制忽略错误,比如rm -f和mkdir -p。
陆道峰
2020/06/17
1.6K0
Shell 简明教程
Shell 的作用是解释执行用户的命令,用户输入一条命令,shell 就行一条,这种方式成为交互式,还有另外一种方式,就是用户事先写一个 shell 脚本,包含很多命令,然后让 shell 一次性的进行执行,这种方式被称为“批处理方式”。 一般我们在UNIX中使用的 shell 就是 bash 和 sh,当然也有其他 shell,在 UNIX 环境下可以使用 /etc/shells: valid login shells 命令来显示所有的 shell,想要切换,直接输入 shell 名即可。
用户3147702
2022/06/27
2.2K0
Shell 简明教程
Bash速查表
例 #!/usr/bin/env bash NAME="John" echo "Hello $NAME!" 变量 NAME="John" echo $NAME echo "$NAME" echo "${NAME}!" 字符串引号 NAME="John" echo "Hi $NAME" #=> Hi John echo 'Hi $NAME' #=> Hi $NAME 条件执行 git commit && git push git commit || echo "Commit failed" 功能 get
步履不停凡
2019/08/23
8030
shell | 开启debug模式
shell脚本是没有debug模式的,不过可以通过 set 指令实现简单的debug功能
Amadeus
2022/10/25
1.4K0
shell | 开启debug模式
高效的Shell编程建议及入坑
描述:在进行shell脚本语言编写的时候,不仅要注意写的功能,更要注意他的美观以及通用性,还需要让其他参与运维的人都能看懂;
全栈工程师修炼指南
2022/09/28
9790
高效的Shell编程建议及入坑
node 镜像 ENTRYPOINT 脚本解析
以 node:18 为例,node 官方镜像的 ENTRYPOINT 入口脚本为以下内容:
山月
2022/11/02
1K0
node 镜像 ENTRYPOINT 脚本解析
编写可靠 bash 脚本的一些技巧
作者:astarsun,腾讯搜索工程师 写过很多 bash 脚本的人都知道,bash 的坑不是一般的多。其实 bash 本身并不是一个很严谨的语言,但是很多时候也不得不用。以下总结了一些编写可靠的 bash 脚本的小 tips。 0. set -x -e -u -o pipefail 在写脚本时,在一开始(Shebang 之后)加上下面这一句,或者它的缩略版,能避免很多问题,更重要的是能让很多隐藏的问题暴露出来: set -xeuo pipefail 下面说明每个参数的作用,以及一些例外的处理方式
腾讯技术工程官方号
2020/04/13
1.3K0
Shell脚本
Shell 脚本是运行在 shell 环境中的脚本语言,用于自动执行重复性任务、管理系统配置、以及通过编写脚本和运行脚本来执行一系列命令。shell 脚本可以帮助我们完成系统管理、软件安装、文件操作等需求。
用户10638239
2024/01/29
3830
Shell 脚本攻略之小试牛刀
作者: Escape 链接:https://www.escapelife.site/posts/e8431cda.html
杰哥的IT之旅
2021/04/20
7920
如何写出安全的、基本功能完善的Bash脚本
每个人或多或少总会碰到要使用并且自己完成编写一个最基础的Bash脚本的情况。真实情况是,没有人会说“哇哦,我喜欢写这些脚本”。所以这也是为什么很少有人在写的时候专注在这些脚本上。 我本身也不是一个Bash脚本专家,但是我会在本文中跟你展示一个最基础最简单的安全脚本模板,会让你写的Bash脚本更加安全实用,你掌握了之后肯定会受益匪浅。 为什么要写Bash脚本 其实关于Bash脚本最好的解释如下: The opposite of "it's like riding a bike" is "it's like p
程序猿DD
2023/04/04
6800
如何写出安全的、基本功能完善的Bash脚本
Linux shell 程序设计2——bash的内置命令
常用的内置命令忽略,来看看shell编程中其他一些重要的内置命令: 1、help:显示所有内置命令列表,或显示一个具体命令的用法。 -s: 表示列出命令的语法格式 例子: help -s help help: help [-dms] [pattern ...] 2、echo:用来显示一行文字。默认自动换行。 -n:取消自动换行。 -e:让字符串中的特殊字符起作用,即使字符串在单引号中。 例子: echo hello world 或 echo 'hello world' 或 echo "hello wo
宅蓝三木
2018/02/07
1.5K0
一篇文章让你彻底掌握 Shell
Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。
硬件开源小站
2023/04/07
2.3K0
shell脚本还能这么写?
在平常的开发中,脚本会依赖很多的配置,例如监听端口、配置文件之类的可变参数,如果我们将其硬编码到脚本中,那么改起来就是牵一发动全身了,很麻烦,不可靠。测试我们就需要变量来帮忙了,这样只需要修改一处,脚本整体生效,高效很多。
yxxhero
2022/05/31
1.5K0
Bash 编程易错总结大全
Bash Pitfalls[1] 文章介绍了 40 多条日常 Bash 编程中,老手和新手都容易忽略的错误编程习惯。每条作者在给出错误的范例上,详细分析与解释错误的原因,同时给出正确的改写建议。文中有不少引用的文章,也值得大家仔细阅读。仔细阅读了这篇文章后,收获很多,不感独享,把这篇文章以半翻译半笔记的形式分享给大家。
码农架构
2022/11/17
3K0
Bash 编程易错总结大全
相关推荐
Shell 脚本调试终极技巧:set -x 之外你还需要知道这些
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档