在bash中,是否存在等同于“错误消息”的错误


70

在perl中,您可以退出并显示错误消息msg die "some msg"。bash中是否有等效的单个命令?现在,我正在使用以下命令实现此目的:echo "some msg" && exit 1

Answers:


76

您可以轻松地自己滚动:

die() { echo "$*" 1>&2 ; exit 1; }
...
die "Kaboom"

1
+1; 但请注意,不带参数的die会发出不需要的换行符。我喜欢'{test -n“ $ @” && echo“ $ @”; 1号出口;}>&2'
威廉Pursell

4
@WilliamPursell:可以使用printf %s "${@+$@$'\n'}"-换句话说,打印参数,如果有的话,换行。
l0b0 2012年

六年后回头看这个答案,我意识到这"$*"可能比有意义"$@"。在大多数情况下,行为都是相同的,但是有所不同die -n Oops(不是您想要这样做)。
基思·汤普森

31

这就是我正在使用的。它太小了,无法放入库中,所以我必须输入数百次...

warn () {
    echo "$0:" "$@" >&2
}
die () {
    rc=$1
    shift
    warn "$@"
    exit $rc
}

用法: die 127 "Syntax error"


15

这是与perl的“ die”非常接近的功能(但具有功能名称):

function die
{
    local message=$1
    [ -z "$message" ] && message="Died"
    echo "$message at ${BASH_SOURCE[1]}:${FUNCNAME[1]} line ${BASH_LINENO[0]}." >&2
    exit 1
}

如果内置函数失败(使用函数名),那么将死​​掉的bash方式

function die
{
    local message=$1
    [ -z "$message" ] && message="Died"
    echo "${BASH_SOURCE[1]}: line ${BASH_LINENO[0]}: ${FUNCNAME[1]}: $message." >&2
    exit 1
}

因此,Bash将所有所需的信息保留在几个环境变量中:

  • LINENO-当前执行的行号
  • FUNCNAME-调用函数堆栈,第一个元素(索引0)是当前函数,第二个(索引1)是调用当前函数的函数
  • BASH_LINENO-调用行号栈,其中调用了相应的FUNCNAME
  • BASH_SOURCE-源文件数组,存储了对应的FUNCNAME

5
您可以完全避免使用局部变量${1-Died},这样,您甚至可以传入一个空字符串,它将按预期运行。
2015年

4

是的,这就是您的做法。

您可以使用分号或换行符代替&&,因为您想退出echo是否成功(尽管我不确定是什么使它失败)。

在Shell中进行编程意味着要使用许多小的命令(一些内置命令,一些微型程序),这些命令可以很好地完成一件事情,并将它们与文件重定向,退出代码逻辑和其他胶水连接起来。

如果您习惯于使用函数或方法来完成所有工作的语言,但似乎已经习惯了,那似乎很奇怪。


现在,我发现了另一个不愉快的效果。当执行echo命令时,解释器不会等待它完成,而是同时执行下面的代码!这是我所拥有的:CMD1 || (echo 'ERROR MSG'; exit 1); CMD2; CMD3。现在,如果CMD1失败,我希望回显和退出都会发生,脚本将退出。但是现在,当CMD1发生故障时,实际上会在回显之前执行CMD2和CMD3。这是根据错误日志。怪异与否?
PJx 2011年

实际上,我认为括号()可能是罪魁祸首。只需阅读某个地方,他们可能会在子shell中执行代码,这当然不会达到预期的效果。我只是将代码更改为if-fi块,并且按预期工作。出于好奇,我可以将此代码合并为一个代码吗?
PJx 2011年

2
使用{}代替()以避免subshel​​l问题。同样,将错误发送到stderr而不是stdout是一个好主意:CMD1 || { echo 'ERROR MSG' >&2; exit 1; }; CMD2; CMD3
Gordon Davisson

0
# echo pass params and print them to a log file
wlog(){
    # check terminal if exists echo 
    test -t 1 && echo "`date +%Y.%m.%d-%H:%M:%S` [$$] $*"
    # check LogFile and 
    test -z $LogFile || {
      echo "`date +%Y.%m.%d-%H:%M:%S` [$$] $*" >> $LogFile
    } #eof test
 } 
# eof function wlog 


# exit with passed status and message
Exit(){
    ExitStatus=0
    case $1 in
      [0-9]) ExitStatus="$1"; shift 1;;
  esac
    Msg="$*"
    test "$ExitStatus" = "0" || Msg=" ERROR: $Msg : $@"
    wlog " $Msg"
    exit $ExitStatus
}
#eof function Exit
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.