如何使用陷阱命令触发错误


13

我正在使用Ubuntu 12.04.2。我正在尝试使用“ trap”命令捕获外壳脚本中的异常或错误,但是我也试图手动触发“错误”退出。

我尝试退出1,但不会触发“错误”信号。

#!/bin/bash

func()
{
    exit 1
}

trap "echo hi" INT TERM ERR
func

不确定如何手动触发“错误”退出信号?

Answers:


20

ERR当shell自身以非零错误代码退出时,陷阱不运行代码,而是当该shell运行的任何不属于条件的命令(如in if cmd...cmd || ......)退出时都以非零代码退出退出状态(与导致set -e退出外壳的条件相同)。

如果要在退出状态为非零的外壳程序退出时运行代码,则应添加一个陷阱,EXIT然后在其中检查$?

trap '[ "$?" -eq 0 ] || echo hi' EXIT

但是请注意,在捕获到信号时,将同时运行信号陷阱和EXIT陷阱,因此您可能需要这样做:

unset killed_by
trap 'killed_by=INT;exit' INT
trap 'killed_by=TERM;exit' TERM
trap '
  ret=$?
  if [ -n "$killed_by" ]; then
    echo >&2 "Ouch! Killed by $killed_by"
    exit 1
  elif [ "$ret" -ne 0 ]; then
    echo >&2 "Died with error code $ret"
  fi' EXIT

或使用退出状态(如$((signum + 128))发出信号):

for sig in INT TERM HUP; do
  trap "exit $((128 + $(kill -l "$sig")))" "$sig"
done
trap '
  ret=$?
  [ "$ret" -eq 0 ] || echo >&2 "Bye: $ret"' EXIT

但是请注意,当您的父进程是像bash这样的shell时,通常会在SIGINT或SIGQUIT上退出,这可能会带来令人讨厌的副作用,该shell 实现了终端中断的等待和协作退出处理。因此,您可能需要确保使用相同的信号杀死自己,以便向父母报告您确实遭到了打扰,并且如果收到SIGINT / SIGQUIT,它也应该考虑退出自身。

unset killed_by
for sig in INT QUIT TERM HUP; do
  trap "exit $((128 + $(kill -l "$sig"))); killed_by=$sig" "$sig"
done
trap '
  ret=$?
  [ "$ret" -eq 0 ] || echo >&2 "Bye: $ret"
  if [ -n "$killed_by" ]; then
    trap - "$killed_by" # reset handler
    # ulimit -c 0 # possibly disable core dumps
    kill -s "$killed_by" "$$"
  else
    exec "$ret"
  fi' EXIT

如果要ERR触发陷阱,只需运行退出状态为非零的命令,例如 falsetest


6

使用回报,不会退出,从功能设置上退出的状态(如果该功能下降,通过无回报,状态是最后一个发言的是执行。)如果替换returnexit在问题的例子,它将作为工作我认为您打算这样做:陷阱将在ERR伪信号上触发,并显示“ hi”。出于其他考虑,请尝试以下操作:

#!/bin/bash

func()
{
    echo 'in func'
    return 99
    echo 'still in func'
}

trap 'echo "done"' EXIT
trap 'status=$?; echo "error status is $status"; trap - EXIT; exit $status' ERR
func
echo 'returned from func'

您可以尝试各种修改,例如返回0,注释掉ERR陷阱,不取消ERR处理程序中的EXIT陷阱,不从ERR处理程序中退出或删除返回值并将其false作为func中的最后一条语句。

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.