在bash中使用set -e/set + e与功能 [英] Using set -e / set +e in bash with functions

查看:569
本文介绍了在bash中使用set -e/set + e与功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在脚本中使用一个简单的bash序言:

I've been using a simple bash preamble like this in my scripts:

#!/bin/bash
set -e

结合模块化/使用功能,这今天困扰了我.

In conjunction with modularity / using functions this has bitten me today.

所以,说我在某个地方有一个函数

So, say I have a function somewhere like

foo() {
  #edit: some error happens that make me want to exit the function and signal that to the caller 
  return 2
}

理想情况下,我希望能够使用多个小文件,将它们的功能包含在其他文件中,然后像这样调用这些功能

Ideally I'd like to be able to use multiple small files, include their functions in other files and then call these functions like

set +e
foo
rc=$?
set -e

.这恰好适用于两层例程.但是,如果foo也这样调用子例程,则返回之前的最后一个设置为set -e,这将使脚本在返回时退出-我无法在调用函数中覆盖此函数.所以,我要做的是

. This works for exactly two layers of routines. But if foo is also calling subroutines like that, the last setting before the return will be set -e, which will make the script exit on the return - I cannot override this in the calling function. So, what I had to do is

foo() {
  #calling bar() in a shielded way like above
  #..      

  set +e
  return 2
}

我发现这很违反直觉(这也不是我想要的-如果在某些情况下我想使用该函数而不屏蔽故障,而在其他情况下我想处理清理该怎么办?)什么是最好的方法处理这个?顺便提一句.我正在OSX上执行此操作,尚未测试Linux上的这种行为是否有所不同.

Which I find very counterintuitive (and also not what I want - what if in some contexts I'd like to use the function without shielding against failures, while in other contexts I want to handle the cleanup?) What's the best way to handle this? Btw. I'm doing this on OSX, I haven't tested whether this behaviour is different on Linux.

推荐答案

Shell函数实际上没有返回值",只是退出代码.

Shell functions don't really have "return values", just exit codes.

您可以将&& :添加到调用方,这会使命令经过测试",并且不会退出该命令:

You could add && : to the caller, this makes the command "tested", and won't exit it:

foo() {
    echo 'x'
    return 42
}

out=$(foo && :)
echo $out

:是空命令"(即,它不执行任何操作).在这种情况下,它甚至都不会执行,因为它仅在foo返回0(不是)时才运行.

The : is the "null command" (ie. it doesn't do anything). In this case it doesn't even get executed, since it only gets run if foo return 0 (which it doesn't).

这将输出:

x

可以说有点丑陋,但是话又说回来,所有的shell脚本都可以说有点丑陋;-)

It's arguably a bit ugly, but then again, all of shell scripting is arguably a bit ugly ;-)

在FreeBSD中引用sh(1),这比bash的手册页解释得更好:

Quoting sh(1) from FreeBSD, which explains this better than bash's man page:

 -e errexit
         Exit immediately if any untested command fails in non-interactive
         mode.  The exit status of a command is considered to be explicitly
         tested if the command is part of the list used to control an if,
         elif, while, or until; if the command is the left hand operand of
         an "&&" or "||" operator; or if the command is a pipeline preceded
         by the ! operator.  If a shell function is executed and its exit
         status is explicitly tested, all commands of the function are con‐
         sidered to be tested as well.

这篇关于在bash中使用set -e/set + e与功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆