What does `set -x` do?

450
我有一个包含以下行的shell脚本:
[ "$DEBUG" == 'true' ] && set -x

26
请查看:help -m set | less - Cyrus
6
感谢提供 -m set 的帮助。这很有效。在询问之前,我尝试了 man set,但在Ubuntu上会显示 No manual entry for set - Ole
3
@Ole,set是内置于bash中的命令,因此如果您查看man bash,可以在“SHELL BUILTIN COMMANDS”部分找到它。在查看man页面时,您可以通过搜索这个正则表达式\bset \[来快速跳转到该部分。 - User5910
8
man用于非内置命令,help用于shell内置命令。 - codeforester
1
顺便说一下,字符串比较运算符应该是=而不是==;后者是一个非标准扩展,前者是官方标准化的,并且保证在所有符合POSIX标准的sh实现中都可用。 - Charles Duffy
3个回答

637

set -x 启用shell的一种模式,其中所有执行的命令都会打印到终端。在您的情况下,它明显是用于调试,这是 set -x 的典型用例:如果脚本的功能不如预期,打印执行的每个命令可以帮助您可视化脚本的控制流程。

set +x 禁用该模式。


5
这非常有用!我希望早点有人告诉我这个。是否还有其他有趣的技巧能够提升我们编写脚本的元技能? - Student
23
在你的脚本顶部加上set -e,将使脚本在发生错误时退出并显示错误信息(除非特别处理)。与默认情况相比,我认为这种方式更可取,因为默认情况下脚本会继续运行而不管错误(就像Visual Basic中臭名昭著的On Error Resume Next一样)。 - John Zwinck
5
很遗憾,set -e 的副作用非常不好,甚至会使代码审查几乎变得不可能(因为一行代码的行为取决于调用栈上下文 -- 如果在“检查”上下文中调用函数,则对该调用以及其所有子调用禁用 set -e)。请参见BashFAQ#105中的练习。 - Charles Duffy
2
@JohnZwinck,是的,但我不知道rking是谁。Greycat是BashFAQ的作者,freenode IRC #bash频道的长老等等——如果你要通过权威来争论,了解领域内的权威人物会有所帮助。而且,我绝对会为 tediously 检查每个命令的退出处理辩护,就像在 C 或 Go 中进行代码审查一样,或者任何其他不支持异常的语言。依赖于 set -e 就是依赖于一些根本不可靠的东西。 - Charles Duffy
6
顺便提一句:这些消息会被打印到标准错误输出(stderr),所以如果您在Docker容器中运行此类脚本,这些消息会被解释为错误。 :) - rudi
显示剩余2条评论

107

$(set -x)

打印简单命令的跟踪,对于命令、case命令、select命令以及算术命令和它们的参数或关联的词列表,在它们被展开但尚未执行之前。PS4变量的值被展开,并在命令及其展开后的参数之前打印出结果值。

[source]

示例

set -x
echo $(expr 10 + 20)
+ expr 10 + 20
+ echo 30
30

set +x
echo $(expr 10 + 20)
30

上面的例子说明了set -x的用法。当它被使用时,上述算术表达式会被展开。我们可以看到一行代码是如何逐步评估的。
  • 第一步评估了expr
  • 第二步评估了echo

要了解更多关于set的信息,请访问此链接

说到你的shell脚本,

[ "$DEBUG" == 'true' ] && set -x

你的脚本在选择执行模式为DEBUG时可能会打印一些额外的信息行。传统上,当脚本使用可选参数如-d调用时,人们习惯启用调试模式。

1
在编写示例时,请考虑使用$( )而不是反引号。自从上世纪90年代初首次发布以来,它已成为POSIX.2标准的一部分,因此没有任何有意义的可移植性损失,并且它的形式更好(嵌套良好,不改变包含在内部的反斜杠的含义等)。 - Charles Duffy
感谢@CharlesDuffy的建议,同意你的评论,并已更新答案! - Raju

23

-u:默认情况下禁用。启用后,当使用未配置的变量时会显示错误消息。

-v:默认情况下未激活。激活后,在输出信息之前将显示信息的原始内容(未经过变量解析)。

-x:默认情况下未激活。如果激活,命令内容将在运行命令之前显示(经过变量解析后,添加了++符号)。

比较以下差异:

/ # set -v && echo $HOME
/root
/ # set +v && echo $HOME
set +v && echo $HOME
/root

/ # set -x && echo $HOME
+ echo /root
/root
/ # set +x && echo $HOME
+ set +x
/root

/ # set -u && echo $NOSET
/bin/sh: NOSET: parameter not set
/ # set +u && echo $NOSET

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接