Как инициировать ошибку с помощью команды Trap

У меня была удача с коммерческой программой SpinRite на уровне 2 с палками usb. Если Вы недовольны результатами, я полагаю, что существует гарантия возврата денег.

13
27.04.2016, 19:05
2 ответа

ERR прерывание не должно выполнять код, когда сама оболочка выходит с ненулевым кодом ошибки, но когда любая команда, выполненная той оболочкой, которая не является частью условия (как в if cmd..., или cmd || ......) выходит с ненулевым статусом выхода (те же условия, как какой причины set -e выходить из оболочки).

Если Вы хотите выполнить код выхода оболочки с ненулевым статусом выхода, необходимо включить прерывание EXIT вместо этого и проверка $? там:

trap '[ "$?" -eq 0 ] || echo hi' 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

Обратите внимание однако, что выход обычно на SIGINT или SIGQUIT имеет потенциальные раздражающие побочные эффекты, когда Ваш родительский процесс является оболочкой как bash это реализует ожидание и совместную обработку выхода терминального прерывания. Так, можно хотеть удостовериться, что уничтожили себя с тем же сигналом вместо этого, чтобы сообщить Вашему родителю, что Вы были действительно прерваны, и что он должен рассмотреть выход из себя также, если бы он получил 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 захватите, чтобы стрелять, просто выполнить команду с ненулевым статусом выхода как false или test.

20
27.01.2020, 19:52

Используйте return, а не exit, чтобы установить статус при выходе из функции (если функция не выполняется без возврата, статус соответствует состоянию последней выполненной инструкции). Если вы подставляете return для exit в примере с вопросом он будет работать так, как я думаю, вы задумали: ловушка срабатывает по псевдосигналу ERR, и будет напечатано «привет». Для дополнительных соображений попробуйте следующее:

#!/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, отказ от отмены ловушки EXIT в обработчике ERR, отказ от выхода из обработчика ERR или удаление возврата и установка false как последний оператор в func.

6
27.01.2020, 19:52

Теги

Похожие вопросы