linux bash e,关于Linux:在bash脚本中set -e是什么意思?

我正在研究这个preinst文件的内容,在从debian存档(.deb)文件中解包包包之前脚本会执行这个文件。

脚本包含以下代码:

#!/bin/bash

set -e

# Automatically added by dh_installinit

if ["$1" = install ]; then

if [ -d /usr/share/MyApplicationName ]; then

echo"MyApplicationName is just installed"

return 1

fi

rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf

rm -Rf $HOME/.local/share/file-manager/actions/*

fi

# End automatically added section

我的第一个查询是关于行:

set -e

我认为脚本的其余部分非常简单:它检查debian/ubuntu包管理器是否正在执行安装操作。如果是,它会检查我的应用程序是否刚刚安装在系统上。如果有,脚本将打印消息"myapplicationname is just installed"并结束(return 1表示以"错误"结束,不是吗?).

如果用户要求debian/ubuntu软件包系统安装我的软件包,脚本也会删除两个目录。

这是对的还是我错过了什么?

集合E

在谷歌中找不到这个的原因是:查询中的e被解释为否定。尝试以下查询:bash set"-e"

@当我问自己同样的问题时,我正看着man set

如果您想关闭它,请将破折号改为加号前缀:set +e。

@不过,问真人比问机器人要有趣得多。

@陪审团还是不在…我不完全相信我在SO上遇到的每一个提问者/评论者/回答者和家人都是"真正的人",而不是机器人……;-)

这里解释的是quora.com/…

江户十一〔二〕魔术!

From help set

-e  Exit immediately if a command exits with a non-zero status.

但有些人(Bash Faq and people writing this faq on IRC freenode ;Bash)认为这是坏的做法:

ZZU1

当出现错误时运行函数。

See http://mywiki.wooledge.org/bashfaq/105

如果我想要与"如果命令以非零状态退出,立即退出"相同的语义,该怎么办?

trap 'exit' ERR

以这种方式退出时,您还将获得非零状态

ERR陷阱不是由shell函数继承的,因此如果您有函数,set -o errtrace或set -E将允许您只设置一次陷阱,并将其全局应用。

@柯南,埃多克斯1〔5〕怎么样?我必须承认,我不清楚埃多克斯(EDOCX1)(2)什么时候开火。它是像set -E还是set -o pipefail?或者别的什么?

@aaronmcdaid我恐怕再也无法进入我做这些事情的环境(以前的工作),而且我不太记得设置。我从来不是这方面的专家,也许其他人更了解ERR?

trap 'exit' ERR与set -E有什么不同吗?

如果这是不好的做法,那么为什么要在Debian包中使用它呢?

这并不是普遍认为的坏习惯。和许多不受欢迎的语言结构一样,它也有自己的位置。它的主要问题是边缘情况下的行为有点不直观。

我也不同意这被认为是不好的做法。您提供的链接提到它不是一个完整的解决方案,并且存在gotchas,任何类型的编程解决方案都是如此。使用它的时间是正确的,使用它的时间是错误的。正如Rking在您链接到的文章中所说,"它具有有用的语义,因此从工具箱中排除它就是将其赋予fud。"

@Guypaddock,…用户名对那些没有在freenode bash通道上花费时间的人来说可能没有什么意义,但是"set-e不应该被使用"方面的人是已知的实体——greycat首先编写了bashfaq;geirha编写了一系列工具,包括用于单独测试命令的"evalbot"沙盒。虚拟机。当然,这是权威人士的论点,但作为一个在那里呆了十年的人,我不知道这个"Rking"人是谁,但我确实认识他们不同意的人。

…如果他们不同意的人是有很多时间/经验的人,他们试图为现实世界中的bash用户提供支持(从而了解新用户在哪里和如何被绊倒),那么这种经验告诉他们的信念,哪些语言功能最好避免,这一点可能值得一些人去做。注意。同样,我相信那些花了多年时间帮助调试n0bs编写到该语言的javascript的人,他们知道哪些语言特性容易出错,并且最好避免比随机的JS开发人员更多。

如果命令或管道有误,请停止脚本的执行,因为这是防御壳牌行为的对立,而这是脚本中的错误。在一个终端看到这座建筑物的文档。

仅当管道中的最后一个命令出错时,才会停止执行。有一个bash特定的选项,set -o pipefail,可以用来传播错误,这样,如果前面的某个命令以非零状态退出,那么pipeline命令的返回值就为非零。

如果一条管道由一个单一的简单命令、一份清单或一个复合命令返回一个非零状态组成,则该管道即可立即出口。

根据Default,管道的出口状态是管道中最后一个命令的出口状态,但不包括EDOCX1&6)。

如果这样,管道最后(右)状态的回报以一个非零状态存在,或如果所有指挥官都成功的话,则以零状态存在。

如果你想在出口上执行一些事情,试试定义trap,例如:

trap onexit EXIT

复制这个网站码到您的网站上以设置一个投票箱在您的网站上。

onexit(){ while caller $((n++)); do :; done; }

有类似的选择:-eerrtraceWhich would trap on ERR instead,E.G.:

trap onerr ERR

Examples

零状态示例:

$ true; echo $?

0

Non-零status example:

$ false; echo $?

1

Negating Status Examples:

$ ! false; echo $?

0

$ false || true; echo $?

0

测试与EDOCX1&6

$ bash -c 'set +o pipefail -e; true | true | true; echo success'; echo $?

success

0

$ bash -c 'set +o pipefail -e; false | false | true; echo success'; echo $?

success

0

$ bash -c 'set +o pipefail -e; true | true | false; echo success'; echo $?

1

与pipefail测试

$ bash -c 'set -o pipefail -e; true | false | true; echo success'; echo $?

1

我发现这个问题是在古灵试图找出由于一个set -e而引起的一个脚本的现状。答案不一定是我的;请问这个答案是什么。Basically,EDOCX1&0).Aborts the execution of a command(E.G.a shell script)and returns the exit status code of the command that failed(I.E.The inner script,not the outer script).

例如,假设我有一个壳牌outer-test.sh

#!/bin/sh

set -e

./inner-test.sh

exit 62;

The Code for inner-test.shis:

#!/bin/sh

exit 26;

当我运行时,从指挥线我的外脚本终结者与内幕的出口代码:

$ ./outer-test.sh

$ echo $?

26

我认为,我们的目的是让这个剧本迅速失败。

要自己测试,只需在bash提示下键入set -e。现在,试着运行ls。你会得到一个目录列表。现在,输入lsd。该命令无法识别并返回错误代码,因此bash提示将关闭(由于set -e)。

现在,要在"脚本"的上下文中理解这一点,请使用以下简单脚本:

#!/bin/bash

# set -e

lsd

ls

如果按原样运行,您将在最后一行从ls获得目录列表。如果取消对set -e的注释并再次运行,那么当bash遇到来自lsd的错误时,就不会看到目录列表停止处理。

这个答案是否增加了其他人在这个问题上没有给出的见解或信息?

我认为它对其他答案中没有的功能提供了清晰、简洁的解释。没有什么比其他回答更重要的了。

这是一个古老的问题,但是这里的答案都没有讨论在debian包处理脚本中使用set -e,也就是set -o errexit。根据Debian策略,在这些脚本中必须使用此选项;其目的显然是为了避免出现未处理的错误条件。

这在实践中意味着,您必须了解在什么条件下运行的命令可能返回错误,并显式地处理每个错误。

常见的gotchas包括:diff(当有差异时返回错误)和grep(当没有匹配时返回错误)。通过显式处理可以避免错误:

diff this that ||

echo"$0: there was a difference">&2

grep cat food ||

echo"$0: no cat in the food">&2

(还要注意我们如何注意在消息中包含当前脚本的名称,以及如何将诊断消息写入标准错误而不是标准输出。)

如果没有真正必要或有用的显式处理,则显式不执行任何操作:

diff this that || true

grep cat food || :

(Shell的:no op命令的使用有些模糊,但相当常见。)

只是重申一下,

something || other

if something; then

: nothing

else

other

fi

也就是说,我们明确地说,只有当something失败时,other才应该运行。longhand if(以及其他shell流控制语句,如while、until)也是处理错误的有效方法(事实上,如果不是这样,则带有set -e的shell脚本永远不能包含流控制语句!)

而且,更明确地说,在没有这样的处理程序的情况下,如果diff发现差异,或者grep没有找到匹配,set -e会导致整个脚本立即失败,并出现错误。

另一方面,有些命令在您希望的时候不会产生错误退出状态。通常有问题的命令是find(退出状态不反映是否实际找到文件)和sed(退出状态不显示脚本是否收到任何输入或是否成功执行任何命令)。在某些情况下,一个简单的保护是通过管道传输到一个命令,如果没有输出,该命令会发出尖叫:

find things | grep .

sed -e 's/o/me/' stuff | grep ^

应该注意,管道的退出状态是该管道中最后一个命令的退出状态。所以上面的命令实际上完全掩盖了find和sed的状态,只告诉你grep是否最终成功。

(当然,bash有set -o pipefail;但是debian包脚本不能使用bash特性。该政策明确规定了对这些脚本使用posix sh,尽管情况并非总是如此。)

在许多情况下,当进行防御编码时,这是需要单独注意的事情。有时,您必须检查一个临时文件,以便可以看到生成该输出的命令是否成功完成,即使成语和方便性会指导您使用shell管道。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值