Обработка ловушек и неявные дочерние оболочки в сценариях оболочки

10

Допустим, у вас есть сценарий оболочки, который выполняет какой-то код очистки через EXITловушку, например:

#!/bin/bash

mytrap () {
  echo "It's a trap!" >&2
}

trap mytrap exit

echo I am at the end of the script.

Как и ожидалось, он будет распечатан It's a trap!при выходе из скрипта:

$ sh myscript
I am at the end of the script.
It's a trap!

Вы модифицируете скрипт, чтобы добавить функцию, которая генерирует некоторый вывод, который в конечном итоге передается другой команде, например так:

#!/bin/bash

mytrap () {
  echo "It's a trap!" >&2
}

myfunc () {
  echo "I've got a bad feeling about this..."
}

trap mytrap exit

myfunc | cat > /dev/null

echo I am at the end of the script.

Из-за конвейера код внутри myfuncзапускается в подоболочке ... и подоболочки, похоже, не наследуют trapповедение родителя, что означает, что если вы выполните здесь какие-либо действия, которые должны быть очищены с помощью вашего кода ловушки, который выиграл ' это случилось.

Итак, вы попробуйте это:

myfunc () {
  trap mytrap EXIT
  echo "I've got a bad feeling about this..."
}

И он по-прежнему не запускается mytrapпри выходе из подоболочки. Оказывается, вам нужно явное exit, как это:

myfunc () {
  trap mytrap EXIT
  echo "I've got a bad feeling about this..."
  exit
}

С помощью приведенного выше кода, mytrapсработает соответствующим образом при выходе из subshell:

$ sh myscript 
It's a trap!
I am at the end of the script.
It's a trap!

Это ожидаемое поведение? Я был удивлен несколькими вещами здесь:

  • trap настройки не наследуются вложенными оболочками
  • неявный выход из подоболочки не вызывает EXIT ловушку
larsks
источник

Ответы:

7

trapВстроенный bash позволяет использовать ключевое слово RETURN. Отсюда и изменение:

trap mytrap EXIT

чтобы:

trap mytrap RETURN

Смотрите обсуждение trapв shell-buildins

JRFerguson
источник