使用set -e运行bash函数而不退出shell

时间:2014-05-22 12:15:36

标签: bash shell

考虑以下功能

function current_dir {
  set -e
  git foobar
  echo "I will not print this, because git foobar returned a non-zero exit code"
}

现在,当我获取函数并尝试在我的shell中调用它时,它不仅退出函数,还退出shell本身。

如何避免这种情况?

3 个答案:

答案 0 :(得分:5)

如果你不需要在当前shell中执行该函数(例如,它不是设置需要对调用者可见的任何参数值),你可以创建函数的主体子shell,而不是命令组:

current_dir () (
    set -e
    git foobar
    echo "I will not print this, because git foobar returned a non-zero exit code"
)

答案 1 :(得分:4)

据我所知,set -e将完全按照您的看法执行:只要命令以非零状态退出,就会完全退出shell。

您可以尝试使用trap或在命令之间使用&&重新构建函数:

function current_dir {
  git foobar && echo "I will not print this, because git foobar returned a non-zero exit code"
}

或(更好的可读性):

function current_dir {
  trap 'trap - ERR; return' ERR
  git foobar
  ...other commands...
  echo "I will not print this, because a command returned a non-zero exit code"
}

如果您出于某种原因确实需要set -e,可以使用set +e临时禁用它,并在关键部分后重新启用它。

答案 2 :(得分:3)

“set -e”用于在命令(管道或子shell命令等)以非零状态退出时立即退出。

默认情况下,BASH会忽略错误并继续解释您的脚本。这可能会导致一个非常糟糕的惊喜,例如:

    if ! lss myLock
    then touch myLock; echo "No lock, I can do the job"; rm -f myLock
    fi

此脚本的结果是:

bash: lss : commande introuvable
No lock, I can do the job

正如您所看到的,BASH在找不到的命令和失败的命令之间没有区别。

“ - e”经常用于确保Shell解释器在发生错误后立即停止(因此我们必须考虑所有错误......)这有助于防止在我们执行错误时出现非常糟糕的问题脚本(想想一个rm -rf“$ v”/ *当你忘了设置v ;-))。为此,我们在shebang中传递“-e”选项。显然,它不是为交互式使用而设计的,我不会想象“set -e”的好用,也不能用“set + e”(但要测试)。

回答您的初步问题。您可以通过应用以下解决方案之一来避免终止shell:

使用if语句

function myF1() {
    if git foobar; then
        echo "I will not print this, because git foobar returned a non-zero exit code"
    fi
}

使用控制运算符&&

function myF2() {
    git foobar && \
    echo "I will not print this, because git foobar returned a non-zero exit code"
}

打开子shell

function myF4() {(
    set -e
    git foobar
    echo "I will not print this, because git foobar returned a non-zero exit code"
)}

在这种情况下,“set -e”将立即退出子shell,但它不会终止调用者: - )

使用陷阱不是一个好主意,因为它会对调用者造成副作用(陷阱是全局定义的)。显然我们可以将陷阱和子shell结合起来,但在你的情况下它并没有用。