Як запустити помилку за допомогою команди Trap


13

Я використовую Ubuntu 12.04.2. Я намагаюся використовувати команду "пастка" для зйомки аномальних або помилок у моєму скрипті оболонки, але я також намагаюся вручну запустити вихід "Помилка".

Я спробував вихід 1, але він не спричинить сигнал "Помилка".

#!/bin/bash

func()
{
    exit 1
}

trap "echo hi" INT TERM ERR
func

Не знаєте, як вручну запустити сигнал виходу "Помилка"?

Відповіді:


20

ERRпастка не для запуску коду , коли сама оболонка виходить з ненульовим кодом помилки, але коли будь-яка команда запуску цієї оболонки , яка не є частиною стану (наприклад , в 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

Зауважте, однак, що звичайний вихід при SIGINT або SIGQUIT має потенційні роздратовані побічні ефекти, коли ваш батьківський процес є оболонкою, bashяка реалізує обробку виходу очікування та спільного переривання терміналу. Таким чином, ви можете переконатися, що ви вбили себе тим самим сигналом, щоб повідомити батькові, що вас дійсно перервали, і щоб він міг також вийти з себе, якщо він отримав Знак / Знак.

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.


6

Використовуйте повернення, не вихід, щоб встановити статус на виході з функції (якщо функція падає наскрізний без повернення, статус є те , що останнє твердження виконується.) Якщо ви замінюєте 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останнього твердження у функцію.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.