В bash, какие ловушки наследуются функциями и встроенными функциями?
Я не совсем понимаю, какие ловушки наследуются, когда в bash
, На странице написано:
Когда нужно выполнить простую команду, отличную от встроенной функции или функции оболочки, она вызывается в отдельной среде выполнения [...] [T]raps, захваченные оболочкой, сбрасываются на значения, унаследованные от родителя оболочки, и ловушки игнорируется оболочкой игнорируются [.]
Позже это говорит, что подоболочки ведут себя так же.
Мне кажется, в этом есть смысл. Звучит так, как будто оболочка сбрасывает ловушку, которая запоминается любыми подоболочками и так далее, а если оболочка устанавливает ловушку, она забывается. Я не понимаю, почему был сделан этот дизайн, но я, по крайней мере, думаю, что понимаю, что происходит.
Но как насчет команд, которые являются встроенными или функциями оболочки? И ведут ли они когда-либо по-разному (в отношении наследования ловушек)? Я не могу найти исчерпывающее описание в руководстве - насколько я могу судить, все идет. Кажется, что они обычно наследуются от родителя, но есть исключения, такие как ERR
а также RETURN
каждая из которых наследуется только функциями, когда используются определенные параметры оболочки.
Мои вопросы:
Каков типичный способ наследования ловушек для встроенных функций и функций? Например, есть ли какие-то тонкости в отношении установки и отмены ловушек, как это происходит с большинством команд?
Все ли функции и встроенные функции ведут себя одинаково? (Пожалуйста, не говорите мне, что каждый встроенный имеет отдельный набор правил...)
Какие исключения? То есть, какие сигналы по умолчанию ведут себя по-разному, и какие функции могут изменять свое поведение по умолчанию в зависимости от параметров оболочки и т. Д.? Я знаю о
ERR
а такжеRETURN
а есть ли другие? Попробуйте, как я мог, я не мог найти хороший простой список этого нигде.Когда, если вообще, функция или встроенная функция могут влиять на ловушки родителя? Как
trap - SIGSPEC
противtrap '' SIGSPEC
играть в это?
Спасибо!
PS: я использую GNU bash версии "4.4.19(1)-релиз".
0 ответов
Исходный пост содержит несколько вопросов. Пытаюсь ответить на последний вопрос:When, if ever, can a function or builtin affect the traps of a parent? How does trap - SIGSPEC vs. trap '' SIGSPEC play into this?
(2 вопроса)
Когда функция может влиять на ловушки родителя?
Краткий ответ: только функции, выполняемые в том же процессе, что и родительский вызывающий объект, могут повлиять на вызывающего.
Длинный ответ: важно отметить, что сигналы относятся к "среде исполнения". В linux/Unix это процесс. Наследование происходит между процессами. Следовательно, функция может воздействовать на "родителя" (вызывающего) только в том случае, если выполняется в том же процессе. Он не сможет повлиять на "родительский", если будет выполнен в другом процессе. Примерами использования вспомогательной оболочки являются случаи, когда вспомогательная оболочка принудительно (с помощью '(command)'), при использовании конвейера (за исключением последней команды конвейера), при использовании подстановок команд и т. Д.
function f {
trap 'echo SIGNAL' TERM
}
# Will impact current process traps, as 'f' is executed in the same process
f
# Will not impact current process traps, as 'f' is executed in a sub-shell.
(f)
Разница между 'trap - SIG' и 'trap "" sig ":
Краткий ответ: "-" восстановит поведение сигнала, "" проигнорирует его. Для большинства сигналов поведение по умолчанию - завершить работу оболочки.
Длинный ответ: использование "trap - SIG" сбросит сигнал до поведения по умолчанию, тогда как "trap ""SIG" заставит сигнал игнорироваться.
Для (нескольких) сигналов поведение по умолчанию (начальное) должно игнорироваться (например, QUIT), поэтому нет разницы между командами. Для большинства других сигналов (например, QUIT) по умолчанию сигнал игнорируется. Вы можете использовать "ловушку" "SIG", чтобы предотвратить воздействие сигнала в определенный момент времени.
Например: запретить ctrl/C (INTR) при копировании критических файлов:
sleep 5
# Disable INT during copying of critical files
trap '' INT
cp -r critical-file backup
# Restore INT behavior
trap -- INT
Поскольку сигналы наследуются, поведение сигнала по умолчанию может быть изменено. Рассмотреть возможность:
# Get greeting on USR1
trap 'echo HI' USR1
# Start sub-shell
(
# USR1 will result in 'HI'
sleep 5
trap '' USR1
# USR1 will be ignored during critical file copy
cp -r critical-file backup
# Restore INT behavior
trap - INT
# USR1 will result in 'HI'
sleep 5
)
Попытка обратиться:
Каков именно типичный способ наследования ловушек для встроенных функций и функций? Например, есть ли какие-нибудь тонкости в отношении установки или снятия ловушек, как это бывает с большинством команд?
Как отмечалось выше, функции и встроенные функции не наследуют ловушки. Наследование работает над границами процесса (суб-оболочка, конвейеры, подстановка команд и т. Д.). Когда функция или встроенная команда выполняется в том же процессе, она использует ту же настройку ловушки, что и вызывающий объект - он даже может их изменять.
В руководстве Bash (раздел FUNCTIONS) следующие нажатия являются специальными для функций: DEBUG, RETURN и ERR.
Все другие аспекты среды выполнения оболочки идентичны для функции и ее вызывающей стороны за этими исключениями: ловушки DEBUG и RETURN (см. Описание встроенной ловушки в разделе ВСТРОЕННЫЕ КОМАНДЫ ОБОЛОЧКИ ниже) не наследуются, если функция не получила трассировку. (см. описание встроенной функции declare ниже) или параметр оболочки -o functrace был включен со встроенной функцией set (в этом случае все функции наследуют ловушки DEBUG и RETURN), а ловушка ERR не наследуется, если не указано -o Включена опция оболочки errtrace
builtin работает аналогичным образом, но RETURN, DEBUG не применяются к отдельным командам. ERR относится и к встроенным.
Отложенная обработка сигнала:
Стоит выделить, что большинство скриптовых движков обычно используют "отложенную обработку" для обработки сигналов. Когда сигнал получен, оболочка запомнит сигнал, установит флаг "прервать как можно скорее", а затем возобновит выполнение текущей команды. Команда попытается завершить работу как можно скорее, когда она проверит "прервать как можно скорее".
Для встроенных команд, которые выполняются очень быстро, можно завершить выполнение без проверки "прервать как можно скорее". Для функций обработчик сценариев обычно проверяет флаг "прервать как можно скорее" после завершения каждого "простого" шага.
Отложенное выполнение позволяет каждой команде выполнить обычную очистку (освободить память и другие ресурсы).
Выполнение сигнальной команды (установленной ловушкой) инициируется только после завершения текущей выполняющейся команды.