如何在使用' set -e'时捕获ERR在巴什

时间:2016-03-04 15:41:55

标签: bash interrupt-handling

我有一个简单的脚本:

#!/bin/bash
set -e
trap "echo BOO!" ERR 

function func(){
    ls /root/
}

func

如果我的脚本失败,我想捕获ERR(因为它将在这里b / c我没有查看/ root的权限)。但是,使用set -e时,它不会被困住。没有set -e ERR被困。

根据bash手册页,set -e

  

... ERR上的陷阱(如果已设置)在shell退出之前执行。 ...

为什么我的陷阱没有被执行?从手册页看起来应该是这样。

3 个答案:

答案 0 :(得分:29)

chepner's answer是最佳解决方案:如果您希望set -e(与set -o errexit相同)与ERR合并陷阱,也使用set -o errtrace(与:set -E相同)

简而言之:使用set -eE 代替set -e

#!/bin/bash

set -eE  # same as: `set -o errexit -o errtrace`
trap "echo BOO!" ERR 

function func(){
    ls /root/
}

func

man bashset -o errtrace / set -E

  

如果设置,则ERR上的任何陷阱都由shell函数,命令替换和子shell环境中执行的命令继承。在这种情况下,ERR陷阱通常不会被继承。

我相信发生了什么:

  • 没有 -els命令在您的函数内失败,并且由于是函数中的最后一个命令,函数报告{{1调用者的非零退出代码,即您的顶级脚本范围。在范围中,ls陷阱生效,并且它被调用(但请注意,执行将继续,除非您从陷阱中明确调用ERR)。

  • 使用 exit(但没有-e):-E命令在函数中失败,因为ls生效,Bash 立即退出,直接来自功能范围 - 并且由于没有set -e陷阱生效 (因为它不是从父作用域继承的),不会调用您的陷阱。

虽然ERR页面不正确,但我同意这种行为并不十分明显 - 您必须推断它。

答案 1 :(得分:7)

您需要使用Advanced来继承陷阱。

答案 2 :(得分:4)

ERR替换为EXIT,它将有效。

trap命令的语法是:trap [COMMANDS] [SIGNALS]

有关详情,请参阅http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html